esprima 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3702 @@
1
+ /*
2
+ Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
3
+ Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
4
+ Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
5
+ Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
6
+ Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
7
+ Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
8
+ Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
9
+
10
+ Redistribution and use in source and binary forms, with or without
11
+ modification, are permitted provided that the following conditions are met:
12
+
13
+ * Redistributions of source code must retain the above copyright
14
+ notice, this list of conditions and the following disclaimer.
15
+ * Redistributions in binary form must reproduce the above copyright
16
+ notice, this list of conditions and the following disclaimer in the
17
+ documentation and/or other materials provided with the distribution.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
23
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ /*jslint bitwise:true plusplus:true */
32
+ /*global esprima:true, define:true, exports:true, window: true,
33
+ throwError: true, createLiteral: true, generateStatement: true,
34
+ parseAssignmentExpression: true, parseBlock: true, parseExpression: true,
35
+ parseFunctionDeclaration: true, parseFunctionExpression: true,
36
+ parseFunctionSourceElements: true, parseVariableIdentifier: true,
37
+ parseLeftHandSideExpression: true,
38
+ parseStatement: true, parseSourceElement: true */
39
+
40
+ (function (factory) {
41
+ 'use strict';
42
+
43
+ // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
44
+ // and plain browser loading,
45
+ if (typeof define === 'function' && define.amd) {
46
+ define(['exports'], factory);
47
+ } else if (typeof exports !== 'undefined') {
48
+ factory(exports);
49
+ } else {
50
+ factory((window.esprima = {}));
51
+ }
52
+ }(function (exports) {
53
+ 'use strict';
54
+
55
+ var Token,
56
+ TokenName,
57
+ Syntax,
58
+ PropertyKind,
59
+ Messages,
60
+ Regex,
61
+ source,
62
+ strict,
63
+ index,
64
+ lineNumber,
65
+ lineStart,
66
+ length,
67
+ buffer,
68
+ state,
69
+ extra;
70
+
71
+ Token = {
72
+ BooleanLiteral: 1,
73
+ EOF: 2,
74
+ Identifier: 3,
75
+ Keyword: 4,
76
+ NullLiteral: 5,
77
+ NumericLiteral: 6,
78
+ Punctuator: 7,
79
+ StringLiteral: 8
80
+ };
81
+
82
+ TokenName = {};
83
+ TokenName[Token.BooleanLiteral] = 'Boolean';
84
+ TokenName[Token.EOF] = '<end>';
85
+ TokenName[Token.Identifier] = 'Identifier';
86
+ TokenName[Token.Keyword] = 'Keyword';
87
+ TokenName[Token.NullLiteral] = 'Null';
88
+ TokenName[Token.NumericLiteral] = 'Numeric';
89
+ TokenName[Token.Punctuator] = 'Punctuator';
90
+ TokenName[Token.StringLiteral] = 'String';
91
+
92
+ Syntax = {
93
+ AssignmentExpression: 'AssignmentExpression',
94
+ ArrayExpression: 'ArrayExpression',
95
+ BlockStatement: 'BlockStatement',
96
+ BinaryExpression: 'BinaryExpression',
97
+ BreakStatement: 'BreakStatement',
98
+ CallExpression: 'CallExpression',
99
+ CatchClause: 'CatchClause',
100
+ ConditionalExpression: 'ConditionalExpression',
101
+ ContinueStatement: 'ContinueStatement',
102
+ DoWhileStatement: 'DoWhileStatement',
103
+ DebuggerStatement: 'DebuggerStatement',
104
+ EmptyStatement: 'EmptyStatement',
105
+ ExpressionStatement: 'ExpressionStatement',
106
+ ForStatement: 'ForStatement',
107
+ ForInStatement: 'ForInStatement',
108
+ FunctionDeclaration: 'FunctionDeclaration',
109
+ FunctionExpression: 'FunctionExpression',
110
+ Identifier: 'Identifier',
111
+ IfStatement: 'IfStatement',
112
+ Literal: 'Literal',
113
+ LabeledStatement: 'LabeledStatement',
114
+ LogicalExpression: 'LogicalExpression',
115
+ MemberExpression: 'MemberExpression',
116
+ NewExpression: 'NewExpression',
117
+ ObjectExpression: 'ObjectExpression',
118
+ Program: 'Program',
119
+ Property: 'Property',
120
+ ReturnStatement: 'ReturnStatement',
121
+ SequenceExpression: 'SequenceExpression',
122
+ SwitchStatement: 'SwitchStatement',
123
+ SwitchCase: 'SwitchCase',
124
+ ThisExpression: 'ThisExpression',
125
+ ThrowStatement: 'ThrowStatement',
126
+ TryStatement: 'TryStatement',
127
+ UnaryExpression: 'UnaryExpression',
128
+ UpdateExpression: 'UpdateExpression',
129
+ VariableDeclaration: 'VariableDeclaration',
130
+ VariableDeclarator: 'VariableDeclarator',
131
+ WhileStatement: 'WhileStatement',
132
+ WithStatement: 'WithStatement'
133
+ };
134
+
135
+ PropertyKind = {
136
+ Data: 1,
137
+ Get: 2,
138
+ Set: 4
139
+ };
140
+
141
+ // Error messages should be identical to V8.
142
+ Messages = {
143
+ UnexpectedToken: 'Unexpected token %0',
144
+ UnexpectedNumber: 'Unexpected number',
145
+ UnexpectedString: 'Unexpected string',
146
+ UnexpectedIdentifier: 'Unexpected identifier',
147
+ UnexpectedReserved: 'Unexpected reserved word',
148
+ UnexpectedEOS: 'Unexpected end of input',
149
+ NewlineAfterThrow: 'Illegal newline after throw',
150
+ InvalidRegExp: 'Invalid regular expression',
151
+ UnterminatedRegExp: 'Invalid regular expression: missing /',
152
+ InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
153
+ InvalidLHSInForIn: 'Invalid left-hand side in for-in',
154
+ MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
155
+ NoCatchOrFinally: 'Missing catch or finally after try',
156
+ UnknownLabel: 'Undefined label \'%0\'',
157
+ Redeclaration: '%0 \'%1\' has already been declared',
158
+ IllegalContinue: 'Illegal continue statement',
159
+ IllegalBreak: 'Illegal break statement',
160
+ IllegalReturn: 'Illegal return statement',
161
+ StrictModeWith: 'Strict mode code may not include a with statement',
162
+ StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
163
+ StrictVarName: 'Variable name may not be eval or arguments in strict mode',
164
+ StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
165
+ StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
166
+ StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
167
+ StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
168
+ StrictDelete: 'Delete of an unqualified identifier in strict mode.',
169
+ StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
170
+ AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
171
+ AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
172
+ StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
173
+ StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
174
+ StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
175
+ StrictReservedWord: 'Use of future reserved word in strict mode'
176
+ };
177
+
178
+ // See also tools/generate-unicode-regex.py.
179
+ Regex = {
180
+ NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'),
181
+ NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]')
182
+ };
183
+
184
+ // Ensure the condition is true, otherwise throw an error.
185
+ // This is only to have a better contract semantic, i.e. another safety net
186
+ // to catch a logic error. The condition shall be fulfilled in normal case.
187
+ // Do NOT use this to enforce a certain condition on any user input.
188
+
189
+ function assert(condition, message) {
190
+ if (!condition) {
191
+ throw new Error('ASSERT: ' + message);
192
+ }
193
+ }
194
+
195
+ function sliceSource(from, to) {
196
+ return source.slice(from, to);
197
+ }
198
+
199
+ if (typeof 'esprima'[0] === 'undefined') {
200
+ sliceSource = function sliceArraySource(from, to) {
201
+ return source.slice(from, to).join('');
202
+ };
203
+ }
204
+
205
+ function isDecimalDigit(ch) {
206
+ return '0123456789'.indexOf(ch) >= 0;
207
+ }
208
+
209
+ function isHexDigit(ch) {
210
+ return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
211
+ }
212
+
213
+ function isOctalDigit(ch) {
214
+ return '01234567'.indexOf(ch) >= 0;
215
+ }
216
+
217
+
218
+ // 7.2 White Space
219
+
220
+ function isWhiteSpace(ch) {
221
+ return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') ||
222
+ (ch === '\u000C') || (ch === '\u00A0') ||
223
+ (ch.charCodeAt(0) >= 0x1680 &&
224
+ '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0);
225
+ }
226
+
227
+ // 7.3 Line Terminators
228
+
229
+ function isLineTerminator(ch) {
230
+ return (ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029');
231
+ }
232
+
233
+ // 7.6 Identifier Names and Identifiers
234
+
235
+ function isIdentifierStart(ch) {
236
+ return (ch === '$') || (ch === '_') || (ch === '\\') ||
237
+ (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
238
+ ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch));
239
+ }
240
+
241
+ function isIdentifierPart(ch) {
242
+ return (ch === '$') || (ch === '_') || (ch === '\\') ||
243
+ (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
244
+ ((ch >= '0') && (ch <= '9')) ||
245
+ ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
246
+ }
247
+
248
+ // 7.6.1.2 Future Reserved Words
249
+
250
+ function isFutureReservedWord(id) {
251
+ switch (id) {
252
+
253
+ // Future reserved words.
254
+ case 'class':
255
+ case 'enum':
256
+ case 'export':
257
+ case 'extends':
258
+ case 'import':
259
+ case 'super':
260
+ return true;
261
+ }
262
+
263
+ return false;
264
+ }
265
+
266
+ function isStrictModeReservedWord(id) {
267
+ switch (id) {
268
+
269
+ // Strict Mode reserved words.
270
+ case 'implements':
271
+ case 'interface':
272
+ case 'package':
273
+ case 'private':
274
+ case 'protected':
275
+ case 'public':
276
+ case 'static':
277
+ case 'yield':
278
+ case 'let':
279
+ return true;
280
+ }
281
+
282
+ return false;
283
+ }
284
+
285
+ function isRestrictedWord(id) {
286
+ return id === 'eval' || id === 'arguments';
287
+ }
288
+
289
+ // 7.6.1.1 Keywords
290
+
291
+ function isKeyword(id) {
292
+ var keyword = false;
293
+ switch (id.length) {
294
+ case 2:
295
+ keyword = (id === 'if') || (id === 'in') || (id === 'do');
296
+ break;
297
+ case 3:
298
+ keyword = (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try');
299
+ break;
300
+ case 4:
301
+ keyword = (id === 'this') || (id === 'else') || (id === 'case') || (id === 'void') || (id === 'with');
302
+ break;
303
+ case 5:
304
+ keyword = (id === 'while') || (id === 'break') || (id === 'catch') || (id === 'throw');
305
+ break;
306
+ case 6:
307
+ keyword = (id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch');
308
+ break;
309
+ case 7:
310
+ keyword = (id === 'default') || (id === 'finally');
311
+ break;
312
+ case 8:
313
+ keyword = (id === 'function') || (id === 'continue') || (id === 'debugger');
314
+ break;
315
+ case 10:
316
+ keyword = (id === 'instanceof');
317
+ break;
318
+ }
319
+
320
+ if (keyword) {
321
+ return true;
322
+ }
323
+
324
+ switch (id) {
325
+ // Future reserved words.
326
+ // 'const' is specialized as Keyword in V8.
327
+ case 'const':
328
+ return true;
329
+
330
+ // For compatiblity to SpiderMonkey and ES.next
331
+ case 'yield':
332
+ case 'let':
333
+ return true;
334
+ }
335
+
336
+ if (strict && isStrictModeReservedWord(id)) {
337
+ return true;
338
+ }
339
+
340
+ return isFutureReservedWord(id);
341
+ }
342
+
343
+ // Return the next character and move forward.
344
+
345
+ function nextChar() {
346
+ return source[index++];
347
+ }
348
+
349
+ // 7.4 Comments
350
+
351
+ function skipComment() {
352
+ var ch, blockComment, lineComment;
353
+
354
+ blockComment = false;
355
+ lineComment = false;
356
+
357
+ while (index < length) {
358
+ ch = source[index];
359
+
360
+ if (lineComment) {
361
+ ch = nextChar();
362
+ if (isLineTerminator(ch)) {
363
+ lineComment = false;
364
+ if (ch === '\r' && source[index] === '\n') {
365
+ ++index;
366
+ }
367
+ ++lineNumber;
368
+ lineStart = index;
369
+ }
370
+ } else if (blockComment) {
371
+ if (isLineTerminator(ch)) {
372
+ if (ch === '\r' && source[index + 1] === '\n') {
373
+ ++index;
374
+ }
375
+ ++lineNumber;
376
+ ++index;
377
+ lineStart = index;
378
+ if (index >= length) {
379
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
380
+ }
381
+ } else {
382
+ ch = nextChar();
383
+ if (index >= length) {
384
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
385
+ }
386
+ if (ch === '*') {
387
+ ch = source[index];
388
+ if (ch === '/') {
389
+ ++index;
390
+ blockComment = false;
391
+ }
392
+ }
393
+ }
394
+ } else if (ch === '/') {
395
+ ch = source[index + 1];
396
+ if (ch === '/') {
397
+ index += 2;
398
+ lineComment = true;
399
+ } else if (ch === '*') {
400
+ index += 2;
401
+ blockComment = true;
402
+ if (index >= length) {
403
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
404
+ }
405
+ } else {
406
+ break;
407
+ }
408
+ } else if (isWhiteSpace(ch)) {
409
+ ++index;
410
+ } else if (isLineTerminator(ch)) {
411
+ ++index;
412
+ if (ch === '\r' && source[index] === '\n') {
413
+ ++index;
414
+ }
415
+ ++lineNumber;
416
+ lineStart = index;
417
+ } else {
418
+ break;
419
+ }
420
+ }
421
+ }
422
+
423
+ function scanHexEscape(prefix) {
424
+ var i, len, ch, code = 0;
425
+
426
+ len = (prefix === 'u') ? 4 : 2;
427
+ for (i = 0; i < len; ++i) {
428
+ if (index < length && isHexDigit(source[index])) {
429
+ ch = nextChar();
430
+ code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
431
+ } else {
432
+ return '';
433
+ }
434
+ }
435
+ return String.fromCharCode(code);
436
+ }
437
+
438
+ function scanIdentifier() {
439
+ var ch, start, id, restore;
440
+
441
+ ch = source[index];
442
+ if (!isIdentifierStart(ch)) {
443
+ return;
444
+ }
445
+
446
+ start = index;
447
+ if (ch === '\\') {
448
+ ++index;
449
+ if (source[index] !== 'u') {
450
+ return;
451
+ }
452
+ ++index;
453
+ restore = index;
454
+ ch = scanHexEscape('u');
455
+ if (ch) {
456
+ if (ch === '\\' || !isIdentifierStart(ch)) {
457
+ return;
458
+ }
459
+ id = ch;
460
+ } else {
461
+ index = restore;
462
+ id = 'u';
463
+ }
464
+ } else {
465
+ id = nextChar();
466
+ }
467
+
468
+ while (index < length) {
469
+ ch = source[index];
470
+ if (!isIdentifierPart(ch)) {
471
+ break;
472
+ }
473
+ if (ch === '\\') {
474
+ ++index;
475
+ if (source[index] !== 'u') {
476
+ return;
477
+ }
478
+ ++index;
479
+ restore = index;
480
+ ch = scanHexEscape('u');
481
+ if (ch) {
482
+ if (ch === '\\' || !isIdentifierPart(ch)) {
483
+ return;
484
+ }
485
+ id += ch;
486
+ } else {
487
+ index = restore;
488
+ id += 'u';
489
+ }
490
+ } else {
491
+ id += nextChar();
492
+ }
493
+ }
494
+
495
+ // There is no keyword or literal with only one character.
496
+ // Thus, it must be an identifier.
497
+ if (id.length === 1) {
498
+ return {
499
+ type: Token.Identifier,
500
+ value: id,
501
+ lineNumber: lineNumber,
502
+ lineStart: lineStart,
503
+ range: [start, index]
504
+ };
505
+ }
506
+
507
+ if (isKeyword(id)) {
508
+ return {
509
+ type: Token.Keyword,
510
+ value: id,
511
+ lineNumber: lineNumber,
512
+ lineStart: lineStart,
513
+ range: [start, index]
514
+ };
515
+ }
516
+
517
+ // 7.8.1 Null Literals
518
+
519
+ if (id === 'null') {
520
+ return {
521
+ type: Token.NullLiteral,
522
+ value: id,
523
+ lineNumber: lineNumber,
524
+ lineStart: lineStart,
525
+ range: [start, index]
526
+ };
527
+ }
528
+
529
+ // 7.8.2 Boolean Literals
530
+
531
+ if (id === 'true' || id === 'false') {
532
+ return {
533
+ type: Token.BooleanLiteral,
534
+ value: id,
535
+ lineNumber: lineNumber,
536
+ lineStart: lineStart,
537
+ range: [start, index]
538
+ };
539
+ }
540
+
541
+ return {
542
+ type: Token.Identifier,
543
+ value: id,
544
+ lineNumber: lineNumber,
545
+ lineStart: lineStart,
546
+ range: [start, index]
547
+ };
548
+ }
549
+
550
+ // 7.7 Punctuators
551
+
552
+ function scanPunctuator() {
553
+ var start = index,
554
+ ch1 = source[index],
555
+ ch2,
556
+ ch3,
557
+ ch4;
558
+
559
+ // Check for most common single-character punctuators.
560
+
561
+ if (ch1 === ';' || ch1 === '{' || ch1 === '}') {
562
+ ++index;
563
+ return {
564
+ type: Token.Punctuator,
565
+ value: ch1,
566
+ lineNumber: lineNumber,
567
+ lineStart: lineStart,
568
+ range: [start, index]
569
+ };
570
+ }
571
+
572
+ if (ch1 === ',' || ch1 === '(' || ch1 === ')') {
573
+ ++index;
574
+ return {
575
+ type: Token.Punctuator,
576
+ value: ch1,
577
+ lineNumber: lineNumber,
578
+ lineStart: lineStart,
579
+ range: [start, index]
580
+ };
581
+ }
582
+
583
+ // Dot (.) can also start a floating-point number, hence the need
584
+ // to check the next character.
585
+
586
+ ch2 = source[index + 1];
587
+ if (ch1 === '.' && !isDecimalDigit(ch2)) {
588
+ return {
589
+ type: Token.Punctuator,
590
+ value: nextChar(),
591
+ lineNumber: lineNumber,
592
+ lineStart: lineStart,
593
+ range: [start, index]
594
+ };
595
+ }
596
+
597
+ // Peek more characters.
598
+
599
+ ch3 = source[index + 2];
600
+ ch4 = source[index + 3];
601
+
602
+ // 4-character punctuator: >>>=
603
+
604
+ if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
605
+ if (ch4 === '=') {
606
+ index += 4;
607
+ return {
608
+ type: Token.Punctuator,
609
+ value: '>>>=',
610
+ lineNumber: lineNumber,
611
+ lineStart: lineStart,
612
+ range: [start, index]
613
+ };
614
+ }
615
+ }
616
+
617
+ // 3-character punctuators: === !== >>> <<= >>=
618
+
619
+ if (ch1 === '=' && ch2 === '=' && ch3 === '=') {
620
+ index += 3;
621
+ return {
622
+ type: Token.Punctuator,
623
+ value: '===',
624
+ lineNumber: lineNumber,
625
+ lineStart: lineStart,
626
+ range: [start, index]
627
+ };
628
+ }
629
+
630
+ if (ch1 === '!' && ch2 === '=' && ch3 === '=') {
631
+ index += 3;
632
+ return {
633
+ type: Token.Punctuator,
634
+ value: '!==',
635
+ lineNumber: lineNumber,
636
+ lineStart: lineStart,
637
+ range: [start, index]
638
+ };
639
+ }
640
+
641
+ if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
642
+ index += 3;
643
+ return {
644
+ type: Token.Punctuator,
645
+ value: '>>>',
646
+ lineNumber: lineNumber,
647
+ lineStart: lineStart,
648
+ range: [start, index]
649
+ };
650
+ }
651
+
652
+ if (ch1 === '<' && ch2 === '<' && ch3 === '=') {
653
+ index += 3;
654
+ return {
655
+ type: Token.Punctuator,
656
+ value: '<<=',
657
+ lineNumber: lineNumber,
658
+ lineStart: lineStart,
659
+ range: [start, index]
660
+ };
661
+ }
662
+
663
+ if (ch1 === '>' && ch2 === '>' && ch3 === '=') {
664
+ index += 3;
665
+ return {
666
+ type: Token.Punctuator,
667
+ value: '>>=',
668
+ lineNumber: lineNumber,
669
+ lineStart: lineStart,
670
+ range: [start, index]
671
+ };
672
+ }
673
+
674
+ // 2-character punctuators: <= >= == != ++ -- << >> && ||
675
+ // += -= *= %= &= |= ^= /=
676
+
677
+ if (ch2 === '=') {
678
+ if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
679
+ index += 2;
680
+ return {
681
+ type: Token.Punctuator,
682
+ value: ch1 + ch2,
683
+ lineNumber: lineNumber,
684
+ lineStart: lineStart,
685
+ range: [start, index]
686
+ };
687
+ }
688
+ }
689
+
690
+ if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) {
691
+ if ('+-<>&|'.indexOf(ch2) >= 0) {
692
+ index += 2;
693
+ return {
694
+ type: Token.Punctuator,
695
+ value: ch1 + ch2,
696
+ lineNumber: lineNumber,
697
+ lineStart: lineStart,
698
+ range: [start, index]
699
+ };
700
+ }
701
+ }
702
+
703
+ // The remaining 1-character punctuators.
704
+
705
+ if ('[]<>+-*%&|^!~?:=/'.indexOf(ch1) >= 0) {
706
+ return {
707
+ type: Token.Punctuator,
708
+ value: nextChar(),
709
+ lineNumber: lineNumber,
710
+ lineStart: lineStart,
711
+ range: [start, index]
712
+ };
713
+ }
714
+ }
715
+
716
+ // 7.8.3 Numeric Literals
717
+
718
+ function scanNumericLiteral() {
719
+ var number, start, ch;
720
+
721
+ ch = source[index];
722
+ assert(isDecimalDigit(ch) || (ch === '.'),
723
+ 'Numeric literal must start with a decimal digit or a decimal point');
724
+
725
+ start = index;
726
+ number = '';
727
+ if (ch !== '.') {
728
+ number = nextChar();
729
+ ch = source[index];
730
+
731
+ // Hex number starts with '0x'.
732
+ // Octal number starts with '0'.
733
+ if (number === '0') {
734
+ if (ch === 'x' || ch === 'X') {
735
+ number += nextChar();
736
+ while (index < length) {
737
+ ch = source[index];
738
+ if (!isHexDigit(ch)) {
739
+ break;
740
+ }
741
+ number += nextChar();
742
+ }
743
+
744
+ if (number.length <= 2) {
745
+ // only 0x
746
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
747
+ }
748
+
749
+ if (index < length) {
750
+ ch = source[index];
751
+ if (isIdentifierStart(ch)) {
752
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
753
+ }
754
+ }
755
+ return {
756
+ type: Token.NumericLiteral,
757
+ value: parseInt(number, 16),
758
+ lineNumber: lineNumber,
759
+ lineStart: lineStart,
760
+ range: [start, index]
761
+ };
762
+ } else if (isOctalDigit(ch)) {
763
+ number += nextChar();
764
+ while (index < length) {
765
+ ch = source[index];
766
+ if (!isOctalDigit(ch)) {
767
+ break;
768
+ }
769
+ number += nextChar();
770
+ }
771
+
772
+ if (index < length) {
773
+ ch = source[index];
774
+ if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
775
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
776
+ }
777
+ }
778
+ return {
779
+ type: Token.NumericLiteral,
780
+ value: parseInt(number, 8),
781
+ octal: true,
782
+ lineNumber: lineNumber,
783
+ lineStart: lineStart,
784
+ range: [start, index]
785
+ };
786
+ }
787
+
788
+ // decimal number starts with '0' such as '09' is illegal.
789
+ if (isDecimalDigit(ch)) {
790
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
791
+ }
792
+ }
793
+
794
+ while (index < length) {
795
+ ch = source[index];
796
+ if (!isDecimalDigit(ch)) {
797
+ break;
798
+ }
799
+ number += nextChar();
800
+ }
801
+ }
802
+
803
+ if (ch === '.') {
804
+ number += nextChar();
805
+ while (index < length) {
806
+ ch = source[index];
807
+ if (!isDecimalDigit(ch)) {
808
+ break;
809
+ }
810
+ number += nextChar();
811
+ }
812
+ }
813
+
814
+ if (ch === 'e' || ch === 'E') {
815
+ number += nextChar();
816
+
817
+ ch = source[index];
818
+ if (ch === '+' || ch === '-') {
819
+ number += nextChar();
820
+ }
821
+
822
+ ch = source[index];
823
+ if (isDecimalDigit(ch)) {
824
+ number += nextChar();
825
+ while (index < length) {
826
+ ch = source[index];
827
+ if (!isDecimalDigit(ch)) {
828
+ break;
829
+ }
830
+ number += nextChar();
831
+ }
832
+ } else {
833
+ ch = 'character ' + ch;
834
+ if (index >= length) {
835
+ ch = '<end>';
836
+ }
837
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
838
+ }
839
+ }
840
+
841
+ if (index < length) {
842
+ ch = source[index];
843
+ if (isIdentifierStart(ch)) {
844
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
845
+ }
846
+ }
847
+
848
+ return {
849
+ type: Token.NumericLiteral,
850
+ value: parseFloat(number),
851
+ lineNumber: lineNumber,
852
+ lineStart: lineStart,
853
+ range: [start, index]
854
+ };
855
+ }
856
+
857
+ // 7.8.4 String Literals
858
+
859
+ function scanStringLiteral() {
860
+ var str = '', quote, start, ch, code, unescaped, restore, octal = false;
861
+
862
+ quote = source[index];
863
+ assert((quote === '\'' || quote === '"'),
864
+ 'String literal must starts with a quote');
865
+
866
+ start = index;
867
+ ++index;
868
+
869
+ while (index < length) {
870
+ ch = nextChar();
871
+
872
+ if (ch === quote) {
873
+ quote = '';
874
+ break;
875
+ } else if (ch === '\\') {
876
+ ch = nextChar();
877
+ if (!isLineTerminator(ch)) {
878
+ switch (ch) {
879
+ case 'n':
880
+ str += '\n';
881
+ break;
882
+ case 'r':
883
+ str += '\r';
884
+ break;
885
+ case 't':
886
+ str += '\t';
887
+ break;
888
+ case 'u':
889
+ case 'x':
890
+ restore = index;
891
+ unescaped = scanHexEscape(ch);
892
+ if (unescaped) {
893
+ str += unescaped;
894
+ } else {
895
+ index = restore;
896
+ str += ch;
897
+ }
898
+ break;
899
+ case 'b':
900
+ str += '\b';
901
+ break;
902
+ case 'f':
903
+ str += '\f';
904
+ break;
905
+ case 'v':
906
+ str += '\v';
907
+ break;
908
+
909
+ default:
910
+ if (isOctalDigit(ch)) {
911
+ code = '01234567'.indexOf(ch);
912
+
913
+ // \0 is not octal escape sequence
914
+ if (code !== 0) {
915
+ octal = true;
916
+ }
917
+
918
+ if (index < length && isOctalDigit(source[index])) {
919
+ octal = true;
920
+ code = code * 8 + '01234567'.indexOf(nextChar());
921
+
922
+ // 3 digits are only allowed when string starts
923
+ // with 0, 1, 2, 3
924
+ if ('0123'.indexOf(ch) >= 0 &&
925
+ index < length &&
926
+ isOctalDigit(source[index])) {
927
+ code = code * 8 + '01234567'.indexOf(nextChar());
928
+ }
929
+ }
930
+ str += String.fromCharCode(code);
931
+ } else {
932
+ str += ch;
933
+ }
934
+ break;
935
+ }
936
+ } else {
937
+ ++lineNumber;
938
+ if (ch === '\r' && source[index] === '\n') {
939
+ ++index;
940
+ }
941
+ }
942
+ } else if (isLineTerminator(ch)) {
943
+ break;
944
+ } else {
945
+ str += ch;
946
+ }
947
+ }
948
+
949
+ if (quote !== '') {
950
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
951
+ }
952
+
953
+ return {
954
+ type: Token.StringLiteral,
955
+ value: str,
956
+ octal: octal,
957
+ lineNumber: lineNumber,
958
+ lineStart: lineStart,
959
+ range: [start, index]
960
+ };
961
+ }
962
+
963
+ function scanRegExp() {
964
+ var str = '', ch, start, pattern, flags, value, classMarker = false, restore, terminated = false;
965
+
966
+ buffer = null;
967
+ skipComment();
968
+
969
+ start = index;
970
+ ch = source[index];
971
+ assert(ch === '/', 'Regular expression literal must start with a slash');
972
+ str = nextChar();
973
+
974
+ while (index < length) {
975
+ ch = nextChar();
976
+ str += ch;
977
+ if (classMarker) {
978
+ if (ch === ']') {
979
+ classMarker = false;
980
+ }
981
+ } else {
982
+ if (ch === '\\') {
983
+ ch = nextChar();
984
+ // ECMA-262 7.8.5
985
+ if (isLineTerminator(ch)) {
986
+ throwError({}, Messages.UnterminatedRegExp);
987
+ }
988
+ str += ch;
989
+ } else if (ch === '/') {
990
+ terminated = true;
991
+ break;
992
+ } else if (ch === '[') {
993
+ classMarker = true;
994
+ } else if (isLineTerminator(ch)) {
995
+ throwError({}, Messages.UnterminatedRegExp);
996
+ }
997
+ }
998
+ }
999
+
1000
+ if (!terminated) {
1001
+ throwError({}, Messages.UnterminatedRegExp);
1002
+ }
1003
+
1004
+ // Exclude leading and trailing slash.
1005
+ pattern = str.substr(1, str.length - 2);
1006
+
1007
+ flags = '';
1008
+ while (index < length) {
1009
+ ch = source[index];
1010
+ if (!isIdentifierPart(ch)) {
1011
+ break;
1012
+ }
1013
+
1014
+ ++index;
1015
+ if (ch === '\\' && index < length) {
1016
+ ch = source[index];
1017
+ if (ch === 'u') {
1018
+ ++index;
1019
+ restore = index;
1020
+ ch = scanHexEscape('u');
1021
+ if (ch) {
1022
+ flags += ch;
1023
+ str += '\\u';
1024
+ for (; restore < index; ++restore) {
1025
+ str += source[restore];
1026
+ }
1027
+ } else {
1028
+ index = restore;
1029
+ flags += 'u';
1030
+ str += '\\u';
1031
+ }
1032
+ } else {
1033
+ str += '\\';
1034
+ }
1035
+ } else {
1036
+ flags += ch;
1037
+ str += ch;
1038
+ }
1039
+ }
1040
+
1041
+ try {
1042
+ value = new RegExp(pattern, flags);
1043
+ } catch (e) {
1044
+ throwError({}, Messages.InvalidRegExp);
1045
+ }
1046
+
1047
+ return {
1048
+ literal: str,
1049
+ value: value,
1050
+ range: [start, index]
1051
+ };
1052
+ }
1053
+
1054
+ function isIdentifierName(token) {
1055
+ return token.type === Token.Identifier ||
1056
+ token.type === Token.Keyword ||
1057
+ token.type === Token.BooleanLiteral ||
1058
+ token.type === Token.NullLiteral;
1059
+ }
1060
+
1061
+ function advance() {
1062
+ var ch, token;
1063
+
1064
+ skipComment();
1065
+
1066
+ if (index >= length) {
1067
+ return {
1068
+ type: Token.EOF,
1069
+ lineNumber: lineNumber,
1070
+ lineStart: lineStart,
1071
+ range: [index, index]
1072
+ };
1073
+ }
1074
+
1075
+ token = scanPunctuator();
1076
+ if (typeof token !== 'undefined') {
1077
+ return token;
1078
+ }
1079
+
1080
+ ch = source[index];
1081
+
1082
+ if (ch === '\'' || ch === '"') {
1083
+ return scanStringLiteral();
1084
+ }
1085
+
1086
+ if (ch === '.' || isDecimalDigit(ch)) {
1087
+ return scanNumericLiteral();
1088
+ }
1089
+
1090
+ token = scanIdentifier();
1091
+ if (typeof token !== 'undefined') {
1092
+ return token;
1093
+ }
1094
+
1095
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1096
+ }
1097
+
1098
+ function lex() {
1099
+ var token;
1100
+
1101
+ if (buffer) {
1102
+ index = buffer.range[1];
1103
+ lineNumber = buffer.lineNumber;
1104
+ lineStart = buffer.lineStart;
1105
+ token = buffer;
1106
+ buffer = null;
1107
+ return token;
1108
+ }
1109
+
1110
+ buffer = null;
1111
+ return advance();
1112
+ }
1113
+
1114
+ function lookahead() {
1115
+ var pos, line, start;
1116
+
1117
+ if (buffer !== null) {
1118
+ return buffer;
1119
+ }
1120
+
1121
+ pos = index;
1122
+ line = lineNumber;
1123
+ start = lineStart;
1124
+ buffer = advance();
1125
+ index = pos;
1126
+ lineNumber = line;
1127
+ lineStart = start;
1128
+
1129
+ return buffer;
1130
+ }
1131
+
1132
+ // Return true if there is a line terminator before the next token.
1133
+
1134
+ function peekLineTerminator() {
1135
+ var pos, line, start, found;
1136
+
1137
+ pos = index;
1138
+ line = lineNumber;
1139
+ start = lineStart;
1140
+ skipComment();
1141
+ found = lineNumber !== line;
1142
+ index = pos;
1143
+ lineNumber = line;
1144
+ lineStart = start;
1145
+
1146
+ return found;
1147
+ }
1148
+
1149
+ // Throw an exception
1150
+
1151
+ function throwError(token, messageFormat) {
1152
+ var error,
1153
+ args = Array.prototype.slice.call(arguments, 2),
1154
+ msg = messageFormat.replace(
1155
+ /%(\d)/g,
1156
+ function (whole, index) {
1157
+ return args[index] || '';
1158
+ }
1159
+ );
1160
+
1161
+ if (typeof token.lineNumber === 'number') {
1162
+ error = new Error('Line ' + token.lineNumber + ': ' + msg);
1163
+ error.index = token.range[0];
1164
+ error.lineNumber = token.lineNumber;
1165
+ error.column = token.range[0] - lineStart + 1;
1166
+ } else {
1167
+ error = new Error('Line ' + lineNumber + ': ' + msg);
1168
+ error.index = index;
1169
+ error.lineNumber = lineNumber;
1170
+ error.column = index - lineStart + 1;
1171
+ }
1172
+
1173
+ throw error;
1174
+ }
1175
+
1176
+ function throwErrorTolerant() {
1177
+ try {
1178
+ throwError.apply(null, arguments);
1179
+ } catch (e) {
1180
+ if (extra.errors) {
1181
+ extra.errors.push(e);
1182
+ } else {
1183
+ throw e;
1184
+ }
1185
+ }
1186
+ }
1187
+
1188
+
1189
+ // Throw an exception because of the token.
1190
+
1191
+ function throwUnexpected(token) {
1192
+ if (token.type === Token.EOF) {
1193
+ throwError(token, Messages.UnexpectedEOS);
1194
+ }
1195
+
1196
+ if (token.type === Token.NumericLiteral) {
1197
+ throwError(token, Messages.UnexpectedNumber);
1198
+ }
1199
+
1200
+ if (token.type === Token.StringLiteral) {
1201
+ throwError(token, Messages.UnexpectedString);
1202
+ }
1203
+
1204
+ if (token.type === Token.Identifier) {
1205
+ throwError(token, Messages.UnexpectedIdentifier);
1206
+ }
1207
+
1208
+ if (token.type === Token.Keyword) {
1209
+ if (isFutureReservedWord(token.value)) {
1210
+ throwError(token, Messages.UnexpectedReserved);
1211
+ } else if (strict && isStrictModeReservedWord(token.value)) {
1212
+ throwError(token, Messages.StrictReservedWord);
1213
+ }
1214
+ throwError(token, Messages.UnexpectedToken, token.value);
1215
+ }
1216
+
1217
+ // BooleanLiteral, NullLiteral, or Punctuator.
1218
+ throwError(token, Messages.UnexpectedToken, token.value);
1219
+ }
1220
+
1221
+ // Expect the next token to match the specified punctuator.
1222
+ // If not, an exception will be thrown.
1223
+
1224
+ function expect(value) {
1225
+ var token = lex();
1226
+ if (token.type !== Token.Punctuator || token.value !== value) {
1227
+ throwUnexpected(token);
1228
+ }
1229
+ }
1230
+
1231
+ // Expect the next token to match the specified keyword.
1232
+ // If not, an exception will be thrown.
1233
+
1234
+ function expectKeyword(keyword) {
1235
+ var token = lex();
1236
+ if (token.type !== Token.Keyword || token.value !== keyword) {
1237
+ throwUnexpected(token);
1238
+ }
1239
+ }
1240
+
1241
+ // Return true if the next token matches the specified punctuator.
1242
+
1243
+ function match(value) {
1244
+ var token = lookahead();
1245
+ return token.type === Token.Punctuator && token.value === value;
1246
+ }
1247
+
1248
+ // Return true if the next token matches the specified keyword
1249
+
1250
+ function matchKeyword(keyword) {
1251
+ var token = lookahead();
1252
+ return token.type === Token.Keyword && token.value === keyword;
1253
+ }
1254
+
1255
+ // Return true if the next token is an assignment operator
1256
+
1257
+ function matchAssign() {
1258
+ var token = lookahead(),
1259
+ op = token.value;
1260
+
1261
+ if (token.type !== Token.Punctuator) {
1262
+ return false;
1263
+ }
1264
+ return op === '=' ||
1265
+ op === '*=' ||
1266
+ op === '/=' ||
1267
+ op === '%=' ||
1268
+ op === '+=' ||
1269
+ op === '-=' ||
1270
+ op === '<<=' ||
1271
+ op === '>>=' ||
1272
+ op === '>>>=' ||
1273
+ op === '&=' ||
1274
+ op === '^=' ||
1275
+ op === '|=';
1276
+ }
1277
+
1278
+ function consumeSemicolon() {
1279
+ var token, line;
1280
+
1281
+ // Catch the very common case first.
1282
+ if (source[index] === ';') {
1283
+ lex();
1284
+ return;
1285
+ }
1286
+
1287
+ line = lineNumber;
1288
+ skipComment();
1289
+ if (lineNumber !== line) {
1290
+ return;
1291
+ }
1292
+
1293
+ if (match(';')) {
1294
+ lex();
1295
+ return;
1296
+ }
1297
+
1298
+ token = lookahead();
1299
+ if (token.type !== Token.EOF && !match('}')) {
1300
+ throwUnexpected(token);
1301
+ }
1302
+ return;
1303
+ }
1304
+
1305
+ // Return true if provided expression is LeftHandSideExpression
1306
+
1307
+ function isLeftHandSide(expr) {
1308
+ return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
1309
+ }
1310
+
1311
+ // 11.1.4 Array Initialiser
1312
+
1313
+ function parseArrayInitialiser() {
1314
+ var elements = [];
1315
+
1316
+ expect('[');
1317
+
1318
+ while (!match(']')) {
1319
+ if (match(',')) {
1320
+ lex();
1321
+ elements.push(null);
1322
+ } else {
1323
+ elements.push(parseAssignmentExpression());
1324
+
1325
+ if (!match(']')) {
1326
+ expect(',');
1327
+ }
1328
+ }
1329
+ }
1330
+
1331
+ expect(']');
1332
+
1333
+ return {
1334
+ type: Syntax.ArrayExpression,
1335
+ elements: elements
1336
+ };
1337
+ }
1338
+
1339
+ // 11.1.5 Object Initialiser
1340
+
1341
+ function parsePropertyFunction(param, first) {
1342
+ var previousStrict, body;
1343
+
1344
+ previousStrict = strict;
1345
+ body = parseFunctionSourceElements();
1346
+ if (first && strict && isRestrictedWord(param[0].name)) {
1347
+ throwError(first, Messages.StrictParamName);
1348
+ }
1349
+ strict = previousStrict;
1350
+
1351
+ return {
1352
+ type: Syntax.FunctionExpression,
1353
+ id: null,
1354
+ params: param,
1355
+ defaults: [],
1356
+ body: body,
1357
+ rest: null,
1358
+ generator: false,
1359
+ expression: false
1360
+ };
1361
+ }
1362
+
1363
+ function parseObjectPropertyKey() {
1364
+ var token = lex();
1365
+
1366
+ // Note: This function is called only from parseObjectProperty(), where
1367
+ // EOF and Punctuator tokens are already filtered out.
1368
+
1369
+ if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
1370
+ if (strict && token.octal) {
1371
+ throwError(token, Messages.StrictOctalLiteral);
1372
+ }
1373
+ return createLiteral(token);
1374
+ }
1375
+
1376
+ return {
1377
+ type: Syntax.Identifier,
1378
+ name: token.value
1379
+ };
1380
+ }
1381
+
1382
+ function parseObjectProperty() {
1383
+ var token, key, id, param;
1384
+
1385
+ token = lookahead();
1386
+
1387
+ if (token.type === Token.Identifier) {
1388
+
1389
+ id = parseObjectPropertyKey();
1390
+
1391
+ // Property Assignment: Getter and Setter.
1392
+
1393
+ if (token.value === 'get' && !match(':')) {
1394
+ key = parseObjectPropertyKey();
1395
+ expect('(');
1396
+ expect(')');
1397
+ return {
1398
+ type: Syntax.Property,
1399
+ key: key,
1400
+ value: parsePropertyFunction([]),
1401
+ kind: 'get'
1402
+ };
1403
+ } else if (token.value === 'set' && !match(':')) {
1404
+ key = parseObjectPropertyKey();
1405
+ expect('(');
1406
+ token = lookahead();
1407
+ if (token.type !== Token.Identifier) {
1408
+ throwUnexpected(lex());
1409
+ }
1410
+ param = [ parseVariableIdentifier() ];
1411
+ expect(')');
1412
+ return {
1413
+ type: Syntax.Property,
1414
+ key: key,
1415
+ value: parsePropertyFunction(param, token),
1416
+ kind: 'set'
1417
+ };
1418
+ } else {
1419
+ expect(':');
1420
+ return {
1421
+ type: Syntax.Property,
1422
+ key: id,
1423
+ value: parseAssignmentExpression(),
1424
+ kind: 'init'
1425
+ };
1426
+ }
1427
+ } else if (token.type === Token.EOF || token.type === Token.Punctuator) {
1428
+ throwUnexpected(token);
1429
+ } else {
1430
+ key = parseObjectPropertyKey();
1431
+ expect(':');
1432
+ return {
1433
+ type: Syntax.Property,
1434
+ key: key,
1435
+ value: parseAssignmentExpression(),
1436
+ kind: 'init'
1437
+ };
1438
+ }
1439
+ }
1440
+
1441
+ function parseObjectInitialiser() {
1442
+ var properties = [], property, name, kind, map = {}, toString = String;
1443
+
1444
+ expect('{');
1445
+
1446
+ while (!match('}')) {
1447
+ property = parseObjectProperty();
1448
+
1449
+ if (property.key.type === Syntax.Identifier) {
1450
+ name = property.key.name;
1451
+ } else {
1452
+ name = toString(property.key.value);
1453
+ }
1454
+ kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
1455
+ if (Object.prototype.hasOwnProperty.call(map, name)) {
1456
+ if (map[name] === PropertyKind.Data) {
1457
+ if (strict && kind === PropertyKind.Data) {
1458
+ throwErrorTolerant({}, Messages.StrictDuplicateProperty);
1459
+ } else if (kind !== PropertyKind.Data) {
1460
+ throwError({}, Messages.AccessorDataProperty);
1461
+ }
1462
+ } else {
1463
+ if (kind === PropertyKind.Data) {
1464
+ throwError({}, Messages.AccessorDataProperty);
1465
+ } else if (map[name] & kind) {
1466
+ throwError({}, Messages.AccessorGetSet);
1467
+ }
1468
+ }
1469
+ map[name] |= kind;
1470
+ } else {
1471
+ map[name] = kind;
1472
+ }
1473
+
1474
+ properties.push(property);
1475
+
1476
+ if (!match('}')) {
1477
+ expect(',');
1478
+ }
1479
+ }
1480
+
1481
+ expect('}');
1482
+
1483
+ return {
1484
+ type: Syntax.ObjectExpression,
1485
+ properties: properties
1486
+ };
1487
+ }
1488
+
1489
+ // 11.1 Primary Expressions
1490
+
1491
+ function parsePrimaryExpression() {
1492
+ var expr,
1493
+ token = lookahead(),
1494
+ type = token.type;
1495
+
1496
+ if (type === Token.Identifier) {
1497
+ return {
1498
+ type: Syntax.Identifier,
1499
+ name: lex().value
1500
+ };
1501
+ }
1502
+
1503
+ if (type === Token.StringLiteral || type === Token.NumericLiteral) {
1504
+ if (strict && token.octal) {
1505
+ throwErrorTolerant(token, Messages.StrictOctalLiteral);
1506
+ }
1507
+ return createLiteral(lex());
1508
+ }
1509
+
1510
+ if (type === Token.Keyword) {
1511
+ if (matchKeyword('this')) {
1512
+ lex();
1513
+ return {
1514
+ type: Syntax.ThisExpression
1515
+ };
1516
+ }
1517
+
1518
+ if (matchKeyword('function')) {
1519
+ return parseFunctionExpression();
1520
+ }
1521
+ }
1522
+
1523
+ if (type === Token.BooleanLiteral) {
1524
+ lex();
1525
+ token.value = (token.value === 'true');
1526
+ return createLiteral(token);
1527
+ }
1528
+
1529
+ if (type === Token.NullLiteral) {
1530
+ lex();
1531
+ token.value = null;
1532
+ return createLiteral(token);
1533
+ }
1534
+
1535
+ if (match('[')) {
1536
+ return parseArrayInitialiser();
1537
+ }
1538
+
1539
+ if (match('{')) {
1540
+ return parseObjectInitialiser();
1541
+ }
1542
+
1543
+ if (match('(')) {
1544
+ lex();
1545
+ state.lastParenthesized = expr = parseExpression();
1546
+ expect(')');
1547
+ return expr;
1548
+ }
1549
+
1550
+ if (match('/') || match('/=')) {
1551
+ return createLiteral(scanRegExp());
1552
+ }
1553
+
1554
+ return throwUnexpected(lex());
1555
+ }
1556
+
1557
+ // 11.2 Left-Hand-Side Expressions
1558
+
1559
+ function parseArguments() {
1560
+ var args = [];
1561
+
1562
+ expect('(');
1563
+
1564
+ if (!match(')')) {
1565
+ while (index < length) {
1566
+ args.push(parseAssignmentExpression());
1567
+ if (match(')')) {
1568
+ break;
1569
+ }
1570
+ expect(',');
1571
+ }
1572
+ }
1573
+
1574
+ expect(')');
1575
+
1576
+ return args;
1577
+ }
1578
+
1579
+ function parseNonComputedProperty() {
1580
+ var token = lex();
1581
+
1582
+ if (!isIdentifierName(token)) {
1583
+ throwUnexpected(token);
1584
+ }
1585
+
1586
+ return {
1587
+ type: Syntax.Identifier,
1588
+ name: token.value
1589
+ };
1590
+ }
1591
+
1592
+ function parseNonComputedMember(object) {
1593
+ return {
1594
+ type: Syntax.MemberExpression,
1595
+ computed: false,
1596
+ object: object,
1597
+ property: parseNonComputedProperty()
1598
+ };
1599
+ }
1600
+
1601
+ function parseComputedMember(object) {
1602
+ var property, expr;
1603
+
1604
+ expect('[');
1605
+ property = parseExpression();
1606
+ expr = {
1607
+ type: Syntax.MemberExpression,
1608
+ computed: true,
1609
+ object: object,
1610
+ property: property
1611
+ };
1612
+ expect(']');
1613
+ return expr;
1614
+ }
1615
+
1616
+ function parseCallMember(object) {
1617
+ return {
1618
+ type: Syntax.CallExpression,
1619
+ callee: object,
1620
+ 'arguments': parseArguments()
1621
+ };
1622
+ }
1623
+
1624
+ function parseNewExpression() {
1625
+ var expr;
1626
+
1627
+ expectKeyword('new');
1628
+
1629
+ expr = {
1630
+ type: Syntax.NewExpression,
1631
+ callee: parseLeftHandSideExpression(),
1632
+ 'arguments': []
1633
+ };
1634
+
1635
+ if (match('(')) {
1636
+ expr['arguments'] = parseArguments();
1637
+ }
1638
+
1639
+ return expr;
1640
+ }
1641
+
1642
+ function parseLeftHandSideExpressionAllowCall() {
1643
+ var useNew, expr;
1644
+
1645
+ useNew = matchKeyword('new');
1646
+ expr = useNew ? parseNewExpression() : parsePrimaryExpression();
1647
+
1648
+ while (index < length) {
1649
+ if (match('.')) {
1650
+ lex();
1651
+ expr = parseNonComputedMember(expr);
1652
+ } else if (match('[')) {
1653
+ expr = parseComputedMember(expr);
1654
+ } else if (match('(')) {
1655
+ expr = parseCallMember(expr);
1656
+ } else {
1657
+ break;
1658
+ }
1659
+ }
1660
+
1661
+ return expr;
1662
+ }
1663
+
1664
+ function parseLeftHandSideExpression() {
1665
+ var useNew, expr;
1666
+
1667
+ useNew = matchKeyword('new');
1668
+ expr = useNew ? parseNewExpression() : parsePrimaryExpression();
1669
+
1670
+ while (index < length) {
1671
+ if (match('.')) {
1672
+ lex();
1673
+ expr = parseNonComputedMember(expr);
1674
+ } else if (match('[')) {
1675
+ expr = parseComputedMember(expr);
1676
+ } else {
1677
+ break;
1678
+ }
1679
+ }
1680
+
1681
+ return expr;
1682
+ }
1683
+
1684
+ // 11.3 Postfix Expressions
1685
+
1686
+ function parsePostfixExpression() {
1687
+ var expr = parseLeftHandSideExpressionAllowCall();
1688
+
1689
+ if ((match('++') || match('--')) && !peekLineTerminator()) {
1690
+ // 11.3.1, 11.3.2
1691
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
1692
+ throwError({}, Messages.StrictLHSPostfix);
1693
+ }
1694
+
1695
+ if (!isLeftHandSide(expr)) {
1696
+ throwError({}, Messages.InvalidLHSInAssignment);
1697
+ }
1698
+
1699
+ expr = {
1700
+ type: Syntax.UpdateExpression,
1701
+ operator: lex().value,
1702
+ argument: expr,
1703
+ prefix: false
1704
+ };
1705
+ }
1706
+
1707
+ return expr;
1708
+ }
1709
+
1710
+ // 11.4 Unary Operators
1711
+
1712
+ function parseUnaryExpression() {
1713
+ var token, expr;
1714
+
1715
+ if (match('++') || match('--')) {
1716
+ token = lex();
1717
+ expr = parseUnaryExpression();
1718
+ // 11.4.4, 11.4.5
1719
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
1720
+ throwError({}, Messages.StrictLHSPrefix);
1721
+ }
1722
+
1723
+ if (!isLeftHandSide(expr)) {
1724
+ throwError({}, Messages.InvalidLHSInAssignment);
1725
+ }
1726
+
1727
+ expr = {
1728
+ type: Syntax.UpdateExpression,
1729
+ operator: token.value,
1730
+ argument: expr,
1731
+ prefix: true
1732
+ };
1733
+ return expr;
1734
+ }
1735
+
1736
+ if (match('+') || match('-') || match('~') || match('!')) {
1737
+ expr = {
1738
+ type: Syntax.UnaryExpression,
1739
+ operator: lex().value,
1740
+ argument: parseUnaryExpression()
1741
+ };
1742
+ return expr;
1743
+ }
1744
+
1745
+ if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
1746
+ expr = {
1747
+ type: Syntax.UnaryExpression,
1748
+ operator: lex().value,
1749
+ argument: parseUnaryExpression()
1750
+ };
1751
+ if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
1752
+ throwErrorTolerant({}, Messages.StrictDelete);
1753
+ }
1754
+ return expr;
1755
+ }
1756
+
1757
+ return parsePostfixExpression();
1758
+ }
1759
+
1760
+ // 11.5 Multiplicative Operators
1761
+
1762
+ function parseMultiplicativeExpression() {
1763
+ var expr = parseUnaryExpression();
1764
+
1765
+ while (match('*') || match('/') || match('%')) {
1766
+ expr = {
1767
+ type: Syntax.BinaryExpression,
1768
+ operator: lex().value,
1769
+ left: expr,
1770
+ right: parseUnaryExpression()
1771
+ };
1772
+ }
1773
+
1774
+ return expr;
1775
+ }
1776
+
1777
+ // 11.6 Additive Operators
1778
+
1779
+ function parseAdditiveExpression() {
1780
+ var expr = parseMultiplicativeExpression();
1781
+
1782
+ while (match('+') || match('-')) {
1783
+ expr = {
1784
+ type: Syntax.BinaryExpression,
1785
+ operator: lex().value,
1786
+ left: expr,
1787
+ right: parseMultiplicativeExpression()
1788
+ };
1789
+ }
1790
+
1791
+ return expr;
1792
+ }
1793
+
1794
+ // 11.7 Bitwise Shift Operators
1795
+
1796
+ function parseShiftExpression() {
1797
+ var expr = parseAdditiveExpression();
1798
+
1799
+ while (match('<<') || match('>>') || match('>>>')) {
1800
+ expr = {
1801
+ type: Syntax.BinaryExpression,
1802
+ operator: lex().value,
1803
+ left: expr,
1804
+ right: parseAdditiveExpression()
1805
+ };
1806
+ }
1807
+
1808
+ return expr;
1809
+ }
1810
+ // 11.8 Relational Operators
1811
+
1812
+ function parseRelationalExpression() {
1813
+ var expr, previousAllowIn;
1814
+
1815
+ previousAllowIn = state.allowIn;
1816
+ state.allowIn = true;
1817
+
1818
+ expr = parseShiftExpression();
1819
+
1820
+ while (match('<') || match('>') || match('<=') || match('>=') || (previousAllowIn && matchKeyword('in')) || matchKeyword('instanceof')) {
1821
+ expr = {
1822
+ type: Syntax.BinaryExpression,
1823
+ operator: lex().value,
1824
+ left: expr,
1825
+ right: parseShiftExpression()
1826
+ };
1827
+ }
1828
+
1829
+ state.allowIn = previousAllowIn;
1830
+ return expr;
1831
+ }
1832
+
1833
+ // 11.9 Equality Operators
1834
+
1835
+ function parseEqualityExpression() {
1836
+ var expr = parseRelationalExpression();
1837
+
1838
+ while (match('==') || match('!=') || match('===') || match('!==')) {
1839
+ expr = {
1840
+ type: Syntax.BinaryExpression,
1841
+ operator: lex().value,
1842
+ left: expr,
1843
+ right: parseRelationalExpression()
1844
+ };
1845
+ }
1846
+
1847
+ return expr;
1848
+ }
1849
+
1850
+ // 11.10 Binary Bitwise Operators
1851
+
1852
+ function parseBitwiseANDExpression() {
1853
+ var expr = parseEqualityExpression();
1854
+
1855
+ while (match('&')) {
1856
+ lex();
1857
+ expr = {
1858
+ type: Syntax.BinaryExpression,
1859
+ operator: '&',
1860
+ left: expr,
1861
+ right: parseEqualityExpression()
1862
+ };
1863
+ }
1864
+
1865
+ return expr;
1866
+ }
1867
+
1868
+ function parseBitwiseXORExpression() {
1869
+ var expr = parseBitwiseANDExpression();
1870
+
1871
+ while (match('^')) {
1872
+ lex();
1873
+ expr = {
1874
+ type: Syntax.BinaryExpression,
1875
+ operator: '^',
1876
+ left: expr,
1877
+ right: parseBitwiseANDExpression()
1878
+ };
1879
+ }
1880
+
1881
+ return expr;
1882
+ }
1883
+
1884
+ function parseBitwiseORExpression() {
1885
+ var expr = parseBitwiseXORExpression();
1886
+
1887
+ while (match('|')) {
1888
+ lex();
1889
+ expr = {
1890
+ type: Syntax.BinaryExpression,
1891
+ operator: '|',
1892
+ left: expr,
1893
+ right: parseBitwiseXORExpression()
1894
+ };
1895
+ }
1896
+
1897
+ return expr;
1898
+ }
1899
+
1900
+ // 11.11 Binary Logical Operators
1901
+
1902
+ function parseLogicalANDExpression() {
1903
+ var expr = parseBitwiseORExpression();
1904
+
1905
+ while (match('&&')) {
1906
+ lex();
1907
+ expr = {
1908
+ type: Syntax.LogicalExpression,
1909
+ operator: '&&',
1910
+ left: expr,
1911
+ right: parseBitwiseORExpression()
1912
+ };
1913
+ }
1914
+
1915
+ return expr;
1916
+ }
1917
+
1918
+ function parseLogicalORExpression() {
1919
+ var expr = parseLogicalANDExpression();
1920
+
1921
+ while (match('||')) {
1922
+ lex();
1923
+ expr = {
1924
+ type: Syntax.LogicalExpression,
1925
+ operator: '||',
1926
+ left: expr,
1927
+ right: parseLogicalANDExpression()
1928
+ };
1929
+ }
1930
+
1931
+ return expr;
1932
+ }
1933
+
1934
+ // 11.12 Conditional Operator
1935
+
1936
+ function parseConditionalExpression() {
1937
+ var expr, previousAllowIn, consequent;
1938
+
1939
+ expr = parseLogicalORExpression();
1940
+
1941
+ if (match('?')) {
1942
+ lex();
1943
+ previousAllowIn = state.allowIn;
1944
+ state.allowIn = true;
1945
+ consequent = parseAssignmentExpression();
1946
+ state.allowIn = previousAllowIn;
1947
+ expect(':');
1948
+
1949
+ expr = {
1950
+ type: Syntax.ConditionalExpression,
1951
+ test: expr,
1952
+ consequent: consequent,
1953
+ alternate: parseAssignmentExpression()
1954
+ };
1955
+ }
1956
+
1957
+ return expr;
1958
+ }
1959
+
1960
+ // 11.13 Assignment Operators
1961
+
1962
+ function parseAssignmentExpression() {
1963
+ var expr;
1964
+
1965
+ expr = parseConditionalExpression();
1966
+
1967
+ if (matchAssign()) {
1968
+ // LeftHandSideExpression
1969
+ if (!isLeftHandSide(expr)) {
1970
+ throwError({}, Messages.InvalidLHSInAssignment);
1971
+ }
1972
+
1973
+ // 11.13.1
1974
+ if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
1975
+ throwError({}, Messages.StrictLHSAssignment);
1976
+ }
1977
+
1978
+ expr = {
1979
+ type: Syntax.AssignmentExpression,
1980
+ operator: lex().value,
1981
+ left: expr,
1982
+ right: parseAssignmentExpression()
1983
+ };
1984
+ }
1985
+
1986
+ return expr;
1987
+ }
1988
+
1989
+ // 11.14 Comma Operator
1990
+
1991
+ function parseExpression() {
1992
+ var expr = parseAssignmentExpression();
1993
+
1994
+ if (match(',')) {
1995
+ expr = {
1996
+ type: Syntax.SequenceExpression,
1997
+ expressions: [ expr ]
1998
+ };
1999
+
2000
+ while (index < length) {
2001
+ if (!match(',')) {
2002
+ break;
2003
+ }
2004
+ lex();
2005
+ expr.expressions.push(parseAssignmentExpression());
2006
+ }
2007
+
2008
+ }
2009
+ return expr;
2010
+ }
2011
+
2012
+ // 12.1 Block
2013
+
2014
+ function parseStatementList() {
2015
+ var list = [],
2016
+ statement;
2017
+
2018
+ while (index < length) {
2019
+ if (match('}')) {
2020
+ break;
2021
+ }
2022
+ statement = parseSourceElement();
2023
+ if (typeof statement === 'undefined') {
2024
+ break;
2025
+ }
2026
+ list.push(statement);
2027
+ }
2028
+
2029
+ return list;
2030
+ }
2031
+
2032
+ function parseBlock() {
2033
+ var block;
2034
+
2035
+ expect('{');
2036
+
2037
+ block = parseStatementList();
2038
+
2039
+ expect('}');
2040
+
2041
+ return {
2042
+ type: Syntax.BlockStatement,
2043
+ body: block
2044
+ };
2045
+ }
2046
+
2047
+ // 12.2 Variable Statement
2048
+
2049
+ function parseVariableIdentifier() {
2050
+ var token = lex();
2051
+
2052
+ if (token.type !== Token.Identifier) {
2053
+ throwUnexpected(token);
2054
+ }
2055
+
2056
+ return {
2057
+ type: Syntax.Identifier,
2058
+ name: token.value
2059
+ };
2060
+ }
2061
+
2062
+ function parseVariableDeclaration(kind) {
2063
+ var id = parseVariableIdentifier(),
2064
+ init = null;
2065
+
2066
+ // 12.2.1
2067
+ if (strict && isRestrictedWord(id.name)) {
2068
+ throwErrorTolerant({}, Messages.StrictVarName);
2069
+ }
2070
+
2071
+ if (kind === 'const') {
2072
+ expect('=');
2073
+ init = parseAssignmentExpression();
2074
+ } else if (match('=')) {
2075
+ lex();
2076
+ init = parseAssignmentExpression();
2077
+ }
2078
+
2079
+ return {
2080
+ type: Syntax.VariableDeclarator,
2081
+ id: id,
2082
+ init: init
2083
+ };
2084
+ }
2085
+
2086
+ function parseVariableDeclarationList(kind) {
2087
+ var list = [];
2088
+
2089
+ while (index < length) {
2090
+ list.push(parseVariableDeclaration(kind));
2091
+ if (!match(',')) {
2092
+ break;
2093
+ }
2094
+ lex();
2095
+ }
2096
+
2097
+ return list;
2098
+ }
2099
+
2100
+ function parseVariableStatement() {
2101
+ var declarations;
2102
+
2103
+ expectKeyword('var');
2104
+
2105
+ declarations = parseVariableDeclarationList();
2106
+
2107
+ consumeSemicolon();
2108
+
2109
+ return {
2110
+ type: Syntax.VariableDeclaration,
2111
+ declarations: declarations,
2112
+ kind: 'var'
2113
+ };
2114
+ }
2115
+
2116
+ // kind may be `const` or `let`
2117
+ // Both are experimental and not in the specification yet.
2118
+ // see http://wiki.ecmascript.org/doku.php?id=harmony:const
2119
+ // and http://wiki.ecmascript.org/doku.php?id=harmony:let
2120
+ function parseConstLetDeclaration(kind) {
2121
+ var declarations;
2122
+
2123
+ expectKeyword(kind);
2124
+
2125
+ declarations = parseVariableDeclarationList(kind);
2126
+
2127
+ consumeSemicolon();
2128
+
2129
+ return {
2130
+ type: Syntax.VariableDeclaration,
2131
+ declarations: declarations,
2132
+ kind: kind
2133
+ };
2134
+ }
2135
+
2136
+ // 12.3 Empty Statement
2137
+
2138
+ function parseEmptyStatement() {
2139
+ expect(';');
2140
+
2141
+ return {
2142
+ type: Syntax.EmptyStatement
2143
+ };
2144
+ }
2145
+
2146
+ // 12.4 Expression Statement
2147
+
2148
+ function parseExpressionStatement() {
2149
+ var expr = parseExpression();
2150
+
2151
+ consumeSemicolon();
2152
+
2153
+ return {
2154
+ type: Syntax.ExpressionStatement,
2155
+ expression: expr
2156
+ };
2157
+ }
2158
+
2159
+ // 12.5 If statement
2160
+
2161
+ function parseIfStatement() {
2162
+ var test, consequent, alternate;
2163
+
2164
+ expectKeyword('if');
2165
+
2166
+ expect('(');
2167
+
2168
+ test = parseExpression();
2169
+
2170
+ expect(')');
2171
+
2172
+ consequent = parseStatement();
2173
+
2174
+ if (matchKeyword('else')) {
2175
+ lex();
2176
+ alternate = parseStatement();
2177
+ } else {
2178
+ alternate = null;
2179
+ }
2180
+
2181
+ return {
2182
+ type: Syntax.IfStatement,
2183
+ test: test,
2184
+ consequent: consequent,
2185
+ alternate: alternate
2186
+ };
2187
+ }
2188
+
2189
+ // 12.6 Iteration Statements
2190
+
2191
+ function parseDoWhileStatement() {
2192
+ var body, test, oldInIteration;
2193
+
2194
+ expectKeyword('do');
2195
+
2196
+ oldInIteration = state.inIteration;
2197
+ state.inIteration = true;
2198
+
2199
+ body = parseStatement();
2200
+
2201
+ state.inIteration = oldInIteration;
2202
+
2203
+ expectKeyword('while');
2204
+
2205
+ expect('(');
2206
+
2207
+ test = parseExpression();
2208
+
2209
+ expect(')');
2210
+
2211
+ if (match(';')) {
2212
+ lex();
2213
+ }
2214
+
2215
+ return {
2216
+ type: Syntax.DoWhileStatement,
2217
+ body: body,
2218
+ test: test
2219
+ };
2220
+ }
2221
+
2222
+ function parseWhileStatement() {
2223
+ var test, body, oldInIteration;
2224
+
2225
+ expectKeyword('while');
2226
+
2227
+ expect('(');
2228
+
2229
+ test = parseExpression();
2230
+
2231
+ expect(')');
2232
+
2233
+ oldInIteration = state.inIteration;
2234
+ state.inIteration = true;
2235
+
2236
+ body = parseStatement();
2237
+
2238
+ state.inIteration = oldInIteration;
2239
+
2240
+ return {
2241
+ type: Syntax.WhileStatement,
2242
+ test: test,
2243
+ body: body
2244
+ };
2245
+ }
2246
+
2247
+ function parseForVariableDeclaration() {
2248
+ var token = lex();
2249
+
2250
+ return {
2251
+ type: Syntax.VariableDeclaration,
2252
+ declarations: parseVariableDeclarationList(),
2253
+ kind: token.value
2254
+ };
2255
+ }
2256
+
2257
+ function parseForStatement() {
2258
+ var init, test, update, left, right, body, oldInIteration;
2259
+
2260
+ init = test = update = null;
2261
+
2262
+ expectKeyword('for');
2263
+
2264
+ expect('(');
2265
+
2266
+ if (match(';')) {
2267
+ lex();
2268
+ } else {
2269
+ if (matchKeyword('var') || matchKeyword('let')) {
2270
+ state.allowIn = false;
2271
+ init = parseForVariableDeclaration();
2272
+ state.allowIn = true;
2273
+
2274
+ if (init.declarations.length === 1 && matchKeyword('in')) {
2275
+ lex();
2276
+ left = init;
2277
+ right = parseExpression();
2278
+ init = null;
2279
+ }
2280
+ } else {
2281
+ state.allowIn = false;
2282
+ init = parseExpression();
2283
+ state.allowIn = true;
2284
+
2285
+ if (matchKeyword('in')) {
2286
+ // LeftHandSideExpression
2287
+ if (!isLeftHandSide(init)) {
2288
+ throwError({}, Messages.InvalidLHSInForIn);
2289
+ }
2290
+
2291
+ lex();
2292
+ left = init;
2293
+ right = parseExpression();
2294
+ init = null;
2295
+ }
2296
+ }
2297
+
2298
+ if (typeof left === 'undefined') {
2299
+ expect(';');
2300
+ }
2301
+ }
2302
+
2303
+ if (typeof left === 'undefined') {
2304
+
2305
+ if (!match(';')) {
2306
+ test = parseExpression();
2307
+ }
2308
+ expect(';');
2309
+
2310
+ if (!match(')')) {
2311
+ update = parseExpression();
2312
+ }
2313
+ }
2314
+
2315
+ expect(')');
2316
+
2317
+ oldInIteration = state.inIteration;
2318
+ state.inIteration = true;
2319
+
2320
+ body = parseStatement();
2321
+
2322
+ state.inIteration = oldInIteration;
2323
+
2324
+ if (typeof left === 'undefined') {
2325
+ return {
2326
+ type: Syntax.ForStatement,
2327
+ init: init,
2328
+ test: test,
2329
+ update: update,
2330
+ body: body
2331
+ };
2332
+ }
2333
+
2334
+ return {
2335
+ type: Syntax.ForInStatement,
2336
+ left: left,
2337
+ right: right,
2338
+ body: body,
2339
+ each: false
2340
+ };
2341
+ }
2342
+
2343
+ // 12.7 The continue statement
2344
+
2345
+ function parseContinueStatement() {
2346
+ var token, label = null;
2347
+
2348
+ expectKeyword('continue');
2349
+
2350
+ // Optimize the most common form: 'continue;'.
2351
+ if (source[index] === ';') {
2352
+ lex();
2353
+
2354
+ if (!state.inIteration) {
2355
+ throwError({}, Messages.IllegalContinue);
2356
+ }
2357
+
2358
+ return {
2359
+ type: Syntax.ContinueStatement,
2360
+ label: null
2361
+ };
2362
+ }
2363
+
2364
+ if (peekLineTerminator()) {
2365
+ if (!state.inIteration) {
2366
+ throwError({}, Messages.IllegalContinue);
2367
+ }
2368
+
2369
+ return {
2370
+ type: Syntax.ContinueStatement,
2371
+ label: null
2372
+ };
2373
+ }
2374
+
2375
+ token = lookahead();
2376
+ if (token.type === Token.Identifier) {
2377
+ label = parseVariableIdentifier();
2378
+
2379
+ if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
2380
+ throwError({}, Messages.UnknownLabel, label.name);
2381
+ }
2382
+ }
2383
+
2384
+ consumeSemicolon();
2385
+
2386
+ if (label === null && !state.inIteration) {
2387
+ throwError({}, Messages.IllegalContinue);
2388
+ }
2389
+
2390
+ return {
2391
+ type: Syntax.ContinueStatement,
2392
+ label: label
2393
+ };
2394
+ }
2395
+
2396
+ // 12.8 The break statement
2397
+
2398
+ function parseBreakStatement() {
2399
+ var token, label = null;
2400
+
2401
+ expectKeyword('break');
2402
+
2403
+ // Optimize the most common form: 'break;'.
2404
+ if (source[index] === ';') {
2405
+ lex();
2406
+
2407
+ if (!(state.inIteration || state.inSwitch)) {
2408
+ throwError({}, Messages.IllegalBreak);
2409
+ }
2410
+
2411
+ return {
2412
+ type: Syntax.BreakStatement,
2413
+ label: null
2414
+ };
2415
+ }
2416
+
2417
+ if (peekLineTerminator()) {
2418
+ if (!(state.inIteration || state.inSwitch)) {
2419
+ throwError({}, Messages.IllegalBreak);
2420
+ }
2421
+
2422
+ return {
2423
+ type: Syntax.BreakStatement,
2424
+ label: null
2425
+ };
2426
+ }
2427
+
2428
+ token = lookahead();
2429
+ if (token.type === Token.Identifier) {
2430
+ label = parseVariableIdentifier();
2431
+
2432
+ if (!Object.prototype.hasOwnProperty.call(state.labelSet, label.name)) {
2433
+ throwError({}, Messages.UnknownLabel, label.name);
2434
+ }
2435
+ }
2436
+
2437
+ consumeSemicolon();
2438
+
2439
+ if (label === null && !(state.inIteration || state.inSwitch)) {
2440
+ throwError({}, Messages.IllegalBreak);
2441
+ }
2442
+
2443
+ return {
2444
+ type: Syntax.BreakStatement,
2445
+ label: label
2446
+ };
2447
+ }
2448
+
2449
+ // 12.9 The return statement
2450
+
2451
+ function parseReturnStatement() {
2452
+ var token, argument = null;
2453
+
2454
+ expectKeyword('return');
2455
+
2456
+ if (!state.inFunctionBody) {
2457
+ throwErrorTolerant({}, Messages.IllegalReturn);
2458
+ }
2459
+
2460
+ // 'return' followed by a space and an identifier is very common.
2461
+ if (source[index] === ' ') {
2462
+ if (isIdentifierStart(source[index + 1])) {
2463
+ argument = parseExpression();
2464
+ consumeSemicolon();
2465
+ return {
2466
+ type: Syntax.ReturnStatement,
2467
+ argument: argument
2468
+ };
2469
+ }
2470
+ }
2471
+
2472
+ if (peekLineTerminator()) {
2473
+ return {
2474
+ type: Syntax.ReturnStatement,
2475
+ argument: null
2476
+ };
2477
+ }
2478
+
2479
+ if (!match(';')) {
2480
+ token = lookahead();
2481
+ if (!match('}') && token.type !== Token.EOF) {
2482
+ argument = parseExpression();
2483
+ }
2484
+ }
2485
+
2486
+ consumeSemicolon();
2487
+
2488
+ return {
2489
+ type: Syntax.ReturnStatement,
2490
+ argument: argument
2491
+ };
2492
+ }
2493
+
2494
+ // 12.10 The with statement
2495
+
2496
+ function parseWithStatement() {
2497
+ var object, body;
2498
+
2499
+ if (strict) {
2500
+ throwErrorTolerant({}, Messages.StrictModeWith);
2501
+ }
2502
+
2503
+ expectKeyword('with');
2504
+
2505
+ expect('(');
2506
+
2507
+ object = parseExpression();
2508
+
2509
+ expect(')');
2510
+
2511
+ body = parseStatement();
2512
+
2513
+ return {
2514
+ type: Syntax.WithStatement,
2515
+ object: object,
2516
+ body: body
2517
+ };
2518
+ }
2519
+
2520
+ // 12.10 The swith statement
2521
+
2522
+ function parseSwitchCase() {
2523
+ var test,
2524
+ consequent = [],
2525
+ statement;
2526
+
2527
+ if (matchKeyword('default')) {
2528
+ lex();
2529
+ test = null;
2530
+ } else {
2531
+ expectKeyword('case');
2532
+ test = parseExpression();
2533
+ }
2534
+ expect(':');
2535
+
2536
+ while (index < length) {
2537
+ if (match('}') || matchKeyword('default') || matchKeyword('case')) {
2538
+ break;
2539
+ }
2540
+ statement = parseStatement();
2541
+ if (typeof statement === 'undefined') {
2542
+ break;
2543
+ }
2544
+ consequent.push(statement);
2545
+ }
2546
+
2547
+ return {
2548
+ type: Syntax.SwitchCase,
2549
+ test: test,
2550
+ consequent: consequent
2551
+ };
2552
+ }
2553
+
2554
+ function parseSwitchStatement() {
2555
+ var discriminant, cases, clause, oldInSwitch, defaultFound;
2556
+
2557
+ expectKeyword('switch');
2558
+
2559
+ expect('(');
2560
+
2561
+ discriminant = parseExpression();
2562
+
2563
+ expect(')');
2564
+
2565
+ expect('{');
2566
+
2567
+ if (match('}')) {
2568
+ lex();
2569
+ return {
2570
+ type: Syntax.SwitchStatement,
2571
+ discriminant: discriminant
2572
+ };
2573
+ }
2574
+
2575
+ cases = [];
2576
+
2577
+ oldInSwitch = state.inSwitch;
2578
+ state.inSwitch = true;
2579
+ defaultFound = false;
2580
+
2581
+ while (index < length) {
2582
+ if (match('}')) {
2583
+ break;
2584
+ }
2585
+ clause = parseSwitchCase();
2586
+ if (clause.test === null) {
2587
+ if (defaultFound) {
2588
+ throwError({}, Messages.MultipleDefaultsInSwitch);
2589
+ }
2590
+ defaultFound = true;
2591
+ }
2592
+ cases.push(clause);
2593
+ }
2594
+
2595
+ state.inSwitch = oldInSwitch;
2596
+
2597
+ expect('}');
2598
+
2599
+ return {
2600
+ type: Syntax.SwitchStatement,
2601
+ discriminant: discriminant,
2602
+ cases: cases
2603
+ };
2604
+ }
2605
+
2606
+ // 12.13 The throw statement
2607
+
2608
+ function parseThrowStatement() {
2609
+ var argument;
2610
+
2611
+ expectKeyword('throw');
2612
+
2613
+ if (peekLineTerminator()) {
2614
+ throwError({}, Messages.NewlineAfterThrow);
2615
+ }
2616
+
2617
+ argument = parseExpression();
2618
+
2619
+ consumeSemicolon();
2620
+
2621
+ return {
2622
+ type: Syntax.ThrowStatement,
2623
+ argument: argument
2624
+ };
2625
+ }
2626
+
2627
+ // 12.14 The try statement
2628
+
2629
+ function parseCatchClause() {
2630
+ var param;
2631
+
2632
+ expectKeyword('catch');
2633
+
2634
+ expect('(');
2635
+ if (!match(')')) {
2636
+ param = parseExpression();
2637
+ // 12.14.1
2638
+ if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) {
2639
+ throwErrorTolerant({}, Messages.StrictCatchVariable);
2640
+ }
2641
+ }
2642
+ expect(')');
2643
+
2644
+ return {
2645
+ type: Syntax.CatchClause,
2646
+ param: param,
2647
+ body: parseBlock()
2648
+ };
2649
+ }
2650
+
2651
+ function parseTryStatement() {
2652
+ var block, handlers = [], finalizer = null;
2653
+
2654
+ expectKeyword('try');
2655
+
2656
+ block = parseBlock();
2657
+
2658
+ if (matchKeyword('catch')) {
2659
+ handlers.push(parseCatchClause());
2660
+ }
2661
+
2662
+ if (matchKeyword('finally')) {
2663
+ lex();
2664
+ finalizer = parseBlock();
2665
+ }
2666
+
2667
+ if (handlers.length === 0 && !finalizer) {
2668
+ throwError({}, Messages.NoCatchOrFinally);
2669
+ }
2670
+
2671
+ return {
2672
+ type: Syntax.TryStatement,
2673
+ block: block,
2674
+ guardedHandlers: [],
2675
+ handlers: handlers,
2676
+ finalizer: finalizer
2677
+ };
2678
+ }
2679
+
2680
+ // 12.15 The debugger statement
2681
+
2682
+ function parseDebuggerStatement() {
2683
+ expectKeyword('debugger');
2684
+
2685
+ consumeSemicolon();
2686
+
2687
+ return {
2688
+ type: Syntax.DebuggerStatement
2689
+ };
2690
+ }
2691
+
2692
+ // 12 Statements
2693
+
2694
+ function parseStatement() {
2695
+ var token = lookahead(),
2696
+ expr,
2697
+ labeledBody;
2698
+
2699
+ if (token.type === Token.EOF) {
2700
+ throwUnexpected(token);
2701
+ }
2702
+
2703
+ if (token.type === Token.Punctuator) {
2704
+ switch (token.value) {
2705
+ case ';':
2706
+ return parseEmptyStatement();
2707
+ case '{':
2708
+ return parseBlock();
2709
+ case '(':
2710
+ return parseExpressionStatement();
2711
+ default:
2712
+ break;
2713
+ }
2714
+ }
2715
+
2716
+ if (token.type === Token.Keyword) {
2717
+ switch (token.value) {
2718
+ case 'break':
2719
+ return parseBreakStatement();
2720
+ case 'continue':
2721
+ return parseContinueStatement();
2722
+ case 'debugger':
2723
+ return parseDebuggerStatement();
2724
+ case 'do':
2725
+ return parseDoWhileStatement();
2726
+ case 'for':
2727
+ return parseForStatement();
2728
+ case 'function':
2729
+ return parseFunctionDeclaration();
2730
+ case 'if':
2731
+ return parseIfStatement();
2732
+ case 'return':
2733
+ return parseReturnStatement();
2734
+ case 'switch':
2735
+ return parseSwitchStatement();
2736
+ case 'throw':
2737
+ return parseThrowStatement();
2738
+ case 'try':
2739
+ return parseTryStatement();
2740
+ case 'var':
2741
+ return parseVariableStatement();
2742
+ case 'while':
2743
+ return parseWhileStatement();
2744
+ case 'with':
2745
+ return parseWithStatement();
2746
+ default:
2747
+ break;
2748
+ }
2749
+ }
2750
+
2751
+ expr = parseExpression();
2752
+
2753
+ // 12.12 Labelled Statements
2754
+ if ((expr.type === Syntax.Identifier) && match(':')) {
2755
+ lex();
2756
+
2757
+ if (Object.prototype.hasOwnProperty.call(state.labelSet, expr.name)) {
2758
+ throwError({}, Messages.Redeclaration, 'Label', expr.name);
2759
+ }
2760
+
2761
+ state.labelSet[expr.name] = true;
2762
+ labeledBody = parseStatement();
2763
+ delete state.labelSet[expr.name];
2764
+
2765
+ return {
2766
+ type: Syntax.LabeledStatement,
2767
+ label: expr,
2768
+ body: labeledBody
2769
+ };
2770
+ }
2771
+
2772
+ consumeSemicolon();
2773
+
2774
+ return {
2775
+ type: Syntax.ExpressionStatement,
2776
+ expression: expr
2777
+ };
2778
+ }
2779
+
2780
+ // 13 Function Definition
2781
+
2782
+ function parseFunctionSourceElements() {
2783
+ var sourceElement, sourceElements = [], token, directive, firstRestricted,
2784
+ oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody;
2785
+
2786
+ expect('{');
2787
+
2788
+ while (index < length) {
2789
+ token = lookahead();
2790
+ if (token.type !== Token.StringLiteral) {
2791
+ break;
2792
+ }
2793
+
2794
+ sourceElement = parseSourceElement();
2795
+ sourceElements.push(sourceElement);
2796
+ if (sourceElement.expression.type !== Syntax.Literal) {
2797
+ // this is not directive
2798
+ break;
2799
+ }
2800
+ directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
2801
+ if (directive === 'use strict') {
2802
+ strict = true;
2803
+ if (firstRestricted) {
2804
+ throwError(firstRestricted, Messages.StrictOctalLiteral);
2805
+ }
2806
+ } else {
2807
+ if (!firstRestricted && token.octal) {
2808
+ firstRestricted = token;
2809
+ }
2810
+ }
2811
+ }
2812
+
2813
+ oldLabelSet = state.labelSet;
2814
+ oldInIteration = state.inIteration;
2815
+ oldInSwitch = state.inSwitch;
2816
+ oldInFunctionBody = state.inFunctionBody;
2817
+
2818
+ state.labelSet = {};
2819
+ state.inIteration = false;
2820
+ state.inSwitch = false;
2821
+ state.inFunctionBody = true;
2822
+
2823
+ while (index < length) {
2824
+ if (match('}')) {
2825
+ break;
2826
+ }
2827
+ sourceElement = parseSourceElement();
2828
+ if (typeof sourceElement === 'undefined') {
2829
+ break;
2830
+ }
2831
+ sourceElements.push(sourceElement);
2832
+ }
2833
+
2834
+ expect('}');
2835
+
2836
+ state.labelSet = oldLabelSet;
2837
+ state.inIteration = oldInIteration;
2838
+ state.inSwitch = oldInSwitch;
2839
+ state.inFunctionBody = oldInFunctionBody;
2840
+
2841
+ return {
2842
+ type: Syntax.BlockStatement,
2843
+ body: sourceElements
2844
+ };
2845
+ }
2846
+
2847
+ function parseFunctionDeclaration() {
2848
+ var id, param, params = [], body, token, firstRestricted, message, previousStrict, paramSet;
2849
+
2850
+ expectKeyword('function');
2851
+ token = lookahead();
2852
+ id = parseVariableIdentifier();
2853
+ if (strict) {
2854
+ if (isRestrictedWord(token.value)) {
2855
+ throwError(token, Messages.StrictFunctionName);
2856
+ }
2857
+ } else {
2858
+ if (isRestrictedWord(token.value)) {
2859
+ firstRestricted = token;
2860
+ message = Messages.StrictFunctionName;
2861
+ } else if (isStrictModeReservedWord(token.value)) {
2862
+ firstRestricted = token;
2863
+ message = Messages.StrictReservedWord;
2864
+ }
2865
+ }
2866
+
2867
+ expect('(');
2868
+
2869
+ if (!match(')')) {
2870
+ paramSet = {};
2871
+ while (index < length) {
2872
+ token = lookahead();
2873
+ param = parseVariableIdentifier();
2874
+ if (strict) {
2875
+ if (isRestrictedWord(token.value)) {
2876
+ throwError(token, Messages.StrictParamName);
2877
+ }
2878
+ if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
2879
+ throwError(token, Messages.StrictParamDupe);
2880
+ }
2881
+ } else if (!firstRestricted) {
2882
+ if (isRestrictedWord(token.value)) {
2883
+ firstRestricted = token;
2884
+ message = Messages.StrictParamName;
2885
+ } else if (isStrictModeReservedWord(token.value)) {
2886
+ firstRestricted = token;
2887
+ message = Messages.StrictReservedWord;
2888
+ } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
2889
+ firstRestricted = token;
2890
+ message = Messages.StrictParamDupe;
2891
+ }
2892
+ }
2893
+ params.push(param);
2894
+ paramSet[param.name] = true;
2895
+ if (match(')')) {
2896
+ break;
2897
+ }
2898
+ expect(',');
2899
+ }
2900
+ }
2901
+
2902
+ expect(')');
2903
+
2904
+ previousStrict = strict;
2905
+ body = parseFunctionSourceElements();
2906
+ if (strict && firstRestricted) {
2907
+ throwError(firstRestricted, message);
2908
+ }
2909
+ strict = previousStrict;
2910
+
2911
+ return {
2912
+ type: Syntax.FunctionDeclaration,
2913
+ id: id,
2914
+ params: params,
2915
+ defaults: [],
2916
+ body: body,
2917
+ rest: null,
2918
+ generator: false,
2919
+ expression: false
2920
+ };
2921
+ }
2922
+
2923
+ function parseFunctionExpression() {
2924
+ var token, id = null, firstRestricted, message, param, params = [], body, previousStrict, paramSet;
2925
+
2926
+ expectKeyword('function');
2927
+
2928
+ if (!match('(')) {
2929
+ token = lookahead();
2930
+ id = parseVariableIdentifier();
2931
+ if (strict) {
2932
+ if (isRestrictedWord(token.value)) {
2933
+ throwError(token, Messages.StrictFunctionName);
2934
+ }
2935
+ } else {
2936
+ if (isRestrictedWord(token.value)) {
2937
+ firstRestricted = token;
2938
+ message = Messages.StrictFunctionName;
2939
+ } else if (isStrictModeReservedWord(token.value)) {
2940
+ firstRestricted = token;
2941
+ message = Messages.StrictReservedWord;
2942
+ }
2943
+ }
2944
+ }
2945
+
2946
+ expect('(');
2947
+
2948
+ if (!match(')')) {
2949
+ paramSet = {};
2950
+ while (index < length) {
2951
+ token = lookahead();
2952
+ param = parseVariableIdentifier();
2953
+ if (strict) {
2954
+ if (isRestrictedWord(token.value)) {
2955
+ throwError(token, Messages.StrictParamName);
2956
+ }
2957
+ if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
2958
+ throwError(token, Messages.StrictParamDupe);
2959
+ }
2960
+ } else if (!firstRestricted) {
2961
+ if (isRestrictedWord(token.value)) {
2962
+ firstRestricted = token;
2963
+ message = Messages.StrictParamName;
2964
+ } else if (isStrictModeReservedWord(token.value)) {
2965
+ firstRestricted = token;
2966
+ message = Messages.StrictReservedWord;
2967
+ } else if (Object.prototype.hasOwnProperty.call(paramSet, token.value)) {
2968
+ firstRestricted = token;
2969
+ message = Messages.StrictParamDupe;
2970
+ }
2971
+ }
2972
+ params.push(param);
2973
+ paramSet[param.name] = true;
2974
+ if (match(')')) {
2975
+ break;
2976
+ }
2977
+ expect(',');
2978
+ }
2979
+ }
2980
+
2981
+ expect(')');
2982
+
2983
+ previousStrict = strict;
2984
+ body = parseFunctionSourceElements();
2985
+ if (strict && firstRestricted) {
2986
+ throwError(firstRestricted, message);
2987
+ }
2988
+ strict = previousStrict;
2989
+
2990
+ return {
2991
+ type: Syntax.FunctionExpression,
2992
+ id: id,
2993
+ params: params,
2994
+ defaults: [],
2995
+ body: body,
2996
+ rest: null,
2997
+ generator: false,
2998
+ expression: false
2999
+ };
3000
+ }
3001
+
3002
+ // 14 Program
3003
+
3004
+ function parseSourceElement() {
3005
+ var token = lookahead();
3006
+
3007
+ if (token.type === Token.Keyword) {
3008
+ switch (token.value) {
3009
+ case 'const':
3010
+ case 'let':
3011
+ return parseConstLetDeclaration(token.value);
3012
+ case 'function':
3013
+ return parseFunctionDeclaration();
3014
+ default:
3015
+ return parseStatement();
3016
+ }
3017
+ }
3018
+
3019
+ if (token.type !== Token.EOF) {
3020
+ return parseStatement();
3021
+ }
3022
+ }
3023
+
3024
+ function parseSourceElements() {
3025
+ var sourceElement, sourceElements = [], token, directive, firstRestricted;
3026
+
3027
+ while (index < length) {
3028
+ token = lookahead();
3029
+ if (token.type !== Token.StringLiteral) {
3030
+ break;
3031
+ }
3032
+
3033
+ sourceElement = parseSourceElement();
3034
+ sourceElements.push(sourceElement);
3035
+ if (sourceElement.expression.type !== Syntax.Literal) {
3036
+ // this is not directive
3037
+ break;
3038
+ }
3039
+ directive = sliceSource(token.range[0] + 1, token.range[1] - 1);
3040
+ if (directive === 'use strict') {
3041
+ strict = true;
3042
+ if (firstRestricted) {
3043
+ throwError(firstRestricted, Messages.StrictOctalLiteral);
3044
+ }
3045
+ } else {
3046
+ if (!firstRestricted && token.octal) {
3047
+ firstRestricted = token;
3048
+ }
3049
+ }
3050
+ }
3051
+
3052
+ while (index < length) {
3053
+ sourceElement = parseSourceElement();
3054
+ if (typeof sourceElement === 'undefined') {
3055
+ break;
3056
+ }
3057
+ sourceElements.push(sourceElement);
3058
+ }
3059
+ return sourceElements;
3060
+ }
3061
+
3062
+ function parseProgram() {
3063
+ var program;
3064
+ strict = false;
3065
+ program = {
3066
+ type: Syntax.Program,
3067
+ body: parseSourceElements()
3068
+ };
3069
+ return program;
3070
+ }
3071
+
3072
+ // The following functions are needed only when the option to preserve
3073
+ // the comments is active.
3074
+
3075
+ function addComment(type, value, start, end, loc) {
3076
+ assert(typeof start === 'number', 'Comment must have valid position');
3077
+
3078
+ // Because the way the actual token is scanned, often the comments
3079
+ // (if any) are skipped twice during the lexical analysis.
3080
+ // Thus, we need to skip adding a comment if the comment array already
3081
+ // handled it.
3082
+ if (extra.comments.length > 0) {
3083
+ if (extra.comments[extra.comments.length - 1].range[1] > start) {
3084
+ return;
3085
+ }
3086
+ }
3087
+
3088
+ extra.comments.push({
3089
+ type: type,
3090
+ value: value,
3091
+ range: [start, end],
3092
+ loc: loc
3093
+ });
3094
+ }
3095
+
3096
+ function scanComment() {
3097
+ var comment, ch, loc, start, blockComment, lineComment;
3098
+
3099
+ comment = '';
3100
+ blockComment = false;
3101
+ lineComment = false;
3102
+
3103
+ while (index < length) {
3104
+ ch = source[index];
3105
+
3106
+ if (lineComment) {
3107
+ ch = nextChar();
3108
+ if (isLineTerminator(ch)) {
3109
+ loc.end = {
3110
+ line: lineNumber,
3111
+ column: index - lineStart - 1
3112
+ };
3113
+ lineComment = false;
3114
+ addComment('Line', comment, start, index - 1, loc);
3115
+ if (ch === '\r' && source[index] === '\n') {
3116
+ ++index;
3117
+ }
3118
+ ++lineNumber;
3119
+ lineStart = index;
3120
+ comment = '';
3121
+ } else if (index >= length) {
3122
+ lineComment = false;
3123
+ comment += ch;
3124
+ loc.end = {
3125
+ line: lineNumber,
3126
+ column: length - lineStart
3127
+ };
3128
+ addComment('Line', comment, start, length, loc);
3129
+ } else {
3130
+ comment += ch;
3131
+ }
3132
+ } else if (blockComment) {
3133
+ if (isLineTerminator(ch)) {
3134
+ if (ch === '\r' && source[index + 1] === '\n') {
3135
+ ++index;
3136
+ comment += '\r\n';
3137
+ } else {
3138
+ comment += ch;
3139
+ }
3140
+ ++lineNumber;
3141
+ ++index;
3142
+ lineStart = index;
3143
+ if (index >= length) {
3144
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
3145
+ }
3146
+ } else {
3147
+ ch = nextChar();
3148
+ if (index >= length) {
3149
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
3150
+ }
3151
+ comment += ch;
3152
+ if (ch === '*') {
3153
+ ch = source[index];
3154
+ if (ch === '/') {
3155
+ comment = comment.substr(0, comment.length - 1);
3156
+ blockComment = false;
3157
+ ++index;
3158
+ loc.end = {
3159
+ line: lineNumber,
3160
+ column: index - lineStart
3161
+ };
3162
+ addComment('Block', comment, start, index, loc);
3163
+ comment = '';
3164
+ }
3165
+ }
3166
+ }
3167
+ } else if (ch === '/') {
3168
+ ch = source[index + 1];
3169
+ if (ch === '/') {
3170
+ loc = {
3171
+ start: {
3172
+ line: lineNumber,
3173
+ column: index - lineStart
3174
+ }
3175
+ };
3176
+ start = index;
3177
+ index += 2;
3178
+ lineComment = true;
3179
+ if (index >= length) {
3180
+ loc.end = {
3181
+ line: lineNumber,
3182
+ column: index - lineStart
3183
+ };
3184
+ lineComment = false;
3185
+ addComment('Line', comment, start, index, loc);
3186
+ }
3187
+ } else if (ch === '*') {
3188
+ start = index;
3189
+ index += 2;
3190
+ blockComment = true;
3191
+ loc = {
3192
+ start: {
3193
+ line: lineNumber,
3194
+ column: index - lineStart - 2
3195
+ }
3196
+ };
3197
+ if (index >= length) {
3198
+ throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
3199
+ }
3200
+ } else {
3201
+ break;
3202
+ }
3203
+ } else if (isWhiteSpace(ch)) {
3204
+ ++index;
3205
+ } else if (isLineTerminator(ch)) {
3206
+ ++index;
3207
+ if (ch === '\r' && source[index] === '\n') {
3208
+ ++index;
3209
+ }
3210
+ ++lineNumber;
3211
+ lineStart = index;
3212
+ } else {
3213
+ break;
3214
+ }
3215
+ }
3216
+ }
3217
+
3218
+ function filterCommentLocation() {
3219
+ var i, entry, comment, comments = [];
3220
+
3221
+ for (i = 0; i < extra.comments.length; ++i) {
3222
+ entry = extra.comments[i];
3223
+ comment = {
3224
+ type: entry.type,
3225
+ value: entry.value
3226
+ };
3227
+ if (extra.range) {
3228
+ comment.range = entry.range;
3229
+ }
3230
+ if (extra.loc) {
3231
+ comment.loc = entry.loc;
3232
+ }
3233
+ comments.push(comment);
3234
+ }
3235
+
3236
+ extra.comments = comments;
3237
+ }
3238
+
3239
+ function collectToken() {
3240
+ var start, loc, token, range, value;
3241
+
3242
+ skipComment();
3243
+ start = index;
3244
+ loc = {
3245
+ start: {
3246
+ line: lineNumber,
3247
+ column: index - lineStart
3248
+ }
3249
+ };
3250
+
3251
+ token = extra.advance();
3252
+ loc.end = {
3253
+ line: lineNumber,
3254
+ column: index - lineStart
3255
+ };
3256
+
3257
+ if (token.type !== Token.EOF) {
3258
+ range = [token.range[0], token.range[1]];
3259
+ value = sliceSource(token.range[0], token.range[1]);
3260
+ extra.tokens.push({
3261
+ type: TokenName[token.type],
3262
+ value: value,
3263
+ range: range,
3264
+ loc: loc
3265
+ });
3266
+ }
3267
+
3268
+ return token;
3269
+ }
3270
+
3271
+ function collectRegex() {
3272
+ var pos, loc, regex, token;
3273
+
3274
+ skipComment();
3275
+
3276
+ pos = index;
3277
+ loc = {
3278
+ start: {
3279
+ line: lineNumber,
3280
+ column: index - lineStart
3281
+ }
3282
+ };
3283
+
3284
+ regex = extra.scanRegExp();
3285
+ loc.end = {
3286
+ line: lineNumber,
3287
+ column: index - lineStart
3288
+ };
3289
+
3290
+ // Pop the previous token, which is likely '/' or '/='
3291
+ if (extra.tokens.length > 0) {
3292
+ token = extra.tokens[extra.tokens.length - 1];
3293
+ if (token.range[0] === pos && token.type === 'Punctuator') {
3294
+ if (token.value === '/' || token.value === '/=') {
3295
+ extra.tokens.pop();
3296
+ }
3297
+ }
3298
+ }
3299
+
3300
+ extra.tokens.push({
3301
+ type: 'RegularExpression',
3302
+ value: regex.literal,
3303
+ range: [pos, index],
3304
+ loc: loc
3305
+ });
3306
+
3307
+ return regex;
3308
+ }
3309
+
3310
+ function filterTokenLocation() {
3311
+ var i, entry, token, tokens = [];
3312
+
3313
+ for (i = 0; i < extra.tokens.length; ++i) {
3314
+ entry = extra.tokens[i];
3315
+ token = {
3316
+ type: entry.type,
3317
+ value: entry.value
3318
+ };
3319
+ if (extra.range) {
3320
+ token.range = entry.range;
3321
+ }
3322
+ if (extra.loc) {
3323
+ token.loc = entry.loc;
3324
+ }
3325
+ tokens.push(token);
3326
+ }
3327
+
3328
+ extra.tokens = tokens;
3329
+ }
3330
+
3331
+ function createLiteral(token) {
3332
+ return {
3333
+ type: Syntax.Literal,
3334
+ value: token.value
3335
+ };
3336
+ }
3337
+
3338
+ function createRawLiteral(token) {
3339
+ return {
3340
+ type: Syntax.Literal,
3341
+ value: token.value,
3342
+ raw: sliceSource(token.range[0], token.range[1])
3343
+ };
3344
+ }
3345
+
3346
+ function wrapTrackingFunction(range, loc) {
3347
+
3348
+ return function (parseFunction) {
3349
+
3350
+ function isBinary(node) {
3351
+ return node.type === Syntax.LogicalExpression ||
3352
+ node.type === Syntax.BinaryExpression;
3353
+ }
3354
+
3355
+ function visit(node) {
3356
+ if (isBinary(node.left)) {
3357
+ visit(node.left);
3358
+ }
3359
+ if (isBinary(node.right)) {
3360
+ visit(node.right);
3361
+ }
3362
+
3363
+ if (range && typeof node.range === 'undefined') {
3364
+ node.range = [node.left.range[0], node.right.range[1]];
3365
+ }
3366
+ if (loc && typeof node.loc === 'undefined') {
3367
+ node.loc = {
3368
+ start: node.left.loc.start,
3369
+ end: node.right.loc.end
3370
+ };
3371
+ }
3372
+ }
3373
+
3374
+ return function () {
3375
+ var node, rangeInfo, locInfo;
3376
+
3377
+ skipComment();
3378
+ rangeInfo = [index, 0];
3379
+ locInfo = {
3380
+ start: {
3381
+ line: lineNumber,
3382
+ column: index - lineStart
3383
+ }
3384
+ };
3385
+
3386
+ node = parseFunction.apply(null, arguments);
3387
+ if (typeof node !== 'undefined') {
3388
+
3389
+ if (range && typeof node.range === 'undefined') {
3390
+ rangeInfo[1] = index;
3391
+ node.range = rangeInfo;
3392
+ }
3393
+
3394
+ if (loc && typeof node.loc === 'undefined') {
3395
+ locInfo.end = {
3396
+ line: lineNumber,
3397
+ column: index - lineStart
3398
+ };
3399
+ node.loc = locInfo;
3400
+ }
3401
+
3402
+ if (isBinary(node)) {
3403
+ visit(node);
3404
+ }
3405
+
3406
+ if (node.type === Syntax.MemberExpression) {
3407
+ if (typeof node.object.range !== 'undefined') {
3408
+ node.range[0] = node.object.range[0];
3409
+ }
3410
+ if (typeof node.object.loc !== 'undefined') {
3411
+ node.loc.start = node.object.loc.start;
3412
+ }
3413
+ }
3414
+
3415
+ if (node.type === Syntax.CallExpression) {
3416
+ if (typeof node.callee.range !== 'undefined') {
3417
+ node.range[0] = node.callee.range[0];
3418
+ }
3419
+ if (typeof node.callee.loc !== 'undefined') {
3420
+ node.loc.start = node.callee.loc.start;
3421
+ }
3422
+ }
3423
+ return node;
3424
+ }
3425
+ };
3426
+
3427
+ };
3428
+ }
3429
+
3430
+ function patch() {
3431
+
3432
+ var wrapTracking;
3433
+
3434
+ if (extra.comments) {
3435
+ extra.skipComment = skipComment;
3436
+ skipComment = scanComment;
3437
+ }
3438
+
3439
+ if (extra.raw) {
3440
+ extra.createLiteral = createLiteral;
3441
+ createLiteral = createRawLiteral;
3442
+ }
3443
+
3444
+ if (extra.range || extra.loc) {
3445
+
3446
+ wrapTracking = wrapTrackingFunction(extra.range, extra.loc);
3447
+
3448
+ extra.parseAdditiveExpression = parseAdditiveExpression;
3449
+ extra.parseAssignmentExpression = parseAssignmentExpression;
3450
+ extra.parseBitwiseANDExpression = parseBitwiseANDExpression;
3451
+ extra.parseBitwiseORExpression = parseBitwiseORExpression;
3452
+ extra.parseBitwiseXORExpression = parseBitwiseXORExpression;
3453
+ extra.parseBlock = parseBlock;
3454
+ extra.parseFunctionSourceElements = parseFunctionSourceElements;
3455
+ extra.parseCallMember = parseCallMember;
3456
+ extra.parseCatchClause = parseCatchClause;
3457
+ extra.parseComputedMember = parseComputedMember;
3458
+ extra.parseConditionalExpression = parseConditionalExpression;
3459
+ extra.parseConstLetDeclaration = parseConstLetDeclaration;
3460
+ extra.parseEqualityExpression = parseEqualityExpression;
3461
+ extra.parseExpression = parseExpression;
3462
+ extra.parseForVariableDeclaration = parseForVariableDeclaration;
3463
+ extra.parseFunctionDeclaration = parseFunctionDeclaration;
3464
+ extra.parseFunctionExpression = parseFunctionExpression;
3465
+ extra.parseLogicalANDExpression = parseLogicalANDExpression;
3466
+ extra.parseLogicalORExpression = parseLogicalORExpression;
3467
+ extra.parseMultiplicativeExpression = parseMultiplicativeExpression;
3468
+ extra.parseNewExpression = parseNewExpression;
3469
+ extra.parseNonComputedMember = parseNonComputedMember;
3470
+ extra.parseNonComputedProperty = parseNonComputedProperty;
3471
+ extra.parseObjectProperty = parseObjectProperty;
3472
+ extra.parseObjectPropertyKey = parseObjectPropertyKey;
3473
+ extra.parsePostfixExpression = parsePostfixExpression;
3474
+ extra.parsePrimaryExpression = parsePrimaryExpression;
3475
+ extra.parseProgram = parseProgram;
3476
+ extra.parsePropertyFunction = parsePropertyFunction;
3477
+ extra.parseRelationalExpression = parseRelationalExpression;
3478
+ extra.parseStatement = parseStatement;
3479
+ extra.parseShiftExpression = parseShiftExpression;
3480
+ extra.parseSwitchCase = parseSwitchCase;
3481
+ extra.parseUnaryExpression = parseUnaryExpression;
3482
+ extra.parseVariableDeclaration = parseVariableDeclaration;
3483
+ extra.parseVariableIdentifier = parseVariableIdentifier;
3484
+
3485
+ parseAdditiveExpression = wrapTracking(extra.parseAdditiveExpression);
3486
+ parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression);
3487
+ parseBitwiseANDExpression = wrapTracking(extra.parseBitwiseANDExpression);
3488
+ parseBitwiseORExpression = wrapTracking(extra.parseBitwiseORExpression);
3489
+ parseBitwiseXORExpression = wrapTracking(extra.parseBitwiseXORExpression);
3490
+ parseBlock = wrapTracking(extra.parseBlock);
3491
+ parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements);
3492
+ parseCallMember = wrapTracking(extra.parseCallMember);
3493
+ parseCatchClause = wrapTracking(extra.parseCatchClause);
3494
+ parseComputedMember = wrapTracking(extra.parseComputedMember);
3495
+ parseConditionalExpression = wrapTracking(extra.parseConditionalExpression);
3496
+ parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration);
3497
+ parseEqualityExpression = wrapTracking(extra.parseEqualityExpression);
3498
+ parseExpression = wrapTracking(extra.parseExpression);
3499
+ parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration);
3500
+ parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration);
3501
+ parseFunctionExpression = wrapTracking(extra.parseFunctionExpression);
3502
+ parseLogicalANDExpression = wrapTracking(extra.parseLogicalANDExpression);
3503
+ parseLogicalORExpression = wrapTracking(extra.parseLogicalORExpression);
3504
+ parseMultiplicativeExpression = wrapTracking(extra.parseMultiplicativeExpression);
3505
+ parseNewExpression = wrapTracking(extra.parseNewExpression);
3506
+ parseNonComputedMember = wrapTracking(extra.parseNonComputedMember);
3507
+ parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty);
3508
+ parseObjectProperty = wrapTracking(extra.parseObjectProperty);
3509
+ parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey);
3510
+ parsePostfixExpression = wrapTracking(extra.parsePostfixExpression);
3511
+ parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression);
3512
+ parseProgram = wrapTracking(extra.parseProgram);
3513
+ parsePropertyFunction = wrapTracking(extra.parsePropertyFunction);
3514
+ parseRelationalExpression = wrapTracking(extra.parseRelationalExpression);
3515
+ parseStatement = wrapTracking(extra.parseStatement);
3516
+ parseShiftExpression = wrapTracking(extra.parseShiftExpression);
3517
+ parseSwitchCase = wrapTracking(extra.parseSwitchCase);
3518
+ parseUnaryExpression = wrapTracking(extra.parseUnaryExpression);
3519
+ parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration);
3520
+ parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier);
3521
+ }
3522
+
3523
+ if (typeof extra.tokens !== 'undefined') {
3524
+ extra.advance = advance;
3525
+ extra.scanRegExp = scanRegExp;
3526
+
3527
+ advance = collectToken;
3528
+ scanRegExp = collectRegex;
3529
+ }
3530
+ }
3531
+
3532
+ function unpatch() {
3533
+ if (typeof extra.skipComment === 'function') {
3534
+ skipComment = extra.skipComment;
3535
+ }
3536
+
3537
+ if (extra.raw) {
3538
+ createLiteral = extra.createLiteral;
3539
+ }
3540
+
3541
+ if (extra.range || extra.loc) {
3542
+ parseAdditiveExpression = extra.parseAdditiveExpression;
3543
+ parseAssignmentExpression = extra.parseAssignmentExpression;
3544
+ parseBitwiseANDExpression = extra.parseBitwiseANDExpression;
3545
+ parseBitwiseORExpression = extra.parseBitwiseORExpression;
3546
+ parseBitwiseXORExpression = extra.parseBitwiseXORExpression;
3547
+ parseBlock = extra.parseBlock;
3548
+ parseFunctionSourceElements = extra.parseFunctionSourceElements;
3549
+ parseCallMember = extra.parseCallMember;
3550
+ parseCatchClause = extra.parseCatchClause;
3551
+ parseComputedMember = extra.parseComputedMember;
3552
+ parseConditionalExpression = extra.parseConditionalExpression;
3553
+ parseConstLetDeclaration = extra.parseConstLetDeclaration;
3554
+ parseEqualityExpression = extra.parseEqualityExpression;
3555
+ parseExpression = extra.parseExpression;
3556
+ parseForVariableDeclaration = extra.parseForVariableDeclaration;
3557
+ parseFunctionDeclaration = extra.parseFunctionDeclaration;
3558
+ parseFunctionExpression = extra.parseFunctionExpression;
3559
+ parseLogicalANDExpression = extra.parseLogicalANDExpression;
3560
+ parseLogicalORExpression = extra.parseLogicalORExpression;
3561
+ parseMultiplicativeExpression = extra.parseMultiplicativeExpression;
3562
+ parseNewExpression = extra.parseNewExpression;
3563
+ parseNonComputedMember = extra.parseNonComputedMember;
3564
+ parseNonComputedProperty = extra.parseNonComputedProperty;
3565
+ parseObjectProperty = extra.parseObjectProperty;
3566
+ parseObjectPropertyKey = extra.parseObjectPropertyKey;
3567
+ parsePrimaryExpression = extra.parsePrimaryExpression;
3568
+ parsePostfixExpression = extra.parsePostfixExpression;
3569
+ parseProgram = extra.parseProgram;
3570
+ parsePropertyFunction = extra.parsePropertyFunction;
3571
+ parseRelationalExpression = extra.parseRelationalExpression;
3572
+ parseStatement = extra.parseStatement;
3573
+ parseShiftExpression = extra.parseShiftExpression;
3574
+ parseSwitchCase = extra.parseSwitchCase;
3575
+ parseUnaryExpression = extra.parseUnaryExpression;
3576
+ parseVariableDeclaration = extra.parseVariableDeclaration;
3577
+ parseVariableIdentifier = extra.parseVariableIdentifier;
3578
+ }
3579
+
3580
+ if (typeof extra.scanRegExp === 'function') {
3581
+ advance = extra.advance;
3582
+ scanRegExp = extra.scanRegExp;
3583
+ }
3584
+ }
3585
+
3586
+ function stringToArray(str) {
3587
+ var length = str.length,
3588
+ result = [],
3589
+ i;
3590
+ for (i = 0; i < length; ++i) {
3591
+ result[i] = str.charAt(i);
3592
+ }
3593
+ return result;
3594
+ }
3595
+
3596
+ function parse(code, options) {
3597
+ var program, toString;
3598
+
3599
+ toString = String;
3600
+ if (typeof code !== 'string' && !(code instanceof String)) {
3601
+ code = toString(code);
3602
+ }
3603
+
3604
+ source = code;
3605
+ index = 0;
3606
+ lineNumber = (source.length > 0) ? 1 : 0;
3607
+ lineStart = 0;
3608
+ length = source.length;
3609
+ buffer = null;
3610
+ state = {
3611
+ allowIn: true,
3612
+ labelSet: {},
3613
+ lastParenthesized: null,
3614
+ inFunctionBody: false,
3615
+ inIteration: false,
3616
+ inSwitch: false
3617
+ };
3618
+
3619
+ extra = {};
3620
+ if (typeof options !== 'undefined') {
3621
+ extra.range = (typeof options.range === 'boolean') && options.range;
3622
+ extra.loc = (typeof options.loc === 'boolean') && options.loc;
3623
+ extra.raw = (typeof options.raw === 'boolean') && options.raw;
3624
+ if (typeof options.tokens === 'boolean' && options.tokens) {
3625
+ extra.tokens = [];
3626
+ }
3627
+ if (typeof options.comment === 'boolean' && options.comment) {
3628
+ extra.comments = [];
3629
+ }
3630
+ if (typeof options.tolerant === 'boolean' && options.tolerant) {
3631
+ extra.errors = [];
3632
+ }
3633
+ }
3634
+
3635
+ if (length > 0) {
3636
+ if (typeof source[0] === 'undefined') {
3637
+ // Try first to convert to a string. This is good as fast path
3638
+ // for old IE which understands string indexing for string
3639
+ // literals only and not for string object.
3640
+ if (code instanceof String) {
3641
+ source = code.valueOf();
3642
+ }
3643
+
3644
+ // Force accessing the characters via an array.
3645
+ if (typeof source[0] === 'undefined') {
3646
+ source = stringToArray(code);
3647
+ }
3648
+ }
3649
+ }
3650
+
3651
+ patch();
3652
+ try {
3653
+ program = parseProgram();
3654
+ if (typeof extra.comments !== 'undefined') {
3655
+ filterCommentLocation();
3656
+ program.comments = extra.comments;
3657
+ }
3658
+ if (typeof extra.tokens !== 'undefined') {
3659
+ filterTokenLocation();
3660
+ program.tokens = extra.tokens;
3661
+ }
3662
+ if (typeof extra.errors !== 'undefined') {
3663
+ program.errors = extra.errors;
3664
+ }
3665
+ } catch (e) {
3666
+ throw e;
3667
+ } finally {
3668
+ unpatch();
3669
+ extra = {};
3670
+ }
3671
+
3672
+ return program;
3673
+ }
3674
+
3675
+ // Sync with package.json.
3676
+ exports.version = '1.0.0-dev';
3677
+
3678
+ exports.parse = parse;
3679
+
3680
+ // Deep copy.
3681
+ exports.Syntax = (function () {
3682
+ var name, types = {};
3683
+
3684
+ if (typeof Object.create === 'function') {
3685
+ types = Object.create(null);
3686
+ }
3687
+
3688
+ for (name in Syntax) {
3689
+ if (Syntax.hasOwnProperty(name)) {
3690
+ types[name] = Syntax[name];
3691
+ }
3692
+ }
3693
+
3694
+ if (typeof Object.freeze === 'function') {
3695
+ Object.freeze(types);
3696
+ }
3697
+
3698
+ return types;
3699
+ }());
3700
+
3701
+ }));
3702
+ /* vim: set sw=4 ts=4 et tw=80 : */