2 Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
17 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 (function (root, factory) {
28 // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
29 // Rhino, and plain browser loading.
31 /* istanbul ignore next */
32 if (typeof define === 'function' && define.amd) {
33 define(['exports'], factory);
34 } else if (typeof exports !== 'undefined') {
37 factory((root.esprima = {}));
39 }(this, function (exports) {
68 firstCoverInitializedNameError;
84 TokenName[Token.BooleanLiteral] = 'Boolean';
85 TokenName[Token.EOF] = '<end>';
86 TokenName[Token.Identifier] = 'Identifier';
87 TokenName[Token.Keyword] = 'Keyword';
88 TokenName[Token.NullLiteral] = 'Null';
89 TokenName[Token.NumericLiteral] = 'Numeric';
90 TokenName[Token.Punctuator] = 'Punctuator';
91 TokenName[Token.StringLiteral] = 'String';
92 TokenName[Token.RegularExpression] = 'RegularExpression';
93 TokenName[Token.Template] = 'Template';
95 // A function following one of those tokens is an expression.
96 FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
97 'return', 'case', 'delete', 'throw', 'void',
98 // assignment operators
99 '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=',
100 '&=', '|=', '^=', ',',
101 // binary/unary operators
102 '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&',
103 '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=',
104 '<=', '<', '>', '!=', '!=='];
107 AssignmentExpression: 'AssignmentExpression',
108 AssignmentPattern: 'AssignmentPattern',
109 ArrayExpression: 'ArrayExpression',
110 ArrayPattern: 'ArrayPattern',
111 ArrowFunctionExpression: 'ArrowFunctionExpression',
112 BlockStatement: 'BlockStatement',
113 BinaryExpression: 'BinaryExpression',
114 BreakStatement: 'BreakStatement',
115 CallExpression: 'CallExpression',
116 CatchClause: 'CatchClause',
117 ClassBody: 'ClassBody',
118 ClassDeclaration: 'ClassDeclaration',
119 ClassExpression: 'ClassExpression',
120 ConditionalExpression: 'ConditionalExpression',
121 ContinueStatement: 'ContinueStatement',
122 DoWhileStatement: 'DoWhileStatement',
123 DebuggerStatement: 'DebuggerStatement',
124 EmptyStatement: 'EmptyStatement',
125 ExportAllDeclaration: 'ExportAllDeclaration',
126 ExportDefaultDeclaration: 'ExportDefaultDeclaration',
127 ExportNamedDeclaration: 'ExportNamedDeclaration',
128 ExportSpecifier: 'ExportSpecifier',
129 ExpressionStatement: 'ExpressionStatement',
130 ForStatement: 'ForStatement',
131 ForOfStatement: 'ForOfStatement',
132 ForInStatement: 'ForInStatement',
133 FunctionDeclaration: 'FunctionDeclaration',
134 FunctionExpression: 'FunctionExpression',
135 Identifier: 'Identifier',
136 IfStatement: 'IfStatement',
137 ImportDeclaration: 'ImportDeclaration',
138 ImportDefaultSpecifier: 'ImportDefaultSpecifier',
139 ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
140 ImportSpecifier: 'ImportSpecifier',
142 LabeledStatement: 'LabeledStatement',
143 LogicalExpression: 'LogicalExpression',
144 MemberExpression: 'MemberExpression',
145 MetaProperty: 'MetaProperty',
146 MethodDefinition: 'MethodDefinition',
147 NewExpression: 'NewExpression',
148 ObjectExpression: 'ObjectExpression',
149 ObjectPattern: 'ObjectPattern',
151 Property: 'Property',
152 RestElement: 'RestElement',
153 ReturnStatement: 'ReturnStatement',
154 SequenceExpression: 'SequenceExpression',
155 SpreadElement: 'SpreadElement',
157 SwitchCase: 'SwitchCase',
158 SwitchStatement: 'SwitchStatement',
159 TaggedTemplateExpression: 'TaggedTemplateExpression',
160 TemplateElement: 'TemplateElement',
161 TemplateLiteral: 'TemplateLiteral',
162 ThisExpression: 'ThisExpression',
163 ThrowStatement: 'ThrowStatement',
164 TryStatement: 'TryStatement',
165 UnaryExpression: 'UnaryExpression',
166 UpdateExpression: 'UpdateExpression',
167 VariableDeclaration: 'VariableDeclaration',
168 VariableDeclarator: 'VariableDeclarator',
169 WhileStatement: 'WhileStatement',
170 WithStatement: 'WithStatement',
171 YieldExpression: 'YieldExpression'
175 ArrowParameterPlaceHolder: 'ArrowParameterPlaceHolder'
178 // Error messages should be identical to V8.
180 UnexpectedToken: 'Unexpected token %0',
181 UnexpectedNumber: 'Unexpected number',
182 UnexpectedString: 'Unexpected string',
183 UnexpectedIdentifier: 'Unexpected identifier',
184 UnexpectedReserved: 'Unexpected reserved word',
185 UnexpectedTemplate: 'Unexpected quasi %0',
186 UnexpectedEOS: 'Unexpected end of input',
187 NewlineAfterThrow: 'Illegal newline after throw',
188 InvalidRegExp: 'Invalid regular expression',
189 UnterminatedRegExp: 'Invalid regular expression: missing /',
190 InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
191 InvalidLHSInForIn: 'Invalid left-hand side in for-in',
192 InvalidLHSInForLoop: 'Invalid left-hand side in for-loop',
193 MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
194 NoCatchOrFinally: 'Missing catch or finally after try',
195 UnknownLabel: 'Undefined label \'%0\'',
196 Redeclaration: '%0 \'%1\' has already been declared',
197 IllegalContinue: 'Illegal continue statement',
198 IllegalBreak: 'Illegal break statement',
199 IllegalReturn: 'Illegal return statement',
200 StrictModeWith: 'Strict mode code may not include a with statement',
201 StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
202 StrictVarName: 'Variable name may not be eval or arguments in strict mode',
203 StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
204 StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
205 StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
206 StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
207 StrictDelete: 'Delete of an unqualified identifier in strict mode.',
208 StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
209 StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
210 StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
211 StrictReservedWord: 'Use of future reserved word in strict mode',
212 TemplateOctalLiteral: 'Octal literals are not allowed in template strings.',
213 ParameterAfterRestParameter: 'Rest parameter must be last formal parameter',
214 DefaultRestParameter: 'Unexpected token =',
215 ObjectPatternAsRestParameter: 'Unexpected token {',
216 DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals',
217 ConstructorSpecialMethod: 'Class constructor may not be an accessor',
218 DuplicateConstructor: 'A class may only have one constructor',
219 StaticPrototype: 'Classes may not have static property named prototype',
220 MissingFromClause: 'Unexpected token',
221 NoAsAfterImportNamespace: 'Unexpected token',
222 InvalidModuleSpecifier: 'Unexpected token',
223 IllegalImportDeclaration: 'Unexpected token',
224 IllegalExportDeclaration: 'Unexpected token',
225 DuplicateBinding: 'Duplicate binding %0'
228 // See also tools/generate-unicode-regex.js.
230 // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart:
231 NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\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-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\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-\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-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\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\u2118-\u211D\u2124\u2126\u2128\u212A-\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\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\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-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\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]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/,
233 // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart:
234 NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\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-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\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\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\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\u0D01-\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\u0DE6-\u0DEF\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\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\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-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\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\u2118-\u211D\u2124\u2126\u2128\u212A-\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\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\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-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\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-\uFE2D\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]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
237 // Ensure the condition is true, otherwise throw an error.
238 // This is only to have a better contract semantic, i.e. another safety net
239 // to catch a logic error. The condition shall be fulfilled in normal case.
240 // Do NOT use this to enforce a certain condition on any user input.
242 function assert(condition, message) {
243 /* istanbul ignore if */
245 throw new Error('ASSERT: ' + message);
249 function isDecimalDigit(ch) {
250 return (ch >= 0x30 && ch <= 0x39); // 0..9
253 function isHexDigit(ch) {
254 return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
257 function isOctalDigit(ch) {
258 return '01234567'.indexOf(ch) >= 0;
261 function octalToDecimal(ch) {
262 // \0 is not octal escape sequence
263 var octal = (ch !== '0'), code = '01234567'.indexOf(ch);
265 if (index < length && isOctalDigit(source[index])) {
267 code = code * 8 + '01234567'.indexOf(source[index++]);
269 // 3 digits are only allowed when string starts
271 if ('0123'.indexOf(ch) >= 0 &&
273 isOctalDigit(source[index])) {
274 code = code * 8 + '01234567'.indexOf(source[index++]);
284 // ECMA-262 11.2 White Space
286 function isWhiteSpace(ch) {
287 return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) ||
288 (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0);
291 // ECMA-262 11.3 Line Terminators
293 function isLineTerminator(ch) {
294 return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029);
297 // ECMA-262 11.6 Identifier Names and Identifiers
299 function fromCodePoint(cp) {
300 return (cp < 0x10000) ? String.fromCharCode(cp) :
301 String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) +
302 String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023));
305 function isIdentifierStart(ch) {
306 return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
307 (ch >= 0x41 && ch <= 0x5A) || // A..Z
308 (ch >= 0x61 && ch <= 0x7A) || // a..z
309 (ch === 0x5C) || // \ (backslash)
310 ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch)));
313 function isIdentifierPart(ch) {
314 return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore)
315 (ch >= 0x41 && ch <= 0x5A) || // A..Z
316 (ch >= 0x61 && ch <= 0x7A) || // a..z
317 (ch >= 0x30 && ch <= 0x39) || // 0..9
318 (ch === 0x5C) || // \ (backslash)
319 ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch)));
322 // ECMA-262 11.6.2.2 Future Reserved Words
324 function isFutureReservedWord(id) {
336 function isStrictModeReservedWord(id) {
353 function isRestrictedWord(id) {
354 return id === 'eval' || id === 'arguments';
357 // ECMA-262 11.6.2.1 Keywords
359 function isKeyword(id) {
362 return (id === 'if') || (id === 'in') || (id === 'do');
364 return (id === 'var') || (id === 'for') || (id === 'new') ||
365 (id === 'try') || (id === 'let');
367 return (id === 'this') || (id === 'else') || (id === 'case') ||
368 (id === 'void') || (id === 'with') || (id === 'enum');
370 return (id === 'while') || (id === 'break') || (id === 'catch') ||
371 (id === 'throw') || (id === 'const') || (id === 'yield') ||
372 (id === 'class') || (id === 'super');
374 return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
375 (id === 'switch') || (id === 'export') || (id === 'import');
377 return (id === 'default') || (id === 'finally') || (id === 'extends');
379 return (id === 'function') || (id === 'continue') || (id === 'debugger');
381 return (id === 'instanceof');
387 // ECMA-262 11.4 Comments
389 function addComment(type, value, start, end, loc) {
392 assert(typeof start === 'number', 'Comment must have valid position');
394 state.lastCommentStart = start;
401 comment.range = [start, end];
406 extra.comments.push(comment);
407 if (extra.attachComment) {
408 extra.leadingComments.push(comment);
409 extra.trailingComments.push(comment);
411 if (extra.tokenize) {
412 comment.type = comment.type + 'Comment';
413 if (extra.delegate) {
414 comment = extra.delegate(comment);
416 extra.tokens.push(comment);
420 function skipSingleLineComment(offset) {
421 var start, loc, ch, comment;
423 start = index - offset;
427 column: index - lineStart - offset
431 while (index < length) {
432 ch = source.charCodeAt(index);
434 if (isLineTerminator(ch)) {
435 hasLineTerminator = true;
436 if (extra.comments) {
437 comment = source.slice(start + offset, index - 1);
440 column: index - lineStart - 1
442 addComment('Line', comment, start, index - 1, loc);
444 if (ch === 13 && source.charCodeAt(index) === 10) {
453 if (extra.comments) {
454 comment = source.slice(start + offset, index);
457 column: index - lineStart
459 addComment('Line', comment, start, index, loc);
463 function skipMultiLineComment() {
464 var start, loc, ch, comment;
466 if (extra.comments) {
471 column: index - lineStart - 2
476 while (index < length) {
477 ch = source.charCodeAt(index);
478 if (isLineTerminator(ch)) {
479 if (ch === 0x0D && source.charCodeAt(index + 1) === 0x0A) {
482 hasLineTerminator = true;
486 } else if (ch === 0x2A) {
487 // Block comment ends with '*/'.
488 if (source.charCodeAt(index + 1) === 0x2F) {
491 if (extra.comments) {
492 comment = source.slice(start + 2, index - 2);
495 column: index - lineStart
497 addComment('Block', comment, start, index, loc);
507 // Ran off the end of the file - the whole thing is a comment
508 if (extra.comments) {
511 column: index - lineStart
513 comment = source.slice(start + 2, index);
514 addComment('Block', comment, start, index, loc);
516 tolerateUnexpectedToken();
519 function skipComment() {
521 hasLineTerminator = false;
523 start = (index === 0);
524 while (index < length) {
525 ch = source.charCodeAt(index);
527 if (isWhiteSpace(ch)) {
529 } else if (isLineTerminator(ch)) {
530 hasLineTerminator = true;
532 if (ch === 0x0D && source.charCodeAt(index) === 0x0A) {
538 } else if (ch === 0x2F) { // U+002F is '/'
539 ch = source.charCodeAt(index + 1);
543 skipSingleLineComment(2);
545 } else if (ch === 0x2A) { // U+002A is '*'
548 skipMultiLineComment();
552 } else if (start && ch === 0x2D) { // U+002D is '-'
554 if ((source.charCodeAt(index + 1) === 0x2D) && (source.charCodeAt(index + 2) === 0x3E)) {
555 // '-->' is a single-line comment
557 skipSingleLineComment(3);
561 } else if (ch === 0x3C) { // U+003C is '<'
562 if (source.slice(index + 1, index + 4) === '!--') {
567 skipSingleLineComment(4);
577 function scanHexEscape(prefix) {
578 var i, len, ch, code = 0;
580 len = (prefix === 'u') ? 4 : 2;
581 for (i = 0; i < len; ++i) {
582 if (index < length && isHexDigit(source[index])) {
583 ch = source[index++];
584 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
589 return String.fromCharCode(code);
592 function scanUnicodeCodePointEscape() {
598 // At least, one hex digit is required.
600 throwUnexpectedToken();
603 while (index < length) {
604 ch = source[index++];
605 if (!isHexDigit(ch)) {
608 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
611 if (code > 0x10FFFF || ch !== '}') {
612 throwUnexpectedToken();
615 return fromCodePoint(code);
618 function codePointAt(i) {
619 var cp, first, second;
621 cp = source.charCodeAt(i);
622 if (cp >= 0xD800 && cp <= 0xDBFF) {
623 second = source.charCodeAt(i + 1);
624 if (second >= 0xDC00 && second <= 0xDFFF) {
626 cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
633 function getComplexIdentifier() {
636 cp = codePointAt(index);
637 id = fromCodePoint(cp);
640 // '\u' (U+005C, U+0075) denotes an escaped character.
642 if (source.charCodeAt(index) !== 0x75) {
643 throwUnexpectedToken();
646 if (source[index] === '{') {
648 ch = scanUnicodeCodePointEscape();
650 ch = scanHexEscape('u');
651 cp = ch.charCodeAt(0);
652 if (!ch || ch === '\\' || !isIdentifierStart(cp)) {
653 throwUnexpectedToken();
659 while (index < length) {
660 cp = codePointAt(index);
661 if (!isIdentifierPart(cp)) {
664 ch = fromCodePoint(cp);
668 // '\u' (U+005C, U+0075) denotes an escaped character.
670 id = id.substr(0, id.length - 1);
671 if (source.charCodeAt(index) !== 0x75) {
672 throwUnexpectedToken();
675 if (source[index] === '{') {
677 ch = scanUnicodeCodePointEscape();
679 ch = scanHexEscape('u');
680 cp = ch.charCodeAt(0);
681 if (!ch || ch === '\\' || !isIdentifierPart(cp)) {
682 throwUnexpectedToken();
692 function getIdentifier() {
696 while (index < length) {
697 ch = source.charCodeAt(index);
699 // Blackslash (U+005C) marks Unicode escape sequence.
701 return getComplexIdentifier();
702 } else if (ch >= 0xD800 && ch < 0xDFFF) {
703 // Need to handle surrogate pairs.
705 return getComplexIdentifier();
707 if (isIdentifierPart(ch)) {
714 return source.slice(start, index);
717 function scanIdentifier() {
722 // Backslash (U+005C) starts an escaped character.
723 id = (source.charCodeAt(index) === 0x5C) ? getComplexIdentifier() : getIdentifier();
725 // There is no keyword or literal with only one character.
726 // Thus, it must be an identifier.
727 if (id.length === 1) {
728 type = Token.Identifier;
729 } else if (isKeyword(id)) {
730 type = Token.Keyword;
731 } else if (id === 'null') {
732 type = Token.NullLiteral;
733 } else if (id === 'true' || id === 'false') {
734 type = Token.BooleanLiteral;
736 type = Token.Identifier;
742 lineNumber: lineNumber,
743 lineStart: lineStart,
750 // ECMA-262 11.7 Punctuators
752 function scanPunctuator() {
756 type: Token.Punctuator,
758 lineNumber: lineNumber,
759 lineStart: lineStart,
764 // Check for most common single-character punctuators.
769 if (extra.tokenize) {
770 extra.openParenToken = extra.tokenValues.length;
776 if (extra.tokenize) {
777 extra.openCurlyToken = extra.tokenValues.length;
779 state.curlyStack.push('{');
785 if (source[index] === '.' && source[index + 1] === '.') {
786 // Spread operator: ...
794 state.curlyStack.pop();
808 // 4-character punctuator.
809 str = source.substr(index, 4);
810 if (str === '>>>=') {
814 // 3-character punctuators.
815 str = str.substr(0, 3);
816 if (str === '===' || str === '!==' || str === '>>>' ||
817 str === '<<=' || str === '>>=') {
821 // 2-character punctuators.
822 str = str.substr(0, 2);
823 if (str === '&&' || str === '||' || str === '==' || str === '!=' ||
824 str === '+=' || str === '-=' || str === '*=' || str === '/=' ||
825 str === '++' || str === '--' || str === '<<' || str === '>>' ||
826 str === '&=' || str === '|=' || str === '^=' || str === '%=' ||
827 str === '<=' || str === '>=' || str === '=>') {
831 // 1-character punctuators.
833 if ('<>=!+-*%&|^/'.indexOf(str) >= 0) {
841 if (index === token.start) {
842 throwUnexpectedToken();
850 // ECMA-262 11.8.3 Numeric Literals
852 function scanHexLiteral(start) {
855 while (index < length) {
856 if (!isHexDigit(source[index])) {
859 number += source[index++];
862 if (number.length === 0) {
863 throwUnexpectedToken();
866 if (isIdentifierStart(source.charCodeAt(index))) {
867 throwUnexpectedToken();
871 type: Token.NumericLiteral,
872 value: parseInt('0x' + number, 16),
873 lineNumber: lineNumber,
874 lineStart: lineStart,
880 function scanBinaryLiteral(start) {
885 while (index < length) {
887 if (ch !== '0' && ch !== '1') {
890 number += source[index++];
893 if (number.length === 0) {
895 throwUnexpectedToken();
898 if (index < length) {
899 ch = source.charCodeAt(index);
900 /* istanbul ignore else */
901 if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
902 throwUnexpectedToken();
907 type: Token.NumericLiteral,
908 value: parseInt(number, 2),
909 lineNumber: lineNumber,
910 lineStart: lineStart,
916 function scanOctalLiteral(prefix, start) {
919 if (isOctalDigit(prefix)) {
921 number = '0' + source[index++];
928 while (index < length) {
929 if (!isOctalDigit(source[index])) {
932 number += source[index++];
935 if (!octal && number.length === 0) {
937 throwUnexpectedToken();
940 if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
941 throwUnexpectedToken();
945 type: Token.NumericLiteral,
946 value: parseInt(number, 8),
948 lineNumber: lineNumber,
949 lineStart: lineStart,
955 function isImplicitOctalLiteral() {
958 // Implicit octal, unless there is a non-octal digit.
959 // (Annex B.1.1 on Numeric Literals)
960 for (i = index + 1; i < length; ++i) {
962 if (ch === '8' || ch === '9') {
965 if (!isOctalDigit(ch)) {
973 function scanNumericLiteral() {
974 var number, start, ch;
977 assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
978 'Numeric literal must start with a decimal digit or a decimal point');
983 number = source[index++];
986 // Hex number starts with '0x'.
987 // Octal number starts with '0'.
988 // Octal number in ES6 starts with '0o'.
989 // Binary number in ES6 starts with '0b'.
990 if (number === '0') {
991 if (ch === 'x' || ch === 'X') {
993 return scanHexLiteral(start);
995 if (ch === 'b' || ch === 'B') {
997 return scanBinaryLiteral(start);
999 if (ch === 'o' || ch === 'O') {
1000 return scanOctalLiteral(ch, start);
1003 if (isOctalDigit(ch)) {
1004 if (isImplicitOctalLiteral()) {
1005 return scanOctalLiteral(ch, start);
1010 while (isDecimalDigit(source.charCodeAt(index))) {
1011 number += source[index++];
1017 number += source[index++];
1018 while (isDecimalDigit(source.charCodeAt(index))) {
1019 number += source[index++];
1024 if (ch === 'e' || ch === 'E') {
1025 number += source[index++];
1028 if (ch === '+' || ch === '-') {
1029 number += source[index++];
1031 if (isDecimalDigit(source.charCodeAt(index))) {
1032 while (isDecimalDigit(source.charCodeAt(index))) {
1033 number += source[index++];
1036 throwUnexpectedToken();
1040 if (isIdentifierStart(source.charCodeAt(index))) {
1041 throwUnexpectedToken();
1045 type: Token.NumericLiteral,
1046 value: parseFloat(number),
1047 lineNumber: lineNumber,
1048 lineStart: lineStart,
1054 // ECMA-262 11.8.4 String Literals
1056 function scanStringLiteral() {
1057 var str = '', quote, start, ch, unescaped, octToDec, octal = false;
1059 quote = source[index];
1060 assert((quote === '\'' || quote === '"'),
1061 'String literal must starts with a quote');
1066 while (index < length) {
1067 ch = source[index++];
1072 } else if (ch === '\\') {
1073 ch = source[index++];
1074 if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
1078 if (source[index] === '{') {
1080 str += scanUnicodeCodePointEscape();
1082 unescaped = scanHexEscape(ch);
1084 throw throwUnexpectedToken();
1110 tolerateUnexpectedToken();
1114 if (isOctalDigit(ch)) {
1115 octToDec = octalToDecimal(ch);
1117 octal = octToDec.octal || octal;
1118 str += String.fromCharCode(octToDec.code);
1126 if (ch === '\r' && source[index] === '\n') {
1131 } else if (isLineTerminator(ch.charCodeAt(0))) {
1140 throwUnexpectedToken();
1144 type: Token.StringLiteral,
1147 lineNumber: startLineNumber,
1148 lineStart: startLineStart,
1154 // ECMA-262 11.8.6 Template Literal Lexical Components
1156 function scanTemplate() {
1157 var cooked = '', ch, start, rawOffset, terminated, head, tail, restore, unescaped;
1162 head = (source[index] === '`');
1167 while (index < length) {
1168 ch = source[index++];
1174 } else if (ch === '$') {
1175 if (source[index] === '{') {
1176 state.curlyStack.push('${');
1182 } else if (ch === '\\') {
1183 ch = source[index++];
1184 if (!isLineTerminator(ch.charCodeAt(0))) {
1197 if (source[index] === '{') {
1199 cooked += scanUnicodeCodePointEscape();
1202 unescaped = scanHexEscape(ch);
1204 cooked += unescaped;
1223 if (isDecimalDigit(source.charCodeAt(index))) {
1224 // Illegal: \01 \02 and so on
1225 throwError(Messages.TemplateOctalLiteral);
1228 } else if (isOctalDigit(ch)) {
1230 throwError(Messages.TemplateOctalLiteral);
1238 if (ch === '\r' && source[index] === '\n') {
1243 } else if (isLineTerminator(ch.charCodeAt(0))) {
1245 if (ch === '\r' && source[index] === '\n') {
1256 throwUnexpectedToken();
1260 state.curlyStack.pop();
1264 type: Token.Template,
1267 raw: source.slice(start + 1, index - rawOffset)
1271 lineNumber: lineNumber,
1272 lineStart: lineStart,
1278 // ECMA-262 11.8.5 Regular Expression Literals
1280 function testRegExp(pattern, flags) {
1281 // The BMP character to use as a replacement for astral symbols when
1282 // translating an ES6 "u"-flagged pattern to an ES5-compatible
1284 // Note: replacing with '\uFFFF' enables false positives in unlikely
1285 // scenarios. For example, `[\u{1044f}-\u{10440}]` is an invalid
1286 // pattern that would not be detected by this substitution.
1287 var astralSubstitute = '\uFFFF',
1290 if (flags.indexOf('u') >= 0) {
1292 // Replace every Unicode escape sequence with the equivalent
1293 // BMP character or a constant ASCII code point in the case of
1294 // astral symbols. (See the above note on `astralSubstitute`
1295 // for more information.)
1296 .replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, function ($0, $1, $2) {
1297 var codePoint = parseInt($1 || $2, 16);
1298 if (codePoint > 0x10FFFF) {
1299 throwUnexpectedToken(null, Messages.InvalidRegExp);
1301 if (codePoint <= 0xFFFF) {
1302 return String.fromCharCode(codePoint);
1304 return astralSubstitute;
1306 // Replace each paired surrogate with a single ASCII symbol to
1307 // avoid throwing on regular expressions that are only valid in
1308 // combination with the "u" flag.
1310 /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
1315 // First, detect invalid regular expressions.
1319 throwUnexpectedToken(null, Messages.InvalidRegExp);
1322 // Return a regular expression object for this pattern-flag pair, or
1323 // `null` in case the current environment doesn't support the flags it
1326 return new RegExp(pattern, flags);
1327 } catch (exception) {
1328 /* istanbul ignore next */
1333 function scanRegExpBody() {
1334 var ch, str, classMarker, terminated, body;
1337 assert(ch === '/', 'Regular expression literal must start with a slash');
1338 str = source[index++];
1340 classMarker = false;
1342 while (index < length) {
1343 ch = source[index++];
1346 ch = source[index++];
1348 if (isLineTerminator(ch.charCodeAt(0))) {
1349 throwUnexpectedToken(null, Messages.UnterminatedRegExp);
1352 } else if (isLineTerminator(ch.charCodeAt(0))) {
1353 throwUnexpectedToken(null, Messages.UnterminatedRegExp);
1354 } else if (classMarker) {
1356 classMarker = false;
1362 } else if (ch === '[') {
1369 throwUnexpectedToken(null, Messages.UnterminatedRegExp);
1372 // Exclude leading and trailing slash.
1373 body = str.substr(1, str.length - 2);
1380 function scanRegExpFlags() {
1381 var ch, str, flags, restore;
1385 while (index < length) {
1387 if (!isIdentifierPart(ch.charCodeAt(0))) {
1392 if (ch === '\\' && index < length) {
1397 ch = scanHexEscape('u');
1400 for (str += '\\u'; restore < index; ++restore) {
1401 str += source[restore];
1408 tolerateUnexpectedToken();
1411 tolerateUnexpectedToken();
1425 function scanRegExp() {
1426 var start, body, flags, value;
1433 body = scanRegExpBody();
1434 flags = scanRegExpFlags();
1435 value = testRegExp(body.value, flags.value);
1437 if (extra.tokenize) {
1439 type: Token.RegularExpression,
1442 pattern: body.value,
1445 lineNumber: lineNumber,
1446 lineStart: lineStart,
1453 literal: body.literal + flags.literal,
1456 pattern: body.value,
1464 function collectRegex() {
1465 var pos, loc, regex, token;
1473 column: index - lineStart
1477 regex = scanRegExp();
1481 column: index - lineStart
1484 /* istanbul ignore next */
1485 if (!extra.tokenize) {
1486 // Pop the previous token, which is likely '/' or '/='
1487 if (extra.tokens.length > 0) {
1488 token = extra.tokens[extra.tokens.length - 1];
1489 if (token.range[0] === pos && token.type === 'Punctuator') {
1490 if (token.value === '/' || token.value === '/=') {
1497 type: 'RegularExpression',
1498 value: regex.literal,
1500 range: [pos, index],
1508 function isIdentifierName(token) {
1509 return token.type === Token.Identifier ||
1510 token.type === Token.Keyword ||
1511 token.type === Token.BooleanLiteral ||
1512 token.type === Token.NullLiteral;
1515 // Using the following algorithm:
1516 // https://github.com/mozilla/sweet.js/wiki/design
1518 function advanceSlash() {
1519 var regex, previous, check;
1521 function testKeyword(value) {
1522 return value && (value.length > 1) && (value[0] >= 'a') && (value[0] <= 'z');
1525 previous = extra.tokenValues[extra.tokenValues.length - 1];
1526 regex = (previous !== null);
1535 check = extra.tokenValues[extra.openParenToken - 1];
1536 regex = (check === 'if' || check === 'while' || check === 'for' || check === 'with');
1540 // Dividing a function by anything makes little sense,
1541 // but we have to check for that.
1543 if (testKeyword(extra.tokenValues[extra.openCurlyToken - 3])) {
1544 // Anonymous function, e.g. function(){} /42
1545 check = extra.tokenValues[extra.openCurlyToken - 4];
1546 regex = check ? (FnExprTokens.indexOf(check) < 0) : false;
1547 } else if (testKeyword(extra.tokenValues[extra.openCurlyToken - 4])) {
1548 // Named function, e.g. function f(){} /42/
1549 check = extra.tokenValues[extra.openCurlyToken - 5];
1550 regex = check ? (FnExprTokens.indexOf(check) < 0) : true;
1554 return regex ? collectRegex() : scanPunctuator();
1557 function advance() {
1560 if (index >= length) {
1563 lineNumber: lineNumber,
1564 lineStart: lineStart,
1570 cp = source.charCodeAt(index);
1572 if (isIdentifierStart(cp)) {
1573 token = scanIdentifier();
1574 if (strict && isStrictModeReservedWord(token.value)) {
1575 token.type = Token.Keyword;
1580 // Very common: ( and ) and ;
1581 if (cp === 0x28 || cp === 0x29 || cp === 0x3B) {
1582 return scanPunctuator();
1585 // String literal starts with single quote (U+0027) or double quote (U+0022).
1586 if (cp === 0x27 || cp === 0x22) {
1587 return scanStringLiteral();
1590 // Dot (.) U+002E can also start a floating-point number, hence the need
1591 // to check the next character.
1593 if (isDecimalDigit(source.charCodeAt(index + 1))) {
1594 return scanNumericLiteral();
1596 return scanPunctuator();
1599 if (isDecimalDigit(cp)) {
1600 return scanNumericLiteral();
1603 // Slash (/) U+002F can also start a regex.
1604 if (extra.tokenize && cp === 0x2F) {
1605 return advanceSlash();
1608 // Template literals start with ` (U+0060) for template head
1609 // or } (U+007D) for template middle or template tail.
1610 if (cp === 0x60 || (cp === 0x7D && state.curlyStack[state.curlyStack.length - 1] === '${')) {
1611 return scanTemplate();
1614 // Possible identifier start in a surrogate pair.
1615 if (cp >= 0xD800 && cp < 0xDFFF) {
1616 cp = codePointAt(index);
1617 if (isIdentifierStart(cp)) {
1618 return scanIdentifier();
1622 return scanPunctuator();
1625 function collectToken() {
1626 var loc, token, value, entry;
1631 column: index - lineStart
1638 column: index - lineStart
1641 if (token.type !== Token.EOF) {
1642 value = source.slice(token.start, token.end);
1644 type: TokenName[token.type],
1646 range: [token.start, token.end],
1651 pattern: token.regex.pattern,
1652 flags: token.regex.flags
1655 if (extra.tokenValues) {
1656 extra.tokenValues.push((entry.type === 'Punctuator' || entry.type === 'Keyword') ? entry.value : null);
1658 if (extra.tokenize) {
1665 if (extra.delegate) {
1666 entry = extra.delegate(entry);
1669 extra.tokens.push(entry);
1680 lastLineNumber = lineNumber;
1681 lastLineStart = lineStart;
1688 startLineNumber = lineNumber;
1689 startLineStart = lineStart;
1691 lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
1702 lastLineNumber = lineNumber;
1703 lastLineStart = lineStart;
1706 startLineNumber = lineNumber;
1707 startLineStart = lineStart;
1709 lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
1713 function Position() {
1714 this.line = startLineNumber;
1715 this.column = startIndex - startLineStart;
1718 function SourceLocation() {
1719 this.start = new Position();
1723 function WrappingSourceLocation(startToken) {
1725 line: startToken.lineNumber,
1726 column: startToken.start - startToken.lineStart
1733 this.range = [startIndex, 0];
1736 this.loc = new SourceLocation();
1740 function WrappingNode(startToken) {
1742 this.range = [startToken.start, 0];
1745 this.loc = new WrappingSourceLocation(startToken);
1749 WrappingNode.prototype = Node.prototype = {
1751 processComment: function () {
1756 bottomRight = extra.bottomRightStack,
1759 last = bottomRight[bottomRight.length - 1];
1761 if (this.type === Syntax.Program) {
1762 if (this.body.length > 0) {
1767 * patch innnerComments for properties empty block
1768 * `function a() {/** comments **\/}`
1771 if (this.type === Syntax.BlockStatement && this.body.length === 0) {
1773 for (i = extra.leadingComments.length - 1; i >= 0; --i) {
1774 comment = extra.leadingComments[i];
1775 if (this.range[1] >= comment.range[1]) {
1776 innerComments.unshift(comment);
1777 extra.leadingComments.splice(i, 1);
1778 extra.trailingComments.splice(i, 1);
1781 if (innerComments.length) {
1782 this.innerComments = innerComments;
1783 //bottomRight.push(this);
1788 if (extra.trailingComments.length > 0) {
1789 trailingComments = [];
1790 for (i = extra.trailingComments.length - 1; i >= 0; --i) {
1791 comment = extra.trailingComments[i];
1792 if (comment.range[0] >= this.range[1]) {
1793 trailingComments.unshift(comment);
1794 extra.trailingComments.splice(i, 1);
1797 extra.trailingComments = [];
1799 if (last && last.trailingComments && last.trailingComments[0].range[0] >= this.range[1]) {
1800 trailingComments = last.trailingComments;
1801 delete last.trailingComments;
1805 // Eating the stack.
1806 while (last && last.range[0] >= this.range[0]) {
1807 lastChild = bottomRight.pop();
1808 last = bottomRight[bottomRight.length - 1];
1812 if (lastChild.leadingComments) {
1813 leadingComments = [];
1814 for (i = lastChild.leadingComments.length - 1; i >= 0; --i) {
1815 comment = lastChild.leadingComments[i];
1816 if (comment.range[1] <= this.range[0]) {
1817 leadingComments.unshift(comment);
1818 lastChild.leadingComments.splice(i, 1);
1822 if (!lastChild.leadingComments.length) {
1823 lastChild.leadingComments = undefined;
1826 } else if (extra.leadingComments.length > 0) {
1827 leadingComments = [];
1828 for (i = extra.leadingComments.length - 1; i >= 0; --i) {
1829 comment = extra.leadingComments[i];
1830 if (comment.range[1] <= this.range[0]) {
1831 leadingComments.unshift(comment);
1832 extra.leadingComments.splice(i, 1);
1838 if (leadingComments && leadingComments.length > 0) {
1839 this.leadingComments = leadingComments;
1841 if (trailingComments && trailingComments.length > 0) {
1842 this.trailingComments = trailingComments;
1845 bottomRight.push(this);
1848 finish: function () {
1850 this.range[1] = lastIndex;
1854 line: lastLineNumber,
1855 column: lastIndex - lastLineStart
1858 this.loc.source = extra.source;
1862 if (extra.attachComment) {
1863 this.processComment();
1867 finishArrayExpression: function (elements) {
1868 this.type = Syntax.ArrayExpression;
1869 this.elements = elements;
1874 finishArrayPattern: function (elements) {
1875 this.type = Syntax.ArrayPattern;
1876 this.elements = elements;
1881 finishArrowFunctionExpression: function (params, defaults, body, expression) {
1882 this.type = Syntax.ArrowFunctionExpression;
1884 this.params = params;
1885 this.defaults = defaults;
1887 this.generator = false;
1888 this.expression = expression;
1893 finishAssignmentExpression: function (operator, left, right) {
1894 this.type = Syntax.AssignmentExpression;
1895 this.operator = operator;
1902 finishAssignmentPattern: function (left, right) {
1903 this.type = Syntax.AssignmentPattern;
1910 finishBinaryExpression: function (operator, left, right) {
1911 this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression;
1912 this.operator = operator;
1919 finishBlockStatement: function (body) {
1920 this.type = Syntax.BlockStatement;
1926 finishBreakStatement: function (label) {
1927 this.type = Syntax.BreakStatement;
1933 finishCallExpression: function (callee, args) {
1934 this.type = Syntax.CallExpression;
1935 this.callee = callee;
1936 this.arguments = args;
1941 finishCatchClause: function (param, body) {
1942 this.type = Syntax.CatchClause;
1949 finishClassBody: function (body) {
1950 this.type = Syntax.ClassBody;
1956 finishClassDeclaration: function (id, superClass, body) {
1957 this.type = Syntax.ClassDeclaration;
1959 this.superClass = superClass;
1965 finishClassExpression: function (id, superClass, body) {
1966 this.type = Syntax.ClassExpression;
1968 this.superClass = superClass;
1974 finishConditionalExpression: function (test, consequent, alternate) {
1975 this.type = Syntax.ConditionalExpression;
1977 this.consequent = consequent;
1978 this.alternate = alternate;
1983 finishContinueStatement: function (label) {
1984 this.type = Syntax.ContinueStatement;
1990 finishDebuggerStatement: function () {
1991 this.type = Syntax.DebuggerStatement;
1996 finishDoWhileStatement: function (body, test) {
1997 this.type = Syntax.DoWhileStatement;
2004 finishEmptyStatement: function () {
2005 this.type = Syntax.EmptyStatement;
2010 finishExpressionStatement: function (expression) {
2011 this.type = Syntax.ExpressionStatement;
2012 this.expression = expression;
2017 finishForStatement: function (init, test, update, body) {
2018 this.type = Syntax.ForStatement;
2021 this.update = update;
2027 finishForOfStatement: function (left, right, body) {
2028 this.type = Syntax.ForOfStatement;
2036 finishForInStatement: function (left, right, body) {
2037 this.type = Syntax.ForInStatement;
2046 finishFunctionDeclaration: function (id, params, defaults, body, generator) {
2047 this.type = Syntax.FunctionDeclaration;
2049 this.params = params;
2050 this.defaults = defaults;
2052 this.generator = generator;
2053 this.expression = false;
2058 finishFunctionExpression: function (id, params, defaults, body, generator) {
2059 this.type = Syntax.FunctionExpression;
2061 this.params = params;
2062 this.defaults = defaults;
2064 this.generator = generator;
2065 this.expression = false;
2070 finishIdentifier: function (name) {
2071 this.type = Syntax.Identifier;
2077 finishIfStatement: function (test, consequent, alternate) {
2078 this.type = Syntax.IfStatement;
2080 this.consequent = consequent;
2081 this.alternate = alternate;
2086 finishLabeledStatement: function (label, body) {
2087 this.type = Syntax.LabeledStatement;
2094 finishLiteral: function (token) {
2095 this.type = Syntax.Literal;
2096 this.value = token.value;
2097 this.raw = source.slice(token.start, token.end);
2099 this.regex = token.regex;
2105 finishMemberExpression: function (accessor, object, property) {
2106 this.type = Syntax.MemberExpression;
2107 this.computed = accessor === '[';
2108 this.object = object;
2109 this.property = property;
2114 finishMetaProperty: function (meta, property) {
2115 this.type = Syntax.MetaProperty;
2117 this.property = property;
2122 finishNewExpression: function (callee, args) {
2123 this.type = Syntax.NewExpression;
2124 this.callee = callee;
2125 this.arguments = args;
2130 finishObjectExpression: function (properties) {
2131 this.type = Syntax.ObjectExpression;
2132 this.properties = properties;
2137 finishObjectPattern: function (properties) {
2138 this.type = Syntax.ObjectPattern;
2139 this.properties = properties;
2144 finishPostfixExpression: function (operator, argument) {
2145 this.type = Syntax.UpdateExpression;
2146 this.operator = operator;
2147 this.argument = argument;
2148 this.prefix = false;
2153 finishProgram: function (body, sourceType) {
2154 this.type = Syntax.Program;
2156 this.sourceType = sourceType;
2161 finishProperty: function (kind, key, computed, value, method, shorthand) {
2162 this.type = Syntax.Property;
2164 this.computed = computed;
2167 this.method = method;
2168 this.shorthand = shorthand;
2173 finishRestElement: function (argument) {
2174 this.type = Syntax.RestElement;
2175 this.argument = argument;
2180 finishReturnStatement: function (argument) {
2181 this.type = Syntax.ReturnStatement;
2182 this.argument = argument;
2187 finishSequenceExpression: function (expressions) {
2188 this.type = Syntax.SequenceExpression;
2189 this.expressions = expressions;
2194 finishSpreadElement: function (argument) {
2195 this.type = Syntax.SpreadElement;
2196 this.argument = argument;
2201 finishSwitchCase: function (test, consequent) {
2202 this.type = Syntax.SwitchCase;
2204 this.consequent = consequent;
2209 finishSuper: function () {
2210 this.type = Syntax.Super;
2215 finishSwitchStatement: function (discriminant, cases) {
2216 this.type = Syntax.SwitchStatement;
2217 this.discriminant = discriminant;
2223 finishTaggedTemplateExpression: function (tag, quasi) {
2224 this.type = Syntax.TaggedTemplateExpression;
2231 finishTemplateElement: function (value, tail) {
2232 this.type = Syntax.TemplateElement;
2239 finishTemplateLiteral: function (quasis, expressions) {
2240 this.type = Syntax.TemplateLiteral;
2241 this.quasis = quasis;
2242 this.expressions = expressions;
2247 finishThisExpression: function () {
2248 this.type = Syntax.ThisExpression;
2253 finishThrowStatement: function (argument) {
2254 this.type = Syntax.ThrowStatement;
2255 this.argument = argument;
2260 finishTryStatement: function (block, handler, finalizer) {
2261 this.type = Syntax.TryStatement;
2263 this.guardedHandlers = [];
2264 this.handlers = handler ? [handler] : [];
2265 this.handler = handler;
2266 this.finalizer = finalizer;
2271 finishUnaryExpression: function (operator, argument) {
2272 this.type = (operator === '++' || operator === '--') ? Syntax.UpdateExpression : Syntax.UnaryExpression;
2273 this.operator = operator;
2274 this.argument = argument;
2280 finishVariableDeclaration: function (declarations) {
2281 this.type = Syntax.VariableDeclaration;
2282 this.declarations = declarations;
2288 finishLexicalDeclaration: function (declarations, kind) {
2289 this.type = Syntax.VariableDeclaration;
2290 this.declarations = declarations;
2296 finishVariableDeclarator: function (id, init) {
2297 this.type = Syntax.VariableDeclarator;
2304 finishWhileStatement: function (test, body) {
2305 this.type = Syntax.WhileStatement;
2312 finishWithStatement: function (object, body) {
2313 this.type = Syntax.WithStatement;
2314 this.object = object;
2320 finishExportSpecifier: function (local, exported) {
2321 this.type = Syntax.ExportSpecifier;
2322 this.exported = exported || local;
2328 finishImportDefaultSpecifier: function (local) {
2329 this.type = Syntax.ImportDefaultSpecifier;
2335 finishImportNamespaceSpecifier: function (local) {
2336 this.type = Syntax.ImportNamespaceSpecifier;
2342 finishExportNamedDeclaration: function (declaration, specifiers, src) {
2343 this.type = Syntax.ExportNamedDeclaration;
2344 this.declaration = declaration;
2345 this.specifiers = specifiers;
2351 finishExportDefaultDeclaration: function (declaration) {
2352 this.type = Syntax.ExportDefaultDeclaration;
2353 this.declaration = declaration;
2358 finishExportAllDeclaration: function (src) {
2359 this.type = Syntax.ExportAllDeclaration;
2365 finishImportSpecifier: function (local, imported) {
2366 this.type = Syntax.ImportSpecifier;
2367 this.local = local || imported;
2368 this.imported = imported;
2373 finishImportDeclaration: function (specifiers, src) {
2374 this.type = Syntax.ImportDeclaration;
2375 this.specifiers = specifiers;
2381 finishYieldExpression: function (argument, delegate) {
2382 this.type = Syntax.YieldExpression;
2383 this.argument = argument;
2384 this.delegate = delegate;
2391 function recordError(error) {
2394 for (e = 0; e < extra.errors.length; e++) {
2395 existing = extra.errors[e];
2396 // Prevent duplicated error.
2397 /* istanbul ignore next */
2398 if (existing.index === error.index && existing.message === error.message) {
2403 extra.errors.push(error);
2406 function constructError(msg, column) {
2407 var error = new Error(msg);
2411 /* istanbul ignore else */
2412 if (Object.create && Object.defineProperty) {
2413 error = Object.create(base);
2414 Object.defineProperty(error, 'column', { value: column });
2421 function createError(line, pos, description) {
2422 var msg, column, error;
2424 msg = 'Line ' + line + ': ' + description;
2425 column = pos - (scanning ? lineStart : lastLineStart) + 1;
2426 error = constructError(msg, column);
2427 error.lineNumber = line;
2428 error.description = description;
2433 // Throw an exception
2435 function throwError(messageFormat) {
2438 args = Array.prototype.slice.call(arguments, 1);
2439 msg = messageFormat.replace(/%(\d)/g,
2440 function (whole, idx) {
2441 assert(idx < args.length, 'Message reference must be in range');
2446 throw createError(lastLineNumber, lastIndex, msg);
2449 function tolerateError(messageFormat) {
2450 var args, msg, error;
2452 args = Array.prototype.slice.call(arguments, 1);
2453 /* istanbul ignore next */
2454 msg = messageFormat.replace(/%(\d)/g,
2455 function (whole, idx) {
2456 assert(idx < args.length, 'Message reference must be in range');
2461 error = createError(lineNumber, lastIndex, msg);
2469 // Throw an exception because of the token.
2471 function unexpectedTokenError(token, message) {
2472 var value, msg = message || Messages.UnexpectedToken;
2476 msg = (token.type === Token.EOF) ? Messages.UnexpectedEOS :
2477 (token.type === Token.Identifier) ? Messages.UnexpectedIdentifier :
2478 (token.type === Token.NumericLiteral) ? Messages.UnexpectedNumber :
2479 (token.type === Token.StringLiteral) ? Messages.UnexpectedString :
2480 (token.type === Token.Template) ? Messages.UnexpectedTemplate :
2481 Messages.UnexpectedToken;
2483 if (token.type === Token.Keyword) {
2484 if (isFutureReservedWord(token.value)) {
2485 msg = Messages.UnexpectedReserved;
2486 } else if (strict && isStrictModeReservedWord(token.value)) {
2487 msg = Messages.StrictReservedWord;
2492 value = (token.type === Token.Template) ? token.value.raw : token.value;
2497 msg = msg.replace('%0', value);
2499 return (token && typeof token.lineNumber === 'number') ?
2500 createError(token.lineNumber, token.start, msg) :
2501 createError(scanning ? lineNumber : lastLineNumber, scanning ? index : lastIndex, msg);
2504 function throwUnexpectedToken(token, message) {
2505 throw unexpectedTokenError(token, message);
2508 function tolerateUnexpectedToken(token, message) {
2509 var error = unexpectedTokenError(token, message);
2517 // Expect the next token to match the specified punctuator.
2518 // If not, an exception will be thrown.
2520 function expect(value) {
2522 if (token.type !== Token.Punctuator || token.value !== value) {
2523 throwUnexpectedToken(token);
2528 * @name expectCommaSeparator
2529 * @description Quietly expect a comma when in tolerant mode, otherwise delegates
2530 * to <code>expect(value)</code>
2533 function expectCommaSeparator() {
2538 if (token.type === Token.Punctuator && token.value === ',') {
2540 } else if (token.type === Token.Punctuator && token.value === ';') {
2542 tolerateUnexpectedToken(token);
2544 tolerateUnexpectedToken(token, Messages.UnexpectedToken);
2551 // Expect the next token to match the specified keyword.
2552 // If not, an exception will be thrown.
2554 function expectKeyword(keyword) {
2556 if (token.type !== Token.Keyword || token.value !== keyword) {
2557 throwUnexpectedToken(token);
2561 // Return true if the next token matches the specified punctuator.
2563 function match(value) {
2564 return lookahead.type === Token.Punctuator && lookahead.value === value;
2567 // Return true if the next token matches the specified keyword
2569 function matchKeyword(keyword) {
2570 return lookahead.type === Token.Keyword && lookahead.value === keyword;
2573 // Return true if the next token matches the specified contextual keyword
2574 // (where an identifier is sometimes a keyword depending on the context)
2576 function matchContextualKeyword(keyword) {
2577 return lookahead.type === Token.Identifier && lookahead.value === keyword;
2580 // Return true if the next token is an assignment operator
2582 function matchAssign() {
2585 if (lookahead.type !== Token.Punctuator) {
2588 op = lookahead.value;
2589 return op === '=' ||
2603 function consumeSemicolon() {
2604 // Catch the very common case first: immediately a semicolon (U+003B).
2605 if (source.charCodeAt(startIndex) === 0x3B || match(';')) {
2610 if (hasLineTerminator) {
2614 // FIXME(ikarienator): this is seemingly an issue in the previous location info convention.
2615 lastIndex = startIndex;
2616 lastLineNumber = startLineNumber;
2617 lastLineStart = startLineStart;
2619 if (lookahead.type !== Token.EOF && !match('}')) {
2620 throwUnexpectedToken(lookahead);
2624 // Cover grammar support.
2626 // When an assignment expression position starts with an left parenthesis, the determination of the type
2627 // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead)
2628 // or the first comma. This situation also defers the determination of all the expressions nested in the pair.
2630 // There are three productions that can be parsed in a parentheses pair that needs to be determined
2631 // after the outermost pair is closed. They are:
2633 // 1. AssignmentExpression
2634 // 2. BindingElements
2635 // 3. AssignmentTargets
2637 // In order to avoid exponential backtracking, we use two flags to denote if the production can be
2638 // binding element or assignment target.
2640 // The three productions have the relationship:
2642 // BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression
2644 // with a single exception that CoverInitializedName when used directly in an Expression, generates
2645 // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the
2646 // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair.
2648 // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not
2649 // effect the current flags. This means the production the parser parses is only used as an expression. Therefore
2650 // the CoverInitializedName check is conducted.
2652 // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates
2653 // the flags outside of the parser. This means the production the parser parses is used as a part of a potential
2654 // pattern. The CoverInitializedName check is deferred.
2655 function isolateCoverGrammar(parser) {
2656 var oldIsBindingElement = isBindingElement,
2657 oldIsAssignmentTarget = isAssignmentTarget,
2658 oldFirstCoverInitializedNameError = firstCoverInitializedNameError,
2660 isBindingElement = true;
2661 isAssignmentTarget = true;
2662 firstCoverInitializedNameError = null;
2664 if (firstCoverInitializedNameError !== null) {
2665 throwUnexpectedToken(firstCoverInitializedNameError);
2667 isBindingElement = oldIsBindingElement;
2668 isAssignmentTarget = oldIsAssignmentTarget;
2669 firstCoverInitializedNameError = oldFirstCoverInitializedNameError;
2673 function inheritCoverGrammar(parser) {
2674 var oldIsBindingElement = isBindingElement,
2675 oldIsAssignmentTarget = isAssignmentTarget,
2676 oldFirstCoverInitializedNameError = firstCoverInitializedNameError,
2678 isBindingElement = true;
2679 isAssignmentTarget = true;
2680 firstCoverInitializedNameError = null;
2682 isBindingElement = isBindingElement && oldIsBindingElement;
2683 isAssignmentTarget = isAssignmentTarget && oldIsAssignmentTarget;
2684 firstCoverInitializedNameError = oldFirstCoverInitializedNameError || firstCoverInitializedNameError;
2688 // ECMA-262 13.3.3 Destructuring Binding Patterns
2690 function parseArrayPattern(params, kind) {
2691 var node = new Node(), elements = [], rest, restNode;
2694 while (!match(']')) {
2697 elements.push(null);
2700 restNode = new Node();
2702 params.push(lookahead);
2703 rest = parseVariableIdentifier(kind);
2704 elements.push(restNode.finishRestElement(rest));
2707 elements.push(parsePatternWithDefault(params, kind));
2718 return node.finishArrayPattern(elements);
2721 function parsePropertyPattern(params, kind) {
2722 var node = new Node(), key, keyToken, computed = match('['), init;
2723 if (lookahead.type === Token.Identifier) {
2724 keyToken = lookahead;
2725 key = parseVariableIdentifier();
2727 params.push(keyToken);
2729 init = parseAssignmentExpression();
2731 return node.finishProperty(
2733 new WrappingNode(keyToken).finishAssignmentPattern(key, init), false, true);
2734 } else if (!match(':')) {
2735 params.push(keyToken);
2736 return node.finishProperty('init', key, false, key, false, true);
2739 key = parseObjectPropertyKey();
2742 init = parsePatternWithDefault(params, kind);
2743 return node.finishProperty('init', key, computed, init, false, false);
2746 function parseObjectPattern(params, kind) {
2747 var node = new Node(), properties = [];
2751 while (!match('}')) {
2752 properties.push(parsePropertyPattern(params, kind));
2760 return node.finishObjectPattern(properties);
2763 function parsePattern(params, kind) {
2765 return parseArrayPattern(params, kind);
2766 } else if (match('{')) {
2767 return parseObjectPattern(params, kind);
2768 } else if (matchKeyword('let')) {
2769 if (kind === 'const' || kind === 'let') {
2770 tolerateUnexpectedToken(lookahead, Messages.UnexpectedToken);
2774 params.push(lookahead);
2775 return parseVariableIdentifier(kind);
2778 function parsePatternWithDefault(params, kind) {
2779 var startToken = lookahead, pattern, previousAllowYield, right;
2780 pattern = parsePattern(params, kind);
2783 previousAllowYield = state.allowYield;
2784 state.allowYield = true;
2785 right = isolateCoverGrammar(parseAssignmentExpression);
2786 state.allowYield = previousAllowYield;
2787 pattern = new WrappingNode(startToken).finishAssignmentPattern(pattern, right);
2792 // ECMA-262 12.2.5 Array Initializer
2794 function parseArrayInitializer() {
2795 var elements = [], node = new Node(), restSpread;
2799 while (!match(']')) {
2802 elements.push(null);
2803 } else if (match('...')) {
2804 restSpread = new Node();
2806 restSpread.finishSpreadElement(inheritCoverGrammar(parseAssignmentExpression));
2809 isAssignmentTarget = isBindingElement = false;
2812 elements.push(restSpread);
2814 elements.push(inheritCoverGrammar(parseAssignmentExpression));
2824 return node.finishArrayExpression(elements);
2827 // ECMA-262 12.2.6 Object Initializer
2829 function parsePropertyFunction(node, paramInfo, isGenerator) {
2830 var previousStrict, body;
2832 isAssignmentTarget = isBindingElement = false;
2834 previousStrict = strict;
2835 body = isolateCoverGrammar(parseFunctionSourceElements);
2837 if (strict && paramInfo.firstRestricted) {
2838 tolerateUnexpectedToken(paramInfo.firstRestricted, paramInfo.message);
2840 if (strict && paramInfo.stricted) {
2841 tolerateUnexpectedToken(paramInfo.stricted, paramInfo.message);
2844 strict = previousStrict;
2845 return node.finishFunctionExpression(null, paramInfo.params, paramInfo.defaults, body, isGenerator);
2848 function parsePropertyMethodFunction() {
2849 var params, method, node = new Node(),
2850 previousAllowYield = state.allowYield;
2852 state.allowYield = false;
2853 params = parseParams();
2854 state.allowYield = previousAllowYield;
2856 state.allowYield = false;
2857 method = parsePropertyFunction(node, params, false);
2858 state.allowYield = previousAllowYield;
2863 function parseObjectPropertyKey() {
2864 var token, node = new Node(), expr;
2868 // Note: This function is called only from parseObjectProperty(), where
2869 // EOF and Punctuator tokens are already filtered out.
2871 switch (token.type) {
2872 case Token.StringLiteral:
2873 case Token.NumericLiteral:
2874 if (strict && token.octal) {
2875 tolerateUnexpectedToken(token, Messages.StrictOctalLiteral);
2877 return node.finishLiteral(token);
2878 case Token.Identifier:
2879 case Token.BooleanLiteral:
2880 case Token.NullLiteral:
2882 return node.finishIdentifier(token.value);
2883 case Token.Punctuator:
2884 if (token.value === '[') {
2885 expr = isolateCoverGrammar(parseAssignmentExpression);
2891 throwUnexpectedToken(token);
2894 function lookaheadPropertyName() {
2895 switch (lookahead.type) {
2896 case Token.Identifier:
2897 case Token.StringLiteral:
2898 case Token.BooleanLiteral:
2899 case Token.NullLiteral:
2900 case Token.NumericLiteral:
2903 case Token.Punctuator:
2904 return lookahead.value === '[';
2909 // This function is to try to parse a MethodDefinition as defined in 14.3. But in the case of object literals,
2910 // it might be called at a position where there is in fact a short hand identifier pattern or a data property.
2911 // This can only be determined after we consumed up to the left parentheses.
2913 // In order to avoid back tracking, it returns `null` if the position is not a MethodDefinition and the caller
2914 // is responsible to visit other options.
2915 function tryParseMethodDefinition(token, key, computed, node) {
2916 var value, options, methodNode, params,
2917 previousAllowYield = state.allowYield;
2919 if (token.type === Token.Identifier) {
2920 // check for `get` and `set`;
2922 if (token.value === 'get' && lookaheadPropertyName()) {
2923 computed = match('[');
2924 key = parseObjectPropertyKey();
2925 methodNode = new Node();
2929 state.allowYield = false;
2930 value = parsePropertyFunction(methodNode, {
2934 firstRestricted: null,
2937 state.allowYield = previousAllowYield;
2939 return node.finishProperty('get', key, computed, value, false, false);
2940 } else if (token.value === 'set' && lookaheadPropertyName()) {
2941 computed = match('[');
2942 key = parseObjectPropertyKey();
2943 methodNode = new Node();
2950 firstRestricted: null,
2954 tolerateUnexpectedToken(lookahead);
2956 state.allowYield = false;
2957 parseParam(options);
2958 state.allowYield = previousAllowYield;
2959 if (options.defaultCount === 0) {
2960 options.defaults = [];
2965 state.allowYield = false;
2966 value = parsePropertyFunction(methodNode, options, false);
2967 state.allowYield = previousAllowYield;
2969 return node.finishProperty('set', key, computed, value, false, false);
2971 } else if (token.type === Token.Punctuator && token.value === '*' && lookaheadPropertyName()) {
2972 computed = match('[');
2973 key = parseObjectPropertyKey();
2974 methodNode = new Node();
2976 state.allowYield = true;
2977 params = parseParams();
2978 state.allowYield = previousAllowYield;
2980 state.allowYield = false;
2981 value = parsePropertyFunction(methodNode, params, true);
2982 state.allowYield = previousAllowYield;
2984 return node.finishProperty('init', key, computed, value, true, false);
2987 if (key && match('(')) {
2988 value = parsePropertyMethodFunction();
2989 return node.finishProperty('init', key, computed, value, true, false);
2992 // Not a MethodDefinition.
2996 function parseObjectProperty(hasProto) {
2997 var token = lookahead, node = new Node(), computed, key, maybeMethod, proto, value;
2999 computed = match('[');
3003 key = parseObjectPropertyKey();
3005 maybeMethod = tryParseMethodDefinition(token, key, computed, node);
3011 throwUnexpectedToken(lookahead);
3014 // Check for duplicated __proto__
3016 proto = (key.type === Syntax.Identifier && key.name === '__proto__') ||
3017 (key.type === Syntax.Literal && key.value === '__proto__');
3018 if (hasProto.value && proto) {
3019 tolerateError(Messages.DuplicateProtoProperty);
3021 hasProto.value |= proto;
3026 value = inheritCoverGrammar(parseAssignmentExpression);
3027 return node.finishProperty('init', key, computed, value, false, false);
3030 if (token.type === Token.Identifier) {
3032 firstCoverInitializedNameError = lookahead;
3034 value = isolateCoverGrammar(parseAssignmentExpression);
3035 return node.finishProperty('init', key, computed,
3036 new WrappingNode(token).finishAssignmentPattern(key, value), false, true);
3038 return node.finishProperty('init', key, computed, key, false, true);
3041 throwUnexpectedToken(lookahead);
3044 function parseObjectInitializer() {
3045 var properties = [], hasProto = {value: false}, node = new Node();
3049 while (!match('}')) {
3050 properties.push(parseObjectProperty(hasProto));
3053 expectCommaSeparator();
3059 return node.finishObjectExpression(properties);
3062 function reinterpretExpressionAsPattern(expr) {
3064 switch (expr.type) {
3065 case Syntax.Identifier:
3066 case Syntax.MemberExpression:
3067 case Syntax.RestElement:
3068 case Syntax.AssignmentPattern:
3070 case Syntax.SpreadElement:
3071 expr.type = Syntax.RestElement;
3072 reinterpretExpressionAsPattern(expr.argument);
3074 case Syntax.ArrayExpression:
3075 expr.type = Syntax.ArrayPattern;
3076 for (i = 0; i < expr.elements.length; i++) {
3077 if (expr.elements[i] !== null) {
3078 reinterpretExpressionAsPattern(expr.elements[i]);
3082 case Syntax.ObjectExpression:
3083 expr.type = Syntax.ObjectPattern;
3084 for (i = 0; i < expr.properties.length; i++) {
3085 reinterpretExpressionAsPattern(expr.properties[i].value);
3088 case Syntax.AssignmentExpression:
3089 expr.type = Syntax.AssignmentPattern;
3090 reinterpretExpressionAsPattern(expr.left);
3093 // Allow other node type for tolerant parsing.
3098 // ECMA-262 12.2.9 Template Literals
3100 function parseTemplateElement(option) {
3103 if (lookahead.type !== Token.Template || (option.head && !lookahead.head)) {
3104 throwUnexpectedToken();
3110 return node.finishTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail);
3113 function parseTemplateLiteral() {
3114 var quasi, quasis, expressions, node = new Node();
3116 quasi = parseTemplateElement({ head: true });
3120 while (!quasi.tail) {
3121 expressions.push(parseExpression());
3122 quasi = parseTemplateElement({ head: false });
3126 return node.finishTemplateLiteral(quasis, expressions);
3129 // ECMA-262 12.2.10 The Grouping Operator
3131 function parseGroupExpression() {
3132 var expr, expressions, startToken, i, params = [];
3142 type: PlaceHolders.ArrowParameterPlaceHolder,
3148 startToken = lookahead;
3150 expr = parseRestElement(params);
3156 type: PlaceHolders.ArrowParameterPlaceHolder,
3161 isBindingElement = true;
3162 expr = inheritCoverGrammar(parseAssignmentExpression);
3165 isAssignmentTarget = false;
3166 expressions = [expr];
3168 while (startIndex < length) {
3175 if (!isBindingElement) {
3176 throwUnexpectedToken(lookahead);
3178 expressions.push(parseRestElement(params));
3183 isBindingElement = false;
3184 for (i = 0; i < expressions.length; i++) {
3185 reinterpretExpressionAsPattern(expressions[i]);
3188 type: PlaceHolders.ArrowParameterPlaceHolder,
3193 expressions.push(inheritCoverGrammar(parseAssignmentExpression));
3196 expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
3203 if (expr.type === Syntax.Identifier && expr.name === 'yield') {
3205 type: PlaceHolders.ArrowParameterPlaceHolder,
3210 if (!isBindingElement) {
3211 throwUnexpectedToken(lookahead);
3214 if (expr.type === Syntax.SequenceExpression) {
3215 for (i = 0; i < expr.expressions.length; i++) {
3216 reinterpretExpressionAsPattern(expr.expressions[i]);
3219 reinterpretExpressionAsPattern(expr);
3223 type: PlaceHolders.ArrowParameterPlaceHolder,
3224 params: expr.type === Syntax.SequenceExpression ? expr.expressions : [expr]
3227 isBindingElement = false;
3232 // ECMA-262 12.2 Primary Expressions
3234 function parsePrimaryExpression() {
3235 var type, token, expr, node;
3238 isBindingElement = false;
3239 return inheritCoverGrammar(parseGroupExpression);
3243 return inheritCoverGrammar(parseArrayInitializer);
3247 return inheritCoverGrammar(parseObjectInitializer);
3250 type = lookahead.type;
3253 if (type === Token.Identifier) {
3254 if (state.sourceType === 'module' && lookahead.value === 'await') {
3255 tolerateUnexpectedToken(lookahead);
3257 expr = node.finishIdentifier(lex().value);
3258 } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
3259 isAssignmentTarget = isBindingElement = false;
3260 if (strict && lookahead.octal) {
3261 tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral);
3263 expr = node.finishLiteral(lex());
3264 } else if (type === Token.Keyword) {
3265 if (!strict && state.allowYield && matchKeyword('yield')) {
3266 return parseNonComputedProperty();
3268 if (!strict && matchKeyword('let')) {
3269 return node.finishIdentifier(lex().value);
3271 isAssignmentTarget = isBindingElement = false;
3272 if (matchKeyword('function')) {
3273 return parseFunctionExpression();
3275 if (matchKeyword('this')) {
3277 return node.finishThisExpression();
3279 if (matchKeyword('class')) {
3280 return parseClassExpression();
3282 throwUnexpectedToken(lex());
3283 } else if (type === Token.BooleanLiteral) {
3284 isAssignmentTarget = isBindingElement = false;
3286 token.value = (token.value === 'true');
3287 expr = node.finishLiteral(token);
3288 } else if (type === Token.NullLiteral) {
3289 isAssignmentTarget = isBindingElement = false;
3292 expr = node.finishLiteral(token);
3293 } else if (match('/') || match('/=')) {
3294 isAssignmentTarget = isBindingElement = false;
3297 if (typeof extra.tokens !== 'undefined') {
3298 token = collectRegex();
3300 token = scanRegExp();
3303 expr = node.finishLiteral(token);
3304 } else if (type === Token.Template) {
3305 expr = parseTemplateLiteral();
3307 throwUnexpectedToken(lex());
3313 // ECMA-262 12.3 Left-Hand-Side Expressions
3315 function parseArguments() {
3316 var args = [], expr;
3321 while (startIndex < length) {
3325 expr.finishSpreadElement(isolateCoverGrammar(parseAssignmentExpression));
3327 expr = isolateCoverGrammar(parseAssignmentExpression);
3333 expectCommaSeparator();
3342 function parseNonComputedProperty() {
3343 var token, node = new Node();
3347 if (!isIdentifierName(token)) {
3348 throwUnexpectedToken(token);
3351 return node.finishIdentifier(token.value);
3354 function parseNonComputedMember() {
3357 return parseNonComputedProperty();
3360 function parseComputedMember() {
3365 expr = isolateCoverGrammar(parseExpression);
3372 // ECMA-262 12.3.3 The new Operator
3374 function parseNewExpression() {
3375 var callee, args, node = new Node();
3377 expectKeyword('new');
3381 if (lookahead.type === Token.Identifier && lookahead.value === 'target') {
3382 if (state.inFunctionBody) {
3384 return node.finishMetaProperty('new', 'target');
3387 throwUnexpectedToken(lookahead);
3390 callee = isolateCoverGrammar(parseLeftHandSideExpression);
3391 args = match('(') ? parseArguments() : [];
3393 isAssignmentTarget = isBindingElement = false;
3395 return node.finishNewExpression(callee, args);
3398 // ECMA-262 12.3.4 Function Calls
3400 function parseLeftHandSideExpressionAllowCall() {
3401 var quasi, expr, args, property, startToken, previousAllowIn = state.allowIn;
3403 startToken = lookahead;
3404 state.allowIn = true;
3406 if (matchKeyword('super') && state.inFunctionBody) {
3409 expr = expr.finishSuper();
3410 if (!match('(') && !match('.') && !match('[')) {
3411 throwUnexpectedToken(lookahead);
3414 expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression);
3419 isBindingElement = false;
3420 isAssignmentTarget = true;
3421 property = parseNonComputedMember();
3422 expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
3423 } else if (match('(')) {
3424 isBindingElement = false;
3425 isAssignmentTarget = false;
3426 args = parseArguments();
3427 expr = new WrappingNode(startToken).finishCallExpression(expr, args);
3428 } else if (match('[')) {
3429 isBindingElement = false;
3430 isAssignmentTarget = true;
3431 property = parseComputedMember();
3432 expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
3433 } else if (lookahead.type === Token.Template && lookahead.head) {
3434 quasi = parseTemplateLiteral();
3435 expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi);
3440 state.allowIn = previousAllowIn;
3445 // ECMA-262 12.3 Left-Hand-Side Expressions
3447 function parseLeftHandSideExpression() {
3448 var quasi, expr, property, startToken;
3449 assert(state.allowIn, 'callee of new expression always allow in keyword.');
3451 startToken = lookahead;
3453 if (matchKeyword('super') && state.inFunctionBody) {
3456 expr = expr.finishSuper();
3457 if (!match('[') && !match('.')) {
3458 throwUnexpectedToken(lookahead);
3461 expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression);
3466 isBindingElement = false;
3467 isAssignmentTarget = true;
3468 property = parseComputedMember();
3469 expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
3470 } else if (match('.')) {
3471 isBindingElement = false;
3472 isAssignmentTarget = true;
3473 property = parseNonComputedMember();
3474 expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
3475 } else if (lookahead.type === Token.Template && lookahead.head) {
3476 quasi = parseTemplateLiteral();
3477 expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi);
3485 // ECMA-262 12.4 Postfix Expressions
3487 function parsePostfixExpression() {
3488 var expr, token, startToken = lookahead;
3490 expr = inheritCoverGrammar(parseLeftHandSideExpressionAllowCall);
3492 if (!hasLineTerminator && lookahead.type === Token.Punctuator) {
3493 if (match('++') || match('--')) {
3494 // ECMA-262 11.3.1, 11.3.2
3495 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
3496 tolerateError(Messages.StrictLHSPostfix);
3499 if (!isAssignmentTarget) {
3500 tolerateError(Messages.InvalidLHSInAssignment);
3503 isAssignmentTarget = isBindingElement = false;
3506 expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr);
3513 // ECMA-262 12.5 Unary Operators
3515 function parseUnaryExpression() {
3516 var token, expr, startToken;
3518 if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
3519 expr = parsePostfixExpression();
3520 } else if (match('++') || match('--')) {
3521 startToken = lookahead;
3523 expr = inheritCoverGrammar(parseUnaryExpression);
3524 // ECMA-262 11.4.4, 11.4.5
3525 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
3526 tolerateError(Messages.StrictLHSPrefix);
3529 if (!isAssignmentTarget) {
3530 tolerateError(Messages.InvalidLHSInAssignment);
3532 expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
3533 isAssignmentTarget = isBindingElement = false;
3534 } else if (match('+') || match('-') || match('~') || match('!')) {
3535 startToken = lookahead;
3537 expr = inheritCoverGrammar(parseUnaryExpression);
3538 expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
3539 isAssignmentTarget = isBindingElement = false;
3540 } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
3541 startToken = lookahead;
3543 expr = inheritCoverGrammar(parseUnaryExpression);
3544 expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
3545 if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
3546 tolerateError(Messages.StrictDelete);
3548 isAssignmentTarget = isBindingElement = false;
3550 expr = parsePostfixExpression();
3556 function binaryPrecedence(token, allowIn) {
3559 if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
3563 switch (token.value) {
3600 prec = allowIn ? 7 : 0;
3627 // ECMA-262 12.6 Multiplicative Operators
3628 // ECMA-262 12.7 Additive Operators
3629 // ECMA-262 12.8 Bitwise Shift Operators
3630 // ECMA-262 12.9 Relational Operators
3631 // ECMA-262 12.10 Equality Operators
3632 // ECMA-262 12.11 Binary Bitwise Operators
3633 // ECMA-262 12.12 Binary Logical Operators
3635 function parseBinaryExpression() {
3636 var marker, markers, expr, token, prec, stack, right, operator, left, i;
3639 left = inheritCoverGrammar(parseUnaryExpression);
3642 prec = binaryPrecedence(token, state.allowIn);
3646 isAssignmentTarget = isBindingElement = false;
3650 markers = [marker, lookahead];
3651 right = isolateCoverGrammar(parseUnaryExpression);
3653 stack = [left, token, right];
3655 while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) {
3657 // Reduce: make a binary expression from the three topmost entries.
3658 while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
3659 right = stack.pop();
3660 operator = stack.pop().value;
3663 expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right);
3671 markers.push(lookahead);
3672 expr = isolateCoverGrammar(parseUnaryExpression);
3676 // Final reduce to clean-up the stack.
3677 i = stack.length - 1;
3681 expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
3689 // ECMA-262 12.13 Conditional Operator
3691 function parseConditionalExpression() {
3692 var expr, previousAllowIn, consequent, alternate, startToken;
3694 startToken = lookahead;
3696 expr = inheritCoverGrammar(parseBinaryExpression);
3699 previousAllowIn = state.allowIn;
3700 state.allowIn = true;
3701 consequent = isolateCoverGrammar(parseAssignmentExpression);
3702 state.allowIn = previousAllowIn;
3704 alternate = isolateCoverGrammar(parseAssignmentExpression);
3706 expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
3707 isAssignmentTarget = isBindingElement = false;
3713 // ECMA-262 14.2 Arrow Function Definitions
3715 function parseConciseBody() {
3717 return parseFunctionSourceElements();
3719 return isolateCoverGrammar(parseAssignmentExpression);
3722 function checkPatternParam(options, param) {
3724 switch (param.type) {
3725 case Syntax.Identifier:
3726 validateParam(options, param, param.name);
3728 case Syntax.RestElement:
3729 checkPatternParam(options, param.argument);
3731 case Syntax.AssignmentPattern:
3732 checkPatternParam(options, param.left);
3734 case Syntax.ArrayPattern:
3735 for (i = 0; i < param.elements.length; i++) {
3736 if (param.elements[i] !== null) {
3737 checkPatternParam(options, param.elements[i]);
3741 case Syntax.YieldExpression:
3744 assert(param.type === Syntax.ObjectPattern, 'Invalid type');
3745 for (i = 0; i < param.properties.length; i++) {
3746 checkPatternParam(options, param.properties[i].value);
3751 function reinterpretAsCoverFormalsList(expr) {
3752 var i, len, param, params, defaults, defaultCount, options, token;
3758 switch (expr.type) {
3759 case Syntax.Identifier:
3761 case PlaceHolders.ArrowParameterPlaceHolder:
3762 params = expr.params;
3772 for (i = 0, len = params.length; i < len; i += 1) {
3774 switch (param.type) {
3775 case Syntax.AssignmentPattern:
3776 params[i] = param.left;
3777 if (param.right.type === Syntax.YieldExpression) {
3778 if (param.right.argument) {
3779 throwUnexpectedToken(lookahead);
3781 param.right.type = Syntax.Identifier;
3782 param.right.name = 'yield';
3783 delete param.right.argument;
3784 delete param.right.delegate;
3786 defaults.push(param.right);
3788 checkPatternParam(options, param.left);
3791 checkPatternParam(options, param);
3793 defaults.push(null);
3798 if (strict || !state.allowYield) {
3799 for (i = 0, len = params.length; i < len; i += 1) {
3801 if (param.type === Syntax.YieldExpression) {
3802 throwUnexpectedToken(lookahead);
3807 if (options.message === Messages.StrictParamDupe) {
3808 token = strict ? options.stricted : options.firstRestricted;
3809 throwUnexpectedToken(token, options.message);
3812 if (defaultCount === 0) {
3819 stricted: options.stricted,
3820 firstRestricted: options.firstRestricted,
3821 message: options.message
3825 function parseArrowFunctionExpression(options, node) {
3826 var previousStrict, previousAllowYield, body;
3828 if (hasLineTerminator) {
3829 tolerateUnexpectedToken(lookahead);
3833 previousStrict = strict;
3834 previousAllowYield = state.allowYield;
3835 state.allowYield = true;
3837 body = parseConciseBody();
3839 if (strict && options.firstRestricted) {
3840 throwUnexpectedToken(options.firstRestricted, options.message);
3842 if (strict && options.stricted) {
3843 tolerateUnexpectedToken(options.stricted, options.message);
3846 strict = previousStrict;
3847 state.allowYield = previousAllowYield;
3849 return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement);
3852 // ECMA-262 14.4 Yield expression
3854 function parseYieldExpression() {
3855 var argument, expr, delegate, previousAllowYield;
3861 expectKeyword('yield');
3863 if (!hasLineTerminator) {
3864 previousAllowYield = state.allowYield;
3865 state.allowYield = false;
3866 delegate = match('*');
3869 argument = parseAssignmentExpression();
3871 if (!match(';') && !match('}') && !match(')') && lookahead.type !== Token.EOF) {
3872 argument = parseAssignmentExpression();
3875 state.allowYield = previousAllowYield;
3878 return expr.finishYieldExpression(argument, delegate);
3881 // ECMA-262 12.14 Assignment Operators
3883 function parseAssignmentExpression() {
3884 var token, expr, right, list, startToken;
3886 startToken = lookahead;
3889 if (!state.allowYield && matchKeyword('yield')) {
3890 return parseYieldExpression();
3893 expr = parseConditionalExpression();
3895 if (expr.type === PlaceHolders.ArrowParameterPlaceHolder || match('=>')) {
3896 isAssignmentTarget = isBindingElement = false;
3897 list = reinterpretAsCoverFormalsList(expr);
3900 firstCoverInitializedNameError = null;
3901 return parseArrowFunctionExpression(list, new WrappingNode(startToken));
3907 if (matchAssign()) {
3908 if (!isAssignmentTarget) {
3909 tolerateError(Messages.InvalidLHSInAssignment);
3913 if (strict && expr.type === Syntax.Identifier) {
3914 if (isRestrictedWord(expr.name)) {
3915 tolerateUnexpectedToken(token, Messages.StrictLHSAssignment);
3917 if (isStrictModeReservedWord(expr.name)) {
3918 tolerateUnexpectedToken(token, Messages.StrictReservedWord);
3923 isAssignmentTarget = isBindingElement = false;
3925 reinterpretExpressionAsPattern(expr);
3929 right = isolateCoverGrammar(parseAssignmentExpression);
3930 expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right);
3931 firstCoverInitializedNameError = null;
3937 // ECMA-262 12.15 Comma Operator
3939 function parseExpression() {
3940 var expr, startToken = lookahead, expressions;
3942 expr = isolateCoverGrammar(parseAssignmentExpression);
3945 expressions = [expr];
3947 while (startIndex < length) {
3952 expressions.push(isolateCoverGrammar(parseAssignmentExpression));
3955 expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
3961 // ECMA-262 13.2 Block
3963 function parseStatementListItem() {
3964 if (lookahead.type === Token.Keyword) {
3965 switch (lookahead.value) {
3967 if (state.sourceType !== 'module') {
3968 tolerateUnexpectedToken(lookahead, Messages.IllegalExportDeclaration);
3970 return parseExportDeclaration();
3972 if (state.sourceType !== 'module') {
3973 tolerateUnexpectedToken(lookahead, Messages.IllegalImportDeclaration);
3975 return parseImportDeclaration();
3977 return parseLexicalDeclaration({inFor: false});
3979 return parseFunctionDeclaration(new Node());
3981 return parseClassDeclaration();
3985 if (matchKeyword('let') && isLexicalDeclaration()) {
3986 return parseLexicalDeclaration({inFor: false});
3989 return parseStatement();
3992 function parseStatementList() {
3994 while (startIndex < length) {
3998 list.push(parseStatementListItem());
4004 function parseBlock() {
4005 var block, node = new Node();
4009 block = parseStatementList();
4013 return node.finishBlockStatement(block);
4016 // ECMA-262 13.3.2 Variable Statement
4018 function parseVariableIdentifier(kind) {
4019 var token, node = new Node();
4023 if (token.type === Token.Keyword && token.value === 'yield') {
4025 tolerateUnexpectedToken(token, Messages.StrictReservedWord);
4026 } if (!state.allowYield) {
4027 throwUnexpectedToken(token);
4029 } else if (token.type !== Token.Identifier) {
4030 if (strict && token.type === Token.Keyword && isStrictModeReservedWord(token.value)) {
4031 tolerateUnexpectedToken(token, Messages.StrictReservedWord);
4033 if (strict || token.value !== 'let' || kind !== 'var') {
4034 throwUnexpectedToken(token);
4037 } else if (state.sourceType === 'module' && token.type === Token.Identifier && token.value === 'await') {
4038 tolerateUnexpectedToken(token);
4041 return node.finishIdentifier(token.value);
4044 function parseVariableDeclaration(options) {
4045 var init = null, id, node = new Node(), params = [];
4047 id = parsePattern(params, 'var');
4050 if (strict && isRestrictedWord(id.name)) {
4051 tolerateError(Messages.StrictVarName);
4056 init = isolateCoverGrammar(parseAssignmentExpression);
4057 } else if (id.type !== Syntax.Identifier && !options.inFor) {
4061 return node.finishVariableDeclarator(id, init);
4064 function parseVariableDeclarationList(options) {
4067 opt = { inFor: options.inFor };
4068 list = [parseVariableDeclaration(opt)];
4070 while (match(',')) {
4072 list.push(parseVariableDeclaration(opt));
4078 function parseVariableStatement(node) {
4081 expectKeyword('var');
4083 declarations = parseVariableDeclarationList({ inFor: false });
4087 return node.finishVariableDeclaration(declarations);
4090 // ECMA-262 13.3.1 Let and Const Declarations
4092 function parseLexicalBinding(kind, options) {
4093 var init = null, id, node = new Node(), params = [];
4095 id = parsePattern(params, kind);
4098 if (strict && id.type === Syntax.Identifier && isRestrictedWord(id.name)) {
4099 tolerateError(Messages.StrictVarName);
4102 if (kind === 'const') {
4103 if (!matchKeyword('in') && !matchContextualKeyword('of')) {
4105 init = isolateCoverGrammar(parseAssignmentExpression);
4107 } else if ((!options.inFor && id.type !== Syntax.Identifier) || match('=')) {
4109 init = isolateCoverGrammar(parseAssignmentExpression);
4112 return node.finishVariableDeclarator(id, init);
4115 function parseBindingList(kind, options) {
4116 var list = [parseLexicalBinding(kind, options)];
4118 while (match(',')) {
4120 list.push(parseLexicalBinding(kind, options));
4127 function tokenizerState() {
4130 lineNumber: lineNumber,
4131 lineStart: lineStart,
4132 hasLineTerminator: hasLineTerminator,
4133 lastIndex: lastIndex,
4134 lastLineNumber: lastLineNumber,
4135 lastLineStart: lastLineStart,
4136 startIndex: startIndex,
4137 startLineNumber: startLineNumber,
4138 startLineStart: startLineStart,
4139 lookahead: lookahead,
4140 tokenCount: extra.tokens ? extra.tokens.length : 0
4144 function resetTokenizerState(ts) {
4146 lineNumber = ts.lineNumber;
4147 lineStart = ts.lineStart;
4148 hasLineTerminator = ts.hasLineTerminator;
4149 lastIndex = ts.lastIndex;
4150 lastLineNumber = ts.lastLineNumber;
4151 lastLineStart = ts.lastLineStart;
4152 startIndex = ts.startIndex;
4153 startLineNumber = ts.startLineNumber;
4154 startLineStart = ts.startLineStart;
4155 lookahead = ts.lookahead;
4157 extra.tokens.splice(ts.tokenCount, extra.tokens.length);
4161 function isLexicalDeclaration() {
4164 ts = tokenizerState();
4167 lexical = (lookahead.type === Token.Identifier) || match('[') || match('{') ||
4168 matchKeyword('let') || matchKeyword('yield');
4170 resetTokenizerState(ts);
4175 function parseLexicalDeclaration(options) {
4176 var kind, declarations, node = new Node();
4179 assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const');
4181 declarations = parseBindingList(kind, options);
4185 return node.finishLexicalDeclaration(declarations, kind);
4188 function parseRestElement(params) {
4189 var param, node = new Node();
4194 throwError(Messages.ObjectPatternAsRestParameter);
4197 params.push(lookahead);
4199 param = parseVariableIdentifier();
4202 throwError(Messages.DefaultRestParameter);
4206 throwError(Messages.ParameterAfterRestParameter);
4209 return node.finishRestElement(param);
4212 // ECMA-262 13.4 Empty Statement
4214 function parseEmptyStatement(node) {
4216 return node.finishEmptyStatement();
4219 // ECMA-262 12.4 Expression Statement
4221 function parseExpressionStatement(node) {
4222 var expr = parseExpression();
4224 return node.finishExpressionStatement(expr);
4227 // ECMA-262 13.6 If statement
4229 function parseIfStatement(node) {
4230 var test, consequent, alternate;
4232 expectKeyword('if');
4236 test = parseExpression();
4240 consequent = parseStatement();
4242 if (matchKeyword('else')) {
4244 alternate = parseStatement();
4249 return node.finishIfStatement(test, consequent, alternate);
4252 // ECMA-262 13.7 Iteration Statements
4254 function parseDoWhileStatement(node) {
4255 var body, test, oldInIteration;
4257 expectKeyword('do');
4259 oldInIteration = state.inIteration;
4260 state.inIteration = true;
4262 body = parseStatement();
4264 state.inIteration = oldInIteration;
4266 expectKeyword('while');
4270 test = parseExpression();
4278 return node.finishDoWhileStatement(body, test);
4281 function parseWhileStatement(node) {
4282 var test, body, oldInIteration;
4284 expectKeyword('while');
4288 test = parseExpression();
4292 oldInIteration = state.inIteration;
4293 state.inIteration = true;
4295 body = parseStatement();
4297 state.inIteration = oldInIteration;
4299 return node.finishWhileStatement(test, body);
4302 function parseForStatement(node) {
4303 var init, forIn, initSeq, initStartToken, test, update, left, right, kind, declarations,
4304 body, oldInIteration, previousAllowIn = state.allowIn;
4306 init = test = update = null;
4309 expectKeyword('for');
4316 if (matchKeyword('var')) {
4320 state.allowIn = false;
4321 declarations = parseVariableDeclarationList({ inFor: true });
4322 state.allowIn = previousAllowIn;
4324 if (declarations.length === 1 && matchKeyword('in')) {
4325 init = init.finishVariableDeclaration(declarations);
4328 right = parseExpression();
4330 } else if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) {
4331 init = init.finishVariableDeclaration(declarations);
4334 right = parseAssignmentExpression();
4338 init = init.finishVariableDeclaration(declarations);
4341 } else if (matchKeyword('const') || matchKeyword('let')) {
4345 if (!strict && lookahead.value === 'in') {
4346 init = init.finishIdentifier(kind);
4349 right = parseExpression();
4352 state.allowIn = false;
4353 declarations = parseBindingList(kind, {inFor: true});
4354 state.allowIn = previousAllowIn;
4356 if (declarations.length === 1 && declarations[0].init === null && matchKeyword('in')) {
4357 init = init.finishLexicalDeclaration(declarations, kind);
4360 right = parseExpression();
4362 } else if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) {
4363 init = init.finishLexicalDeclaration(declarations, kind);
4366 right = parseAssignmentExpression();
4371 init = init.finishLexicalDeclaration(declarations, kind);
4375 initStartToken = lookahead;
4376 state.allowIn = false;
4377 init = inheritCoverGrammar(parseAssignmentExpression);
4378 state.allowIn = previousAllowIn;
4380 if (matchKeyword('in')) {
4381 if (!isAssignmentTarget) {
4382 tolerateError(Messages.InvalidLHSInForIn);
4386 reinterpretExpressionAsPattern(init);
4388 right = parseExpression();
4390 } else if (matchContextualKeyword('of')) {
4391 if (!isAssignmentTarget) {
4392 tolerateError(Messages.InvalidLHSInForLoop);
4396 reinterpretExpressionAsPattern(init);
4398 right = parseAssignmentExpression();
4404 while (match(',')) {
4406 initSeq.push(isolateCoverGrammar(parseAssignmentExpression));
4408 init = new WrappingNode(initStartToken).finishSequenceExpression(initSeq);
4415 if (typeof left === 'undefined') {
4418 test = parseExpression();
4423 update = parseExpression();
4429 oldInIteration = state.inIteration;
4430 state.inIteration = true;
4432 body = isolateCoverGrammar(parseStatement);
4434 state.inIteration = oldInIteration;
4436 return (typeof left === 'undefined') ?
4437 node.finishForStatement(init, test, update, body) :
4438 forIn ? node.finishForInStatement(left, right, body) :
4439 node.finishForOfStatement(left, right, body);
4442 // ECMA-262 13.8 The continue statement
4444 function parseContinueStatement(node) {
4445 var label = null, key;
4447 expectKeyword('continue');
4449 // Optimize the most common form: 'continue;'.
4450 if (source.charCodeAt(startIndex) === 0x3B) {
4453 if (!state.inIteration) {
4454 throwError(Messages.IllegalContinue);
4457 return node.finishContinueStatement(null);
4460 if (hasLineTerminator) {
4461 if (!state.inIteration) {
4462 throwError(Messages.IllegalContinue);
4465 return node.finishContinueStatement(null);
4468 if (lookahead.type === Token.Identifier) {
4469 label = parseVariableIdentifier();
4471 key = '$' + label.name;
4472 if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
4473 throwError(Messages.UnknownLabel, label.name);
4479 if (label === null && !state.inIteration) {
4480 throwError(Messages.IllegalContinue);
4483 return node.finishContinueStatement(label);
4486 // ECMA-262 13.9 The break statement
4488 function parseBreakStatement(node) {
4489 var label = null, key;
4491 expectKeyword('break');
4493 // Catch the very common case first: immediately a semicolon (U+003B).
4494 if (source.charCodeAt(lastIndex) === 0x3B) {
4497 if (!(state.inIteration || state.inSwitch)) {
4498 throwError(Messages.IllegalBreak);
4501 return node.finishBreakStatement(null);
4504 if (hasLineTerminator) {
4505 if (!(state.inIteration || state.inSwitch)) {
4506 throwError(Messages.IllegalBreak);
4508 } else if (lookahead.type === Token.Identifier) {
4509 label = parseVariableIdentifier();
4511 key = '$' + label.name;
4512 if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
4513 throwError(Messages.UnknownLabel, label.name);
4519 if (label === null && !(state.inIteration || state.inSwitch)) {
4520 throwError(Messages.IllegalBreak);
4523 return node.finishBreakStatement(label);
4526 // ECMA-262 13.10 The return statement
4528 function parseReturnStatement(node) {
4529 var argument = null;
4531 expectKeyword('return');
4533 if (!state.inFunctionBody) {
4534 tolerateError(Messages.IllegalReturn);
4537 // 'return' followed by a space and an identifier is very common.
4538 if (source.charCodeAt(lastIndex) === 0x20) {
4539 if (isIdentifierStart(source.charCodeAt(lastIndex + 1))) {
4540 argument = parseExpression();
4542 return node.finishReturnStatement(argument);
4546 if (hasLineTerminator) {
4548 return node.finishReturnStatement(null);
4552 if (!match('}') && lookahead.type !== Token.EOF) {
4553 argument = parseExpression();
4559 return node.finishReturnStatement(argument);
4562 // ECMA-262 13.11 The with statement
4564 function parseWithStatement(node) {
4568 tolerateError(Messages.StrictModeWith);
4571 expectKeyword('with');
4575 object = parseExpression();
4579 body = parseStatement();
4581 return node.finishWithStatement(object, body);
4584 // ECMA-262 13.12 The switch statement
4586 function parseSwitchCase() {
4587 var test, consequent = [], statement, node = new Node();
4589 if (matchKeyword('default')) {
4593 expectKeyword('case');
4594 test = parseExpression();
4598 while (startIndex < length) {
4599 if (match('}') || matchKeyword('default') || matchKeyword('case')) {
4602 statement = parseStatementListItem();
4603 consequent.push(statement);
4606 return node.finishSwitchCase(test, consequent);
4609 function parseSwitchStatement(node) {
4610 var discriminant, cases, clause, oldInSwitch, defaultFound;
4612 expectKeyword('switch');
4616 discriminant = parseExpression();
4626 return node.finishSwitchStatement(discriminant, cases);
4629 oldInSwitch = state.inSwitch;
4630 state.inSwitch = true;
4631 defaultFound = false;
4633 while (startIndex < length) {
4637 clause = parseSwitchCase();
4638 if (clause.test === null) {
4640 throwError(Messages.MultipleDefaultsInSwitch);
4642 defaultFound = true;
4647 state.inSwitch = oldInSwitch;
4651 return node.finishSwitchStatement(discriminant, cases);
4654 // ECMA-262 13.14 The throw statement
4656 function parseThrowStatement(node) {
4659 expectKeyword('throw');
4661 if (hasLineTerminator) {
4662 throwError(Messages.NewlineAfterThrow);
4665 argument = parseExpression();
4669 return node.finishThrowStatement(argument);
4672 // ECMA-262 13.15 The try statement
4674 function parseCatchClause() {
4675 var param, params = [], paramMap = {}, key, i, body, node = new Node();
4677 expectKeyword('catch');
4681 throwUnexpectedToken(lookahead);
4684 param = parsePattern(params);
4685 for (i = 0; i < params.length; i++) {
4686 key = '$' + params[i].value;
4687 if (Object.prototype.hasOwnProperty.call(paramMap, key)) {
4688 tolerateError(Messages.DuplicateBinding, params[i].value);
4690 paramMap[key] = true;
4694 if (strict && isRestrictedWord(param.name)) {
4695 tolerateError(Messages.StrictCatchVariable);
4699 body = parseBlock();
4700 return node.finishCatchClause(param, body);
4703 function parseTryStatement(node) {
4704 var block, handler = null, finalizer = null;
4706 expectKeyword('try');
4708 block = parseBlock();
4710 if (matchKeyword('catch')) {
4711 handler = parseCatchClause();
4714 if (matchKeyword('finally')) {
4716 finalizer = parseBlock();
4719 if (!handler && !finalizer) {
4720 throwError(Messages.NoCatchOrFinally);
4723 return node.finishTryStatement(block, handler, finalizer);
4726 // ECMA-262 13.16 The debugger statement
4728 function parseDebuggerStatement(node) {
4729 expectKeyword('debugger');
4733 return node.finishDebuggerStatement();
4738 function parseStatement() {
4739 var type = lookahead.type,
4745 if (type === Token.EOF) {
4746 throwUnexpectedToken(lookahead);
4749 if (type === Token.Punctuator && lookahead.value === '{') {
4750 return parseBlock();
4752 isAssignmentTarget = isBindingElement = true;
4755 if (type === Token.Punctuator) {
4756 switch (lookahead.value) {
4758 return parseEmptyStatement(node);
4760 return parseExpressionStatement(node);
4764 } else if (type === Token.Keyword) {
4765 switch (lookahead.value) {
4767 return parseBreakStatement(node);
4769 return parseContinueStatement(node);
4771 return parseDebuggerStatement(node);
4773 return parseDoWhileStatement(node);
4775 return parseForStatement(node);
4777 return parseFunctionDeclaration(node);
4779 return parseIfStatement(node);
4781 return parseReturnStatement(node);
4783 return parseSwitchStatement(node);
4785 return parseThrowStatement(node);
4787 return parseTryStatement(node);
4789 return parseVariableStatement(node);
4791 return parseWhileStatement(node);
4793 return parseWithStatement(node);
4799 expr = parseExpression();
4801 // ECMA-262 12.12 Labelled Statements
4802 if ((expr.type === Syntax.Identifier) && match(':')) {
4805 key = '$' + expr.name;
4806 if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
4807 throwError(Messages.Redeclaration, 'Label', expr.name);
4810 state.labelSet[key] = true;
4811 labeledBody = parseStatement();
4812 delete state.labelSet[key];
4813 return node.finishLabeledStatement(expr, labeledBody);
4818 return node.finishExpressionStatement(expr);
4821 // ECMA-262 14.1 Function Definition
4823 function parseFunctionSourceElements() {
4824 var statement, body = [], token, directive, firstRestricted,
4825 oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody,
4830 while (startIndex < length) {
4831 if (lookahead.type !== Token.StringLiteral) {
4836 statement = parseStatementListItem();
4837 body.push(statement);
4838 if (statement.expression.type !== Syntax.Literal) {
4839 // this is not directive
4842 directive = source.slice(token.start + 1, token.end - 1);
4843 if (directive === 'use strict') {
4845 if (firstRestricted) {
4846 tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
4849 if (!firstRestricted && token.octal) {
4850 firstRestricted = token;
4855 oldLabelSet = state.labelSet;
4856 oldInIteration = state.inIteration;
4857 oldInSwitch = state.inSwitch;
4858 oldInFunctionBody = state.inFunctionBody;
4860 state.labelSet = {};
4861 state.inIteration = false;
4862 state.inSwitch = false;
4863 state.inFunctionBody = true;
4865 while (startIndex < length) {
4869 body.push(parseStatementListItem());
4874 state.labelSet = oldLabelSet;
4875 state.inIteration = oldInIteration;
4876 state.inSwitch = oldInSwitch;
4877 state.inFunctionBody = oldInFunctionBody;
4879 return node.finishBlockStatement(body);
4882 function validateParam(options, param, name) {
4883 var key = '$' + name;
4885 if (isRestrictedWord(name)) {
4886 options.stricted = param;
4887 options.message = Messages.StrictParamName;
4889 if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
4890 options.stricted = param;
4891 options.message = Messages.StrictParamDupe;
4893 } else if (!options.firstRestricted) {
4894 if (isRestrictedWord(name)) {
4895 options.firstRestricted = param;
4896 options.message = Messages.StrictParamName;
4897 } else if (isStrictModeReservedWord(name)) {
4898 options.firstRestricted = param;
4899 options.message = Messages.StrictReservedWord;
4900 } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
4901 options.stricted = param;
4902 options.message = Messages.StrictParamDupe;
4905 options.paramSet[key] = true;
4908 function parseParam(options) {
4909 var token, param, params = [], i, def;
4912 if (token.value === '...') {
4913 param = parseRestElement(params);
4914 validateParam(options, param.argument, param.argument.name);
4915 options.params.push(param);
4916 options.defaults.push(null);
4920 param = parsePatternWithDefault(params);
4921 for (i = 0; i < params.length; i++) {
4922 validateParam(options, params[i], params[i].value);
4925 if (param.type === Syntax.AssignmentPattern) {
4928 ++options.defaultCount;
4931 options.params.push(param);
4932 options.defaults.push(def);
4937 function parseParams(firstRestricted) {
4944 firstRestricted: firstRestricted
4950 options.paramSet = {};
4951 while (startIndex < length) {
4952 if (!parseParam(options)) {
4961 if (options.defaultCount === 0) {
4962 options.defaults = [];
4966 params: options.params,
4967 defaults: options.defaults,
4968 stricted: options.stricted,
4969 firstRestricted: options.firstRestricted,
4970 message: options.message
4974 function parseFunctionDeclaration(node, identifierIsOptional) {
4975 var id = null, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict,
4976 isGenerator, previousAllowYield;
4978 previousAllowYield = state.allowYield;
4980 expectKeyword('function');
4982 isGenerator = match('*');
4987 if (!identifierIsOptional || !match('(')) {
4989 id = parseVariableIdentifier();
4991 if (isRestrictedWord(token.value)) {
4992 tolerateUnexpectedToken(token, Messages.StrictFunctionName);
4995 if (isRestrictedWord(token.value)) {
4996 firstRestricted = token;
4997 message = Messages.StrictFunctionName;
4998 } else if (isStrictModeReservedWord(token.value)) {
4999 firstRestricted = token;
5000 message = Messages.StrictReservedWord;
5005 state.allowYield = !isGenerator;
5006 tmp = parseParams(firstRestricted);
5007 params = tmp.params;
5008 defaults = tmp.defaults;
5009 stricted = tmp.stricted;
5010 firstRestricted = tmp.firstRestricted;
5012 message = tmp.message;
5016 previousStrict = strict;
5017 body = parseFunctionSourceElements();
5018 if (strict && firstRestricted) {
5019 throwUnexpectedToken(firstRestricted, message);
5021 if (strict && stricted) {
5022 tolerateUnexpectedToken(stricted, message);
5025 strict = previousStrict;
5026 state.allowYield = previousAllowYield;
5028 return node.finishFunctionDeclaration(id, params, defaults, body, isGenerator);
5031 function parseFunctionExpression() {
5032 var token, id = null, stricted, firstRestricted, message, tmp,
5033 params = [], defaults = [], body, previousStrict, node = new Node(),
5034 isGenerator, previousAllowYield;
5036 previousAllowYield = state.allowYield;
5038 expectKeyword('function');
5040 isGenerator = match('*');
5045 state.allowYield = !isGenerator;
5048 id = (!strict && !isGenerator && matchKeyword('yield')) ? parseNonComputedProperty() : parseVariableIdentifier();
5050 if (isRestrictedWord(token.value)) {
5051 tolerateUnexpectedToken(token, Messages.StrictFunctionName);
5054 if (isRestrictedWord(token.value)) {
5055 firstRestricted = token;
5056 message = Messages.StrictFunctionName;
5057 } else if (isStrictModeReservedWord(token.value)) {
5058 firstRestricted = token;
5059 message = Messages.StrictReservedWord;
5064 tmp = parseParams(firstRestricted);
5065 params = tmp.params;
5066 defaults = tmp.defaults;
5067 stricted = tmp.stricted;
5068 firstRestricted = tmp.firstRestricted;
5070 message = tmp.message;
5073 previousStrict = strict;
5074 body = parseFunctionSourceElements();
5075 if (strict && firstRestricted) {
5076 throwUnexpectedToken(firstRestricted, message);
5078 if (strict && stricted) {
5079 tolerateUnexpectedToken(stricted, message);
5081 strict = previousStrict;
5082 state.allowYield = previousAllowYield;
5084 return node.finishFunctionExpression(id, params, defaults, body, isGenerator);
5087 // ECMA-262 14.5 Class Definitions
5089 function parseClassBody() {
5090 var classBody, token, isStatic, hasConstructor = false, body, method, computed, key;
5092 classBody = new Node();
5096 while (!match('}')) {
5100 method = new Node();
5103 computed = match('[');
5107 key = parseObjectPropertyKey();
5108 if (key.name === 'static' && (lookaheadPropertyName() || match('*'))) {
5111 computed = match('[');
5115 key = parseObjectPropertyKey();
5119 method = tryParseMethodDefinition(token, key, computed, method);
5121 method['static'] = isStatic; // jscs:ignore requireDotNotation
5122 if (method.kind === 'init') {
5123 method.kind = 'method';
5126 if (!method.computed && (method.key.name || method.key.value.toString()) === 'constructor') {
5127 if (method.kind !== 'method' || !method.method || method.value.generator) {
5128 throwUnexpectedToken(token, Messages.ConstructorSpecialMethod);
5130 if (hasConstructor) {
5131 throwUnexpectedToken(token, Messages.DuplicateConstructor);
5133 hasConstructor = true;
5135 method.kind = 'constructor';
5138 if (!method.computed && (method.key.name || method.key.value.toString()) === 'prototype') {
5139 throwUnexpectedToken(token, Messages.StaticPrototype);
5142 method.type = Syntax.MethodDefinition;
5143 delete method.method;
5144 delete method.shorthand;
5147 throwUnexpectedToken(lookahead);
5152 return classBody.finishClassBody(body);
5155 function parseClassDeclaration(identifierIsOptional) {
5156 var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
5159 expectKeyword('class');
5161 if (!identifierIsOptional || lookahead.type === Token.Identifier) {
5162 id = parseVariableIdentifier();
5165 if (matchKeyword('extends')) {
5167 superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall);
5169 classBody = parseClassBody();
5170 strict = previousStrict;
5172 return classNode.finishClassDeclaration(id, superClass, classBody);
5175 function parseClassExpression() {
5176 var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
5179 expectKeyword('class');
5181 if (lookahead.type === Token.Identifier) {
5182 id = parseVariableIdentifier();
5185 if (matchKeyword('extends')) {
5187 superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall);
5189 classBody = parseClassBody();
5190 strict = previousStrict;
5192 return classNode.finishClassExpression(id, superClass, classBody);
5195 // ECMA-262 15.2 Modules
5197 function parseModuleSpecifier() {
5198 var node = new Node();
5200 if (lookahead.type !== Token.StringLiteral) {
5201 throwError(Messages.InvalidModuleSpecifier);
5203 return node.finishLiteral(lex());
5206 // ECMA-262 15.2.3 Exports
5208 function parseExportSpecifier() {
5209 var exported, local, node = new Node(), def;
5210 if (matchKeyword('default')) {
5211 // export {default} from 'something';
5214 local = def.finishIdentifier('default');
5216 local = parseVariableIdentifier();
5218 if (matchContextualKeyword('as')) {
5220 exported = parseNonComputedProperty();
5222 return node.finishExportSpecifier(local, exported);
5225 function parseExportNamedDeclaration(node) {
5226 var declaration = null,
5227 isExportFromIdentifier,
5228 src = null, specifiers = [];
5230 // non-default export
5231 if (lookahead.type === Token.Keyword) {
5233 // export var f = 1;
5234 switch (lookahead.value) {
5237 declaration = parseLexicalDeclaration({inFor: false});
5238 return node.finishExportNamedDeclaration(declaration, specifiers, null);
5242 declaration = parseStatementListItem();
5243 return node.finishExportNamedDeclaration(declaration, specifiers, null);
5248 while (!match('}')) {
5249 isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default');
5250 specifiers.push(parseExportSpecifier());
5260 if (matchContextualKeyword('from')) {
5262 // export {default} from 'foo';
5263 // export {foo} from 'foo';
5265 src = parseModuleSpecifier();
5267 } else if (isExportFromIdentifier) {
5269 // export {default}; // missing fromClause
5270 throwError(lookahead.value ?
5271 Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
5277 return node.finishExportNamedDeclaration(declaration, specifiers, src);
5280 function parseExportDefaultDeclaration(node) {
5281 var declaration = null,
5285 // export default ...
5286 expectKeyword('default');
5288 if (matchKeyword('function')) {
5290 // export default function foo () {}
5291 // export default function () {}
5292 declaration = parseFunctionDeclaration(new Node(), true);
5293 return node.finishExportDefaultDeclaration(declaration);
5295 if (matchKeyword('class')) {
5296 declaration = parseClassDeclaration(true);
5297 return node.finishExportDefaultDeclaration(declaration);
5300 if (matchContextualKeyword('from')) {
5301 throwError(Messages.UnexpectedToken, lookahead.value);
5305 // export default {};
5306 // export default [];
5307 // export default (1 + 2);
5309 expression = parseObjectInitializer();
5310 } else if (match('[')) {
5311 expression = parseArrayInitializer();
5313 expression = parseAssignmentExpression();
5316 return node.finishExportDefaultDeclaration(expression);
5319 function parseExportAllDeclaration(node) {
5323 // export * from 'foo';
5325 if (!matchContextualKeyword('from')) {
5326 throwError(lookahead.value ?
5327 Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
5330 src = parseModuleSpecifier();
5333 return node.finishExportAllDeclaration(src);
5336 function parseExportDeclaration() {
5337 var node = new Node();
5338 if (state.inFunctionBody) {
5339 throwError(Messages.IllegalExportDeclaration);
5342 expectKeyword('export');
5344 if (matchKeyword('default')) {
5345 return parseExportDefaultDeclaration(node);
5348 return parseExportAllDeclaration(node);
5350 return parseExportNamedDeclaration(node);
5353 // ECMA-262 15.2.2 Imports
5355 function parseImportSpecifier() {
5356 // import {<foo as bar>} ...;
5357 var local, imported, node = new Node();
5359 imported = parseNonComputedProperty();
5360 if (matchContextualKeyword('as')) {
5362 local = parseVariableIdentifier();
5365 return node.finishImportSpecifier(local, imported);
5368 function parseNamedImports() {
5369 var specifiers = [];
5370 // {foo, bar as bas}
5372 while (!match('}')) {
5373 specifiers.push(parseImportSpecifier());
5385 function parseImportDefaultSpecifier() {
5386 // import <foo> ...;
5387 var local, node = new Node();
5389 local = parseNonComputedProperty();
5391 return node.finishImportDefaultSpecifier(local);
5394 function parseImportNamespaceSpecifier() {
5395 // import <* as foo> ...;
5396 var local, node = new Node();
5399 if (!matchContextualKeyword('as')) {
5400 throwError(Messages.NoAsAfterImportNamespace);
5403 local = parseNonComputedProperty();
5405 return node.finishImportNamespaceSpecifier(local);
5408 function parseImportDeclaration() {
5409 var specifiers = [], src, node = new Node();
5411 if (state.inFunctionBody) {
5412 throwError(Messages.IllegalImportDeclaration);
5415 expectKeyword('import');
5417 if (lookahead.type === Token.StringLiteral) {
5419 src = parseModuleSpecifier();
5424 specifiers = specifiers.concat(parseNamedImports());
5425 } else if (match('*')) {
5427 specifiers.push(parseImportNamespaceSpecifier());
5428 } else if (isIdentifierName(lookahead) && !matchKeyword('default')) {
5430 specifiers.push(parseImportDefaultSpecifier());
5434 // import foo, * as foo
5435 specifiers.push(parseImportNamespaceSpecifier());
5436 } else if (match('{')) {
5437 // import foo, {bar}
5438 specifiers = specifiers.concat(parseNamedImports());
5440 throwUnexpectedToken(lookahead);
5444 throwUnexpectedToken(lex());
5447 if (!matchContextualKeyword('from')) {
5448 throwError(lookahead.value ?
5449 Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
5452 src = parseModuleSpecifier();
5456 return node.finishImportDeclaration(specifiers, src);
5459 // ECMA-262 15.1 Scripts
5461 function parseScriptBody() {
5462 var statement, body = [], token, directive, firstRestricted;
5464 while (startIndex < length) {
5466 if (token.type !== Token.StringLiteral) {
5470 statement = parseStatementListItem();
5471 body.push(statement);
5472 if (statement.expression.type !== Syntax.Literal) {
5473 // this is not directive
5476 directive = source.slice(token.start + 1, token.end - 1);
5477 if (directive === 'use strict') {
5479 if (firstRestricted) {
5480 tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
5483 if (!firstRestricted && token.octal) {
5484 firstRestricted = token;
5489 while (startIndex < length) {
5490 statement = parseStatementListItem();
5491 /* istanbul ignore if */
5492 if (typeof statement === 'undefined') {
5495 body.push(statement);
5500 function parseProgram() {
5506 body = parseScriptBody();
5507 return node.finishProgram(body, state.sourceType);
5510 function filterTokenLocation() {
5511 var i, entry, token, tokens = [];
5513 for (i = 0; i < extra.tokens.length; ++i) {
5514 entry = extra.tokens[i];
5521 pattern: entry.regex.pattern,
5522 flags: entry.regex.flags
5526 token.range = entry.range;
5529 token.loc = entry.loc;
5534 extra.tokens = tokens;
5537 function tokenize(code, options, delegate) {
5542 if (typeof code !== 'string' && !(code instanceof String)) {
5543 code = toString(code);
5548 lineNumber = (source.length > 0) ? 1 : 0;
5551 startLineNumber = lineNumber;
5552 startLineStart = lineStart;
5553 length = source.length;
5559 inFunctionBody: false,
5562 lastCommentStart: -1,
5568 // Options matching.
5569 options = options || {};
5571 // Of course we collect tokens here.
5572 options.tokens = true;
5574 extra.tokenValues = [];
5575 extra.tokenize = true;
5576 extra.delegate = delegate;
5578 // The following two fields are necessary to compute the Regex tokens.
5579 extra.openParenToken = -1;
5580 extra.openCurlyToken = -1;
5582 extra.range = (typeof options.range === 'boolean') && options.range;
5583 extra.loc = (typeof options.loc === 'boolean') && options.loc;
5585 if (typeof options.comment === 'boolean' && options.comment) {
5586 extra.comments = [];
5588 if (typeof options.tolerant === 'boolean' && options.tolerant) {
5594 if (lookahead.type === Token.EOF) {
5595 return extra.tokens;
5599 while (lookahead.type !== Token.EOF) {
5602 } catch (lexError) {
5604 recordError(lexError);
5605 // We have to break on the first error
5606 // to avoid infinite loops.
5614 tokens = extra.tokens;
5615 if (typeof extra.errors !== 'undefined') {
5616 tokens.errors = extra.errors;
5626 function parse(code, options) {
5627 var program, toString;
5630 if (typeof code !== 'string' && !(code instanceof String)) {
5631 code = toString(code);
5636 lineNumber = (source.length > 0) ? 1 : 0;
5639 startLineNumber = lineNumber;
5640 startLineStart = lineStart;
5641 length = source.length;
5647 inFunctionBody: false,
5650 lastCommentStart: -1,
5652 sourceType: 'script'
5657 if (typeof options !== 'undefined') {
5658 extra.range = (typeof options.range === 'boolean') && options.range;
5659 extra.loc = (typeof options.loc === 'boolean') && options.loc;
5660 extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment;
5662 if (extra.loc && options.source !== null && options.source !== undefined) {
5663 extra.source = toString(options.source);
5666 if (typeof options.tokens === 'boolean' && options.tokens) {
5669 if (typeof options.comment === 'boolean' && options.comment) {
5670 extra.comments = [];
5672 if (typeof options.tolerant === 'boolean' && options.tolerant) {
5675 if (extra.attachComment) {
5677 extra.comments = [];
5678 extra.bottomRightStack = [];
5679 extra.trailingComments = [];
5680 extra.leadingComments = [];
5682 if (options.sourceType === 'module') {
5683 // very restrictive condition for now
5684 state.sourceType = options.sourceType;
5690 program = parseProgram();
5691 if (typeof extra.comments !== 'undefined') {
5692 program.comments = extra.comments;
5694 if (typeof extra.tokens !== 'undefined') {
5695 filterTokenLocation();
5696 program.tokens = extra.tokens;
5698 if (typeof extra.errors !== 'undefined') {
5699 program.errors = extra.errors;
5710 // Sync with *.json manifests.
5711 exports.version = '2.7.3';
5713 exports.tokenize = tokenize;
5715 exports.parse = parse;
5718 /* istanbul ignore next */
5719 exports.Syntax = (function () {
5720 var name, types = {};
5722 if (typeof Object.create === 'function') {
5723 types = Object.create(null);
5726 for (name in Syntax) {
5727 if (Syntax.hasOwnProperty(name)) {
5728 types[name] = Syntax[name];
5732 if (typeof Object.freeze === 'function') {
5733 Object.freeze(types);
5740 /* vim: set sw=4 ts=4 et tw=80 : */