UNPKG

248 kBJavaScriptView Raw
1/*
2 Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>
3 Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>
4 Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
5 Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
6 Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
7 Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
8 Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
9 Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
10 Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
11
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14
15 * Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
17 * Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
25 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*/
32
33(function (root, factory) {
34 'use strict';
35
36 // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
37 // Rhino, and plain browser loading.
38
39 /* istanbul ignore next */
40 if (typeof define === 'function' && define.amd) {
41 define(['exports'], factory);
42 } else if (typeof exports !== 'undefined') {
43 factory(exports);
44 } else {
45 factory((root.esprima = {}));
46 }
47}(this, function (exports) {
48 'use strict';
49
50 var Token,
51 TokenName,
52 FnExprTokens,
53 Syntax,
54 PropertyKind,
55 Messages,
56 Regex,
57 SyntaxTreeDelegate,
58 XHTMLEntities,
59 ClassPropertyType,
60 source,
61 strict,
62 index,
63 lineNumber,
64 lineStart,
65 length,
66 delegate,
67 lookahead,
68 state,
69 extra;
70
71 Token = {
72 BooleanLiteral: 1,
73 EOF: 2,
74 Identifier: 3,
75 Keyword: 4,
76 NullLiteral: 5,
77 NumericLiteral: 6,
78 Punctuator: 7,
79 StringLiteral: 8,
80 RegularExpression: 9,
81 Template: 10,
82 JSXIdentifier: 11,
83 JSXText: 12
84 };
85
86 TokenName = {};
87 TokenName[Token.BooleanLiteral] = 'Boolean';
88 TokenName[Token.EOF] = '<end>';
89 TokenName[Token.Identifier] = 'Identifier';
90 TokenName[Token.Keyword] = 'Keyword';
91 TokenName[Token.NullLiteral] = 'Null';
92 TokenName[Token.NumericLiteral] = 'Numeric';
93 TokenName[Token.Punctuator] = 'Punctuator';
94 TokenName[Token.StringLiteral] = 'String';
95 TokenName[Token.JSXIdentifier] = 'JSXIdentifier';
96 TokenName[Token.JSXText] = 'JSXText';
97 TokenName[Token.RegularExpression] = 'RegularExpression';
98 TokenName[Token.Template] = 'Template';
99
100 // A function following one of those tokens is an expression.
101 FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
102 'return', 'case', 'delete', 'throw', 'void',
103 // assignment operators
104 '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=',
105 '&=', '|=', '^=', ',',
106 // binary/unary operators
107 '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&',
108 '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=',
109 '<=', '<', '>', '!=', '!=='];
110
111 Syntax = {
112 AnyTypeAnnotation: 'AnyTypeAnnotation',
113 ArrayExpression: 'ArrayExpression',
114 ArrayPattern: 'ArrayPattern',
115 ArrayTypeAnnotation: 'ArrayTypeAnnotation',
116 ArrowFunctionExpression: 'ArrowFunctionExpression',
117 AssignmentExpression: 'AssignmentExpression',
118 BinaryExpression: 'BinaryExpression',
119 BlockStatement: 'BlockStatement',
120 BooleanTypeAnnotation: 'BooleanTypeAnnotation',
121 BreakStatement: 'BreakStatement',
122 CallExpression: 'CallExpression',
123 CatchClause: 'CatchClause',
124 ClassBody: 'ClassBody',
125 ClassDeclaration: 'ClassDeclaration',
126 ClassExpression: 'ClassExpression',
127 ClassImplements: 'ClassImplements',
128 ClassProperty: 'ClassProperty',
129 ComprehensionBlock: 'ComprehensionBlock',
130 ComprehensionExpression: 'ComprehensionExpression',
131 ConditionalExpression: 'ConditionalExpression',
132 ContinueStatement: 'ContinueStatement',
133 DebuggerStatement: 'DebuggerStatement',
134 DeclareClass: 'DeclareClass',
135 DeclareFunction: 'DeclareFunction',
136 DeclareModule: 'DeclareModule',
137 DeclareVariable: 'DeclareVariable',
138 DoWhileStatement: 'DoWhileStatement',
139 EmptyStatement: 'EmptyStatement',
140 ExportDeclaration: 'ExportDeclaration',
141 ExportBatchSpecifier: 'ExportBatchSpecifier',
142 ExportSpecifier: 'ExportSpecifier',
143 ExpressionStatement: 'ExpressionStatement',
144 ForInStatement: 'ForInStatement',
145 ForOfStatement: 'ForOfStatement',
146 ForStatement: 'ForStatement',
147 FunctionDeclaration: 'FunctionDeclaration',
148 FunctionExpression: 'FunctionExpression',
149 FunctionTypeAnnotation: 'FunctionTypeAnnotation',
150 FunctionTypeParam: 'FunctionTypeParam',
151 GenericTypeAnnotation: 'GenericTypeAnnotation',
152 Identifier: 'Identifier',
153 IfStatement: 'IfStatement',
154 ImportDeclaration: 'ImportDeclaration',
155 ImportDefaultSpecifier: 'ImportDefaultSpecifier',
156 ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
157 ImportSpecifier: 'ImportSpecifier',
158 InterfaceDeclaration: 'InterfaceDeclaration',
159 InterfaceExtends: 'InterfaceExtends',
160 IntersectionTypeAnnotation: 'IntersectionTypeAnnotation',
161 LabeledStatement: 'LabeledStatement',
162 Literal: 'Literal',
163 LogicalExpression: 'LogicalExpression',
164 MemberExpression: 'MemberExpression',
165 MethodDefinition: 'MethodDefinition',
166 NewExpression: 'NewExpression',
167 NullableTypeAnnotation: 'NullableTypeAnnotation',
168 NumberTypeAnnotation: 'NumberTypeAnnotation',
169 ObjectExpression: 'ObjectExpression',
170 ObjectPattern: 'ObjectPattern',
171 ObjectTypeAnnotation: 'ObjectTypeAnnotation',
172 ObjectTypeCallProperty: 'ObjectTypeCallProperty',
173 ObjectTypeIndexer: 'ObjectTypeIndexer',
174 ObjectTypeProperty: 'ObjectTypeProperty',
175 Program: 'Program',
176 Property: 'Property',
177 QualifiedTypeIdentifier: 'QualifiedTypeIdentifier',
178 ReturnStatement: 'ReturnStatement',
179 SequenceExpression: 'SequenceExpression',
180 SpreadElement: 'SpreadElement',
181 SpreadProperty: 'SpreadProperty',
182 StringLiteralTypeAnnotation: 'StringLiteralTypeAnnotation',
183 StringTypeAnnotation: 'StringTypeAnnotation',
184 SwitchCase: 'SwitchCase',
185 SwitchStatement: 'SwitchStatement',
186 TaggedTemplateExpression: 'TaggedTemplateExpression',
187 TemplateElement: 'TemplateElement',
188 TemplateLiteral: 'TemplateLiteral',
189 ThisExpression: 'ThisExpression',
190 ThrowStatement: 'ThrowStatement',
191 TupleTypeAnnotation: 'TupleTypeAnnotation',
192 TryStatement: 'TryStatement',
193 TypeAlias: 'TypeAlias',
194 TypeAnnotation: 'TypeAnnotation',
195 TypeCastExpression: 'TypeCastExpression',
196 TypeofTypeAnnotation: 'TypeofTypeAnnotation',
197 TypeParameterDeclaration: 'TypeParameterDeclaration',
198 TypeParameterInstantiation: 'TypeParameterInstantiation',
199 UnaryExpression: 'UnaryExpression',
200 UnionTypeAnnotation: 'UnionTypeAnnotation',
201 UpdateExpression: 'UpdateExpression',
202 VariableDeclaration: 'VariableDeclaration',
203 VariableDeclarator: 'VariableDeclarator',
204 VoidTypeAnnotation: 'VoidTypeAnnotation',
205 WhileStatement: 'WhileStatement',
206 WithStatement: 'WithStatement',
207 JSXIdentifier: 'JSXIdentifier',
208 JSXNamespacedName: 'JSXNamespacedName',
209 JSXMemberExpression: 'JSXMemberExpression',
210 JSXEmptyExpression: 'JSXEmptyExpression',
211 JSXExpressionContainer: 'JSXExpressionContainer',
212 JSXElement: 'JSXElement',
213 JSXClosingElement: 'JSXClosingElement',
214 JSXOpeningElement: 'JSXOpeningElement',
215 JSXAttribute: 'JSXAttribute',
216 JSXSpreadAttribute: 'JSXSpreadAttribute',
217 JSXText: 'JSXText',
218 YieldExpression: 'YieldExpression',
219 AwaitExpression: 'AwaitExpression'
220 };
221
222 PropertyKind = {
223 Data: 1,
224 Get: 2,
225 Set: 4
226 };
227
228 ClassPropertyType = {
229 'static': 'static',
230 prototype: 'prototype'
231 };
232
233 // Error messages should be identical to V8.
234 Messages = {
235 UnexpectedToken: 'Unexpected token %0',
236 UnexpectedNumber: 'Unexpected number',
237 UnexpectedString: 'Unexpected string',
238 UnexpectedIdentifier: 'Unexpected identifier',
239 UnexpectedReserved: 'Unexpected reserved word',
240 UnexpectedTemplate: 'Unexpected quasi %0',
241 UnexpectedEOS: 'Unexpected end of input',
242 NewlineAfterThrow: 'Illegal newline after throw',
243 InvalidRegExp: 'Invalid regular expression',
244 UnterminatedRegExp: 'Invalid regular expression: missing /',
245 InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
246 InvalidLHSInFormalsList: 'Invalid left-hand side in formals list',
247 InvalidLHSInForIn: 'Invalid left-hand side in for-in',
248 MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
249 NoCatchOrFinally: 'Missing catch or finally after try',
250 UnknownLabel: 'Undefined label \'%0\'',
251 Redeclaration: '%0 \'%1\' has already been declared',
252 IllegalContinue: 'Illegal continue statement',
253 IllegalBreak: 'Illegal break statement',
254 IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition',
255 IllegalClassConstructorProperty: 'Illegal constructor property in class definition',
256 IllegalReturn: 'Illegal return statement',
257 IllegalSpread: 'Illegal spread element',
258 StrictModeWith: 'Strict mode code may not include a with statement',
259 StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
260 StrictVarName: 'Variable name may not be eval or arguments in strict mode',
261 StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
262 StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
263 ParameterAfterRestParameter: 'Rest parameter must be final parameter of an argument list',
264 DefaultRestParameter: 'Rest parameter can not have a default value',
265 ElementAfterSpreadElement: 'Spread must be the final element of an element list',
266 PropertyAfterSpreadProperty: 'A rest property must be the final property of an object literal',
267 ObjectPatternAsRestParameter: 'Invalid rest parameter',
268 ObjectPatternAsSpread: 'Invalid spread argument',
269 StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
270 StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
271 StrictDelete: 'Delete of an unqualified identifier in strict mode.',
272 StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
273 AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
274 AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
275 StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
276 StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
277 StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
278 StrictReservedWord: 'Use of future reserved word in strict mode',
279 MissingFromClause: 'Missing from clause',
280 NoAsAfterImportNamespace: 'Missing as after import *',
281 InvalidModuleSpecifier: 'Invalid module specifier',
282 IllegalImportDeclaration: 'Illegal import declaration',
283 IllegalExportDeclaration: 'Illegal export declaration',
284 NoUninitializedConst: 'Const must be initialized',
285 ComprehensionRequiresBlock: 'Comprehension must have at least one block',
286 ComprehensionError: 'Comprehension Error',
287 EachNotAllowed: 'Each is not supported',
288 InvalidJSXAttributeValue: 'JSX value should be either an expression or a quoted JSX text',
289 ExpectedJSXClosingTag: 'Expected corresponding JSX closing tag for %0',
290 AdjacentJSXElements: 'Adjacent JSX elements must be wrapped in an enclosing tag',
291 ConfusedAboutFunctionType: 'Unexpected token =>. It looks like ' +
292 'you are trying to write a function type, but you ended up ' +
293 'writing a grouped type followed by an =>, which is a syntax ' +
294 'error. Remember, function type parameters are named so function ' +
295 'types look like (name1: type1, name2: type2) => returnType. You ' +
296 'probably wrote (type1) => returnType'
297 };
298
299 // See also tools/generate-unicode-regex.py.
300 Regex = {
301 NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'),
302 NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'),
303 LeadingZeros: new RegExp('^0+(?!$)')
304 };
305
306 // Ensure the condition is true, otherwise throw an error.
307 // This is only to have a better contract semantic, i.e. another safety net
308 // to catch a logic error. The condition shall be fulfilled in normal case.
309 // Do NOT use this to enforce a certain condition on any user input.
310
311 function assert(condition, message) {
312 /* istanbul ignore if */
313 if (!condition) {
314 throw new Error('ASSERT: ' + message);
315 }
316 }
317
318 function StringMap() {
319 this.$data = {};
320 }
321
322 StringMap.prototype.get = function (key) {
323 key = '$' + key;
324 return this.$data[key];
325 };
326
327 StringMap.prototype.set = function (key, value) {
328 key = '$' + key;
329 this.$data[key] = value;
330 return this;
331 };
332
333 StringMap.prototype.has = function (key) {
334 key = '$' + key;
335 return Object.prototype.hasOwnProperty.call(this.$data, key);
336 };
337
338 StringMap.prototype.delete = function (key) {
339 key = '$' + key;
340 return delete this.$data[key];
341 };
342
343 function isDecimalDigit(ch) {
344 return (ch >= 48 && ch <= 57); // 0..9
345 }
346
347 function isHexDigit(ch) {
348 return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
349 }
350
351 function isOctalDigit(ch) {
352 return '01234567'.indexOf(ch) >= 0;
353 }
354
355
356 // 7.2 White Space
357
358 function isWhiteSpace(ch) {
359 return (ch === 32) || // space
360 (ch === 9) || // tab
361 (ch === 0xB) ||
362 (ch === 0xC) ||
363 (ch === 0xA0) ||
364 (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0);
365 }
366
367 // 7.3 Line Terminators
368
369 function isLineTerminator(ch) {
370 return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029);
371 }
372
373 // 7.6 Identifier Names and Identifiers
374
375 function isIdentifierStart(ch) {
376 return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore)
377 (ch >= 65 && ch <= 90) || // A..Z
378 (ch >= 97 && ch <= 122) || // a..z
379 (ch === 92) || // \ (backslash)
380 ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch)));
381 }
382
383 function isIdentifierPart(ch) {
384 return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore)
385 (ch >= 65 && ch <= 90) || // A..Z
386 (ch >= 97 && ch <= 122) || // a..z
387 (ch >= 48 && ch <= 57) || // 0..9
388 (ch === 92) || // \ (backslash)
389 ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch)));
390 }
391
392 // 7.6.1.2 Future Reserved Words
393
394 function isFutureReservedWord(id) {
395 switch (id) {
396 case 'class':
397 case 'enum':
398 case 'export':
399 case 'extends':
400 case 'import':
401 case 'super':
402 return true;
403 default:
404 return false;
405 }
406 }
407
408 function isStrictModeReservedWord(id) {
409 switch (id) {
410 case 'implements':
411 case 'interface':
412 case 'package':
413 case 'private':
414 case 'protected':
415 case 'public':
416 case 'static':
417 case 'yield':
418 case 'let':
419 return true;
420 default:
421 return false;
422 }
423 }
424
425 function isRestrictedWord(id) {
426 return id === 'eval' || id === 'arguments';
427 }
428
429 // 7.6.1.1 Keywords
430
431 function isKeyword(id) {
432 if (strict && isStrictModeReservedWord(id)) {
433 return true;
434 }
435
436 // 'const' is specialized as Keyword in V8.
437 // 'yield' is only treated as a keyword in strict mode.
438 // 'let' is for compatiblity with SpiderMonkey and ES.next.
439 // Some others are from future reserved words.
440
441 switch (id.length) {
442 case 2:
443 return (id === 'if') || (id === 'in') || (id === 'do');
444 case 3:
445 return (id === 'var') || (id === 'for') || (id === 'new') ||
446 (id === 'try') || (id === 'let');
447 case 4:
448 return (id === 'this') || (id === 'else') || (id === 'case') ||
449 (id === 'void') || (id === 'with') || (id === 'enum');
450 case 5:
451 return (id === 'while') || (id === 'break') || (id === 'catch') ||
452 (id === 'throw') || (id === 'const') ||
453 (id === 'class') || (id === 'super');
454 case 6:
455 return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
456 (id === 'switch') || (id === 'export') || (id === 'import');
457 case 7:
458 return (id === 'default') || (id === 'finally') || (id === 'extends');
459 case 8:
460 return (id === 'function') || (id === 'continue') || (id === 'debugger');
461 case 10:
462 return (id === 'instanceof');
463 default:
464 return false;
465 }
466 }
467
468 // 7.4 Comments
469
470 function addComment(type, value, start, end, loc) {
471 var comment;
472 assert(typeof start === 'number', 'Comment must have valid position');
473
474 // Because the way the actual token is scanned, often the comments
475 // (if any) are skipped twice during the lexical analysis.
476 // Thus, we need to skip adding a comment if the comment array already
477 // handled it.
478 if (state.lastCommentStart >= start) {
479 return;
480 }
481 state.lastCommentStart = start;
482
483 comment = {
484 type: type,
485 value: value
486 };
487 if (extra.range) {
488 comment.range = [start, end];
489 }
490 if (extra.loc) {
491 comment.loc = loc;
492 }
493 extra.comments.push(comment);
494 if (extra.attachComment) {
495 extra.leadingComments.push(comment);
496 extra.trailingComments.push(comment);
497 }
498 }
499
500 function skipSingleLineComment() {
501 var start, loc, ch, comment;
502
503 start = index - 2;
504 loc = {
505 start: {
506 line: lineNumber,
507 column: index - lineStart - 2
508 }
509 };
510
511 while (index < length) {
512 ch = source.charCodeAt(index);
513 ++index;
514 if (isLineTerminator(ch)) {
515 if (extra.comments) {
516 comment = source.slice(start + 2, index - 1);
517 loc.end = {
518 line: lineNumber,
519 column: index - lineStart - 1
520 };
521 addComment('Line', comment, start, index - 1, loc);
522 }
523 if (ch === 13 && source.charCodeAt(index) === 10) {
524 ++index;
525 }
526 ++lineNumber;
527 lineStart = index;
528 return;
529 }
530 }
531
532 if (extra.comments) {
533 comment = source.slice(start + 2, index);
534 loc.end = {
535 line: lineNumber,
536 column: index - lineStart
537 };
538 addComment('Line', comment, start, index, loc);
539 }
540 }
541
542 function skipMultiLineComment() {
543 var start, loc, ch, comment;
544
545 if (extra.comments) {
546 start = index - 2;
547 loc = {
548 start: {
549 line: lineNumber,
550 column: index - lineStart - 2
551 }
552 };
553 }
554
555 while (index < length) {
556 ch = source.charCodeAt(index);
557 if (isLineTerminator(ch)) {
558 if (ch === 13 && source.charCodeAt(index + 1) === 10) {
559 ++index;
560 }
561 ++lineNumber;
562 ++index;
563 lineStart = index;
564 if (index >= length) {
565 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
566 }
567 } else if (ch === 42) {
568 // Block comment ends with '*/' (char #42, char #47).
569 if (source.charCodeAt(index + 1) === 47) {
570 ++index;
571 ++index;
572 if (extra.comments) {
573 comment = source.slice(start + 2, index - 2);
574 loc.end = {
575 line: lineNumber,
576 column: index - lineStart
577 };
578 addComment('Block', comment, start, index, loc);
579 }
580 return;
581 }
582 ++index;
583 } else {
584 ++index;
585 }
586 }
587
588 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
589 }
590
591 function skipComment() {
592 var ch;
593
594 while (index < length) {
595 ch = source.charCodeAt(index);
596
597 if (isWhiteSpace(ch)) {
598 ++index;
599 } else if (isLineTerminator(ch)) {
600 ++index;
601 if (ch === 13 && source.charCodeAt(index) === 10) {
602 ++index;
603 }
604 ++lineNumber;
605 lineStart = index;
606 } else if (ch === 47) { // 47 is '/'
607 ch = source.charCodeAt(index + 1);
608 if (ch === 47) {
609 ++index;
610 ++index;
611 skipSingleLineComment();
612 } else if (ch === 42) { // 42 is '*'
613 ++index;
614 ++index;
615 skipMultiLineComment();
616 } else {
617 break;
618 }
619 } else {
620 break;
621 }
622 }
623 }
624
625 function scanHexEscape(prefix) {
626 var i, len, ch, code = 0;
627
628 len = (prefix === 'u') ? 4 : 2;
629 for (i = 0; i < len; ++i) {
630 if (index < length && isHexDigit(source[index])) {
631 ch = source[index++];
632 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
633 } else {
634 return '';
635 }
636 }
637 return String.fromCharCode(code);
638 }
639
640 function scanUnicodeCodePointEscape() {
641 var ch, code, cu1, cu2;
642
643 ch = source[index];
644 code = 0;
645
646 // At least, one hex digit is required.
647 if (ch === '}') {
648 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
649 }
650
651 while (index < length) {
652 ch = source[index++];
653 if (!isHexDigit(ch)) {
654 break;
655 }
656 code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
657 }
658
659 if (code > 0x10FFFF || ch !== '}') {
660 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
661 }
662
663 // UTF-16 Encoding
664 if (code <= 0xFFFF) {
665 return String.fromCharCode(code);
666 }
667 cu1 = ((code - 0x10000) >> 10) + 0xD800;
668 cu2 = ((code - 0x10000) & 1023) + 0xDC00;
669 return String.fromCharCode(cu1, cu2);
670 }
671
672 function getEscapedIdentifier() {
673 var ch, id;
674
675 ch = source.charCodeAt(index++);
676 id = String.fromCharCode(ch);
677
678 // '\u' (char #92, char #117) denotes an escaped character.
679 if (ch === 92) {
680 if (source.charCodeAt(index) !== 117) {
681 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
682 }
683 ++index;
684 ch = scanHexEscape('u');
685 if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) {
686 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
687 }
688 id = ch;
689 }
690
691 while (index < length) {
692 ch = source.charCodeAt(index);
693 if (!isIdentifierPart(ch)) {
694 break;
695 }
696 ++index;
697 id += String.fromCharCode(ch);
698
699 // '\u' (char #92, char #117) denotes an escaped character.
700 if (ch === 92) {
701 id = id.substr(0, id.length - 1);
702 if (source.charCodeAt(index) !== 117) {
703 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
704 }
705 ++index;
706 ch = scanHexEscape('u');
707 if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) {
708 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
709 }
710 id += ch;
711 }
712 }
713
714 return id;
715 }
716
717 function getIdentifier() {
718 var start, ch;
719
720 start = index++;
721 while (index < length) {
722 ch = source.charCodeAt(index);
723 if (ch === 92) {
724 // Blackslash (char #92) marks Unicode escape sequence.
725 index = start;
726 return getEscapedIdentifier();
727 }
728 if (isIdentifierPart(ch)) {
729 ++index;
730 } else {
731 break;
732 }
733 }
734
735 return source.slice(start, index);
736 }
737
738 function scanIdentifier() {
739 var start, id, type;
740
741 start = index;
742
743 // Backslash (char #92) starts an escaped character.
744 id = (source.charCodeAt(index) === 92) ? getEscapedIdentifier() : getIdentifier();
745
746 // There is no keyword or literal with only one character.
747 // Thus, it must be an identifier.
748 if (id.length === 1) {
749 type = Token.Identifier;
750 } else if (isKeyword(id)) {
751 type = Token.Keyword;
752 } else if (id === 'null') {
753 type = Token.NullLiteral;
754 } else if (id === 'true' || id === 'false') {
755 type = Token.BooleanLiteral;
756 } else {
757 type = Token.Identifier;
758 }
759
760 return {
761 type: type,
762 value: id,
763 lineNumber: lineNumber,
764 lineStart: lineStart,
765 range: [start, index]
766 };
767 }
768
769
770 // 7.7 Punctuators
771
772 function scanPunctuator() {
773 var start = index,
774 code = source.charCodeAt(index),
775 code2,
776 ch1 = source[index],
777 ch2,
778 ch3,
779 ch4;
780
781 if (state.inJSXTag || state.inJSXChild) {
782 // Don't need to check for '{' and '}' as it's already handled
783 // correctly by default.
784 switch (code) {
785 case 60: // <
786 case 62: // >
787 ++index;
788 return {
789 type: Token.Punctuator,
790 value: String.fromCharCode(code),
791 lineNumber: lineNumber,
792 lineStart: lineStart,
793 range: [start, index]
794 };
795 }
796 }
797
798 switch (code) {
799 // Check for most common single-character punctuators.
800 case 40: // ( open bracket
801 case 41: // ) close bracket
802 case 59: // ; semicolon
803 case 44: // , comma
804 case 91: // [
805 case 93: // ]
806 case 58: // :
807 case 63: // ?
808 case 126: // ~
809 ++index;
810 if (extra.tokenize && code === 40) {
811 extra.openParenToken = extra.tokens.length;
812 }
813
814 return {
815 type: Token.Punctuator,
816 value: String.fromCharCode(code),
817 lineNumber: lineNumber,
818 lineStart: lineStart,
819 range: [start, index]
820 };
821
822 case 123: // { open curly brace
823 case 125: // } close curly brace
824 ++index;
825 if (extra.tokenize && code === 123) {
826 extra.openCurlyToken = extra.tokens.length;
827 }
828
829 // lookahead2 function can cause tokens to be scanned twice and in doing so
830 // would wreck the curly stack by pushing the same token onto the stack twice.
831 // curlyLastIndex ensures each token is pushed or popped exactly once
832 if (index > state.curlyLastIndex) {
833 state.curlyLastIndex = index;
834 if (code === 123) {
835 state.curlyStack.push('{');
836 } else {
837 state.curlyStack.pop();
838 }
839 }
840
841 return {
842 type: Token.Punctuator,
843 value: String.fromCharCode(code),
844 lineNumber: lineNumber,
845 lineStart: lineStart,
846 range: [start, index]
847 };
848
849 default:
850 code2 = source.charCodeAt(index + 1);
851
852 // '=' (char #61) marks an assignment or comparison operator.
853 if (code2 === 61) {
854 switch (code) {
855 case 37: // %
856 case 38: // &
857 case 42: // *:
858 case 43: // +
859 case 45: // -
860 case 47: // /
861 case 60: // <
862 case 62: // >
863 case 94: // ^
864 case 124: // |
865 index += 2;
866 return {
867 type: Token.Punctuator,
868 value: String.fromCharCode(code) + String.fromCharCode(code2),
869 lineNumber: lineNumber,
870 lineStart: lineStart,
871 range: [start, index]
872 };
873
874 case 33: // !
875 case 61: // =
876 index += 2;
877
878 // !== and ===
879 if (source.charCodeAt(index) === 61) {
880 ++index;
881 }
882 return {
883 type: Token.Punctuator,
884 value: source.slice(start, index),
885 lineNumber: lineNumber,
886 lineStart: lineStart,
887 range: [start, index]
888 };
889 default:
890 break;
891 }
892 }
893 break;
894 }
895
896 // Peek more characters.
897
898 ch2 = source[index + 1];
899 ch3 = source[index + 2];
900 ch4 = source[index + 3];
901
902 // 4-character punctuator: >>>=
903
904 if (ch1 === '>' && ch2 === '>' && ch3 === '>') {
905 if (ch4 === '=') {
906 index += 4;
907 return {
908 type: Token.Punctuator,
909 value: '>>>=',
910 lineNumber: lineNumber,
911 lineStart: lineStart,
912 range: [start, index]
913 };
914 }
915 }
916
917 // 3-character punctuators: === !== >>> <<= >>=
918
919 if (ch1 === '>' && ch2 === '>' && ch3 === '>' && !state.inType) {
920 index += 3;
921 return {
922 type: Token.Punctuator,
923 value: '>>>',
924 lineNumber: lineNumber,
925 lineStart: lineStart,
926 range: [start, index]
927 };
928 }
929
930 if (ch1 === '<' && ch2 === '<' && ch3 === '=') {
931 index += 3;
932 return {
933 type: Token.Punctuator,
934 value: '<<=',
935 lineNumber: lineNumber,
936 lineStart: lineStart,
937 range: [start, index]
938 };
939 }
940
941 if (ch1 === '>' && ch2 === '>' && ch3 === '=') {
942 index += 3;
943 return {
944 type: Token.Punctuator,
945 value: '>>=',
946 lineNumber: lineNumber,
947 lineStart: lineStart,
948 range: [start, index]
949 };
950 }
951
952 if (ch1 === '.' && ch2 === '.' && ch3 === '.') {
953 index += 3;
954 return {
955 type: Token.Punctuator,
956 value: '...',
957 lineNumber: lineNumber,
958 lineStart: lineStart,
959 range: [start, index]
960 };
961 }
962
963 // Other 2-character punctuators: ++ -- << >> && ||
964
965 // Don't match these tokens if we're in a type, since they never can
966 // occur and can mess up types like Map<string, Array<string>>
967 if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0) && !state.inType) {
968 index += 2;
969 return {
970 type: Token.Punctuator,
971 value: ch1 + ch2,
972 lineNumber: lineNumber,
973 lineStart: lineStart,
974 range: [start, index]
975 };
976 }
977
978 if (ch1 === '=' && ch2 === '>') {
979 index += 2;
980 return {
981 type: Token.Punctuator,
982 value: '=>',
983 lineNumber: lineNumber,
984 lineStart: lineStart,
985 range: [start, index]
986 };
987 }
988
989 if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) {
990 ++index;
991 return {
992 type: Token.Punctuator,
993 value: ch1,
994 lineNumber: lineNumber,
995 lineStart: lineStart,
996 range: [start, index]
997 };
998 }
999
1000 if (ch1 === '.') {
1001 ++index;
1002 return {
1003 type: Token.Punctuator,
1004 value: ch1,
1005 lineNumber: lineNumber,
1006 lineStart: lineStart,
1007 range: [start, index]
1008 };
1009 }
1010
1011 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1012 }
1013
1014 // 7.8.3 Numeric Literals
1015
1016 function scanHexLiteral(start) {
1017 var number = '';
1018
1019 while (index < length) {
1020 if (!isHexDigit(source[index])) {
1021 break;
1022 }
1023 number += source[index++];
1024 }
1025
1026 if (number.length === 0) {
1027 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1028 }
1029
1030 if (isIdentifierStart(source.charCodeAt(index))) {
1031 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1032 }
1033
1034 return {
1035 type: Token.NumericLiteral,
1036 value: parseInt('0x' + number, 16),
1037 lineNumber: lineNumber,
1038 lineStart: lineStart,
1039 range: [start, index]
1040 };
1041 }
1042
1043 function scanBinaryLiteral(start) {
1044 var ch, number;
1045
1046 number = '';
1047
1048 while (index < length) {
1049 ch = source[index];
1050 if (ch !== '0' && ch !== '1') {
1051 break;
1052 }
1053 number += source[index++];
1054 }
1055
1056 if (number.length === 0) {
1057 // only 0b or 0B
1058 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1059 }
1060
1061 if (index < length) {
1062 ch = source.charCodeAt(index);
1063 /* istanbul ignore else */
1064 if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
1065 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1066 }
1067 }
1068
1069 return {
1070 type: Token.NumericLiteral,
1071 value: parseInt(number, 2),
1072 lineNumber: lineNumber,
1073 lineStart: lineStart,
1074 range: [start, index]
1075 };
1076 }
1077
1078 function scanOctalLiteral(prefix, start) {
1079 var number, octal;
1080
1081 if (isOctalDigit(prefix)) {
1082 octal = true;
1083 number = '0' + source[index++];
1084 } else {
1085 octal = false;
1086 ++index;
1087 number = '';
1088 }
1089
1090 while (index < length) {
1091 if (!isOctalDigit(source[index])) {
1092 break;
1093 }
1094 number += source[index++];
1095 }
1096
1097 if (!octal && number.length === 0) {
1098 // only 0o or 0O
1099 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1100 }
1101
1102 if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
1103 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1104 }
1105
1106 return {
1107 type: Token.NumericLiteral,
1108 value: parseInt(number, 8),
1109 octal: octal,
1110 lineNumber: lineNumber,
1111 lineStart: lineStart,
1112 range: [start, index]
1113 };
1114 }
1115
1116 function scanNumericLiteral() {
1117 var number, start, ch;
1118
1119 ch = source[index];
1120 assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'),
1121 'Numeric literal must start with a decimal digit or a decimal point');
1122
1123 start = index;
1124 number = '';
1125 if (ch !== '.') {
1126 number = source[index++];
1127 ch = source[index];
1128
1129 // Hex number starts with '0x'.
1130 // Octal number starts with '0'.
1131 // Octal number in ES6 starts with '0o'.
1132 // Binary number in ES6 starts with '0b'.
1133 if (number === '0') {
1134 if (ch === 'x' || ch === 'X') {
1135 ++index;
1136 return scanHexLiteral(start);
1137 }
1138 if (ch === 'b' || ch === 'B') {
1139 ++index;
1140 return scanBinaryLiteral(start);
1141 }
1142 if (ch === 'o' || ch === 'O' || isOctalDigit(ch)) {
1143 return scanOctalLiteral(ch, start);
1144 }
1145 // decimal number starts with '0' such as '09' is illegal.
1146 if (ch && isDecimalDigit(ch.charCodeAt(0))) {
1147 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1148 }
1149 }
1150
1151 while (isDecimalDigit(source.charCodeAt(index))) {
1152 number += source[index++];
1153 }
1154 ch = source[index];
1155 }
1156
1157 if (ch === '.') {
1158 number += source[index++];
1159 while (isDecimalDigit(source.charCodeAt(index))) {
1160 number += source[index++];
1161 }
1162 ch = source[index];
1163 }
1164
1165 if (ch === 'e' || ch === 'E') {
1166 number += source[index++];
1167
1168 ch = source[index];
1169 if (ch === '+' || ch === '-') {
1170 number += source[index++];
1171 }
1172 if (isDecimalDigit(source.charCodeAt(index))) {
1173 while (isDecimalDigit(source.charCodeAt(index))) {
1174 number += source[index++];
1175 }
1176 } else {
1177 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1178 }
1179 }
1180
1181 if (isIdentifierStart(source.charCodeAt(index))) {
1182 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1183 }
1184
1185 return {
1186 type: Token.NumericLiteral,
1187 value: parseFloat(number),
1188 lineNumber: lineNumber,
1189 lineStart: lineStart,
1190 range: [start, index]
1191 };
1192 }
1193
1194 // 7.8.4 String Literals
1195
1196 function scanStringLiteral() {
1197 var str = '', quote, start, ch, code, unescaped, restore, octal = false;
1198
1199 quote = source[index];
1200 assert((quote === '\'' || quote === '"'),
1201 'String literal must starts with a quote');
1202
1203 start = index;
1204 ++index;
1205
1206 while (index < length) {
1207 ch = source[index++];
1208
1209 if (ch === quote) {
1210 quote = '';
1211 break;
1212 } else if (ch === '\\') {
1213 ch = source[index++];
1214 if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
1215 switch (ch) {
1216 case 'n':
1217 str += '\n';
1218 break;
1219 case 'r':
1220 str += '\r';
1221 break;
1222 case 't':
1223 str += '\t';
1224 break;
1225 case 'u':
1226 case 'x':
1227 if (source[index] === '{') {
1228 ++index;
1229 str += scanUnicodeCodePointEscape();
1230 } else {
1231 restore = index;
1232 unescaped = scanHexEscape(ch);
1233 if (unescaped) {
1234 str += unescaped;
1235 } else {
1236 index = restore;
1237 str += ch;
1238 }
1239 }
1240 break;
1241 case 'b':
1242 str += '\b';
1243 break;
1244 case 'f':
1245 str += '\f';
1246 break;
1247 case 'v':
1248 str += '\x0B';
1249 break;
1250
1251 default:
1252 if (isOctalDigit(ch)) {
1253 code = '01234567'.indexOf(ch);
1254
1255 // \0 is not octal escape sequence
1256 if (code !== 0) {
1257 octal = true;
1258 }
1259
1260 /* istanbul ignore else */
1261 if (index < length && isOctalDigit(source[index])) {
1262 octal = true;
1263 code = code * 8 + '01234567'.indexOf(source[index++]);
1264
1265 // 3 digits are only allowed when string starts
1266 // with 0, 1, 2, 3
1267 if ('0123'.indexOf(ch) >= 0 &&
1268 index < length &&
1269 isOctalDigit(source[index])) {
1270 code = code * 8 + '01234567'.indexOf(source[index++]);
1271 }
1272 }
1273 str += String.fromCharCode(code);
1274 } else {
1275 str += ch;
1276 }
1277 break;
1278 }
1279 } else {
1280 ++lineNumber;
1281 if (ch === '\r' && source[index] === '\n') {
1282 ++index;
1283 }
1284 lineStart = index;
1285 }
1286 } else if (isLineTerminator(ch.charCodeAt(0))) {
1287 break;
1288 } else {
1289 str += ch;
1290 }
1291 }
1292
1293 if (quote !== '') {
1294 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1295 }
1296
1297 return {
1298 type: Token.StringLiteral,
1299 value: str,
1300 octal: octal,
1301 lineNumber: lineNumber,
1302 lineStart: lineStart,
1303 range: [start, index]
1304 };
1305 }
1306
1307 function scanTemplate() {
1308 var cooked = '', ch, start, terminated, head, tail, restore, unescaped, code, octal;
1309
1310 terminated = false;
1311 tail = false;
1312 start = index;
1313 head = (source[index] === '`');
1314
1315 ++index;
1316
1317 while (index < length) {
1318 ch = source[index++];
1319 if (ch === '`') {
1320 tail = true;
1321 terminated = true;
1322 break;
1323 } else if (ch === '$') {
1324 if (source[index] === '{') {
1325 ++index;
1326 terminated = true;
1327 break;
1328 }
1329 cooked += ch;
1330 } else if (ch === '\\') {
1331 ch = source[index++];
1332 if (!isLineTerminator(ch.charCodeAt(0))) {
1333 switch (ch) {
1334 case 'n':
1335 cooked += '\n';
1336 break;
1337 case 'r':
1338 cooked += '\r';
1339 break;
1340 case 't':
1341 cooked += '\t';
1342 break;
1343 case 'u':
1344 case 'x':
1345 if (source[index] === '{') {
1346 ++index;
1347 cooked += scanUnicodeCodePointEscape();
1348 } else {
1349 restore = index;
1350 unescaped = scanHexEscape(ch);
1351 if (unescaped) {
1352 cooked += unescaped;
1353 } else {
1354 index = restore;
1355 cooked += ch;
1356 }
1357 }
1358 break;
1359 case 'b':
1360 cooked += '\b';
1361 break;
1362 case 'f':
1363 cooked += '\f';
1364 break;
1365 case 'v':
1366 cooked += '\v';
1367 break;
1368
1369 default:
1370 if (isOctalDigit(ch)) {
1371 code = '01234567'.indexOf(ch);
1372
1373 // \0 is not octal escape sequence
1374 if (code !== 0) {
1375 octal = true;
1376 }
1377
1378 /* istanbul ignore else */
1379 if (index < length && isOctalDigit(source[index])) {
1380 octal = true;
1381 code = code * 8 + '01234567'.indexOf(source[index++]);
1382
1383 // 3 digits are only allowed when string starts
1384 // with 0, 1, 2, 3
1385 if ('0123'.indexOf(ch) >= 0 &&
1386 index < length &&
1387 isOctalDigit(source[index])) {
1388 code = code * 8 + '01234567'.indexOf(source[index++]);
1389 }
1390 }
1391 cooked += String.fromCharCode(code);
1392 } else {
1393 cooked += ch;
1394 }
1395 break;
1396 }
1397 } else {
1398 ++lineNumber;
1399 if (ch === '\r' && source[index] === '\n') {
1400 ++index;
1401 }
1402 lineStart = index;
1403 }
1404 } else if (isLineTerminator(ch.charCodeAt(0))) {
1405 ++lineNumber;
1406 if (ch === '\r' && source[index] === '\n') {
1407 ++index;
1408 }
1409 lineStart = index;
1410 cooked += '\n';
1411 } else {
1412 cooked += ch;
1413 }
1414 }
1415
1416 if (!terminated) {
1417 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
1418 }
1419
1420 if (index > state.curlyLastIndex) {
1421 state.curlyLastIndex = index;
1422 if (!tail) {
1423 state.curlyStack.push('template');
1424 }
1425
1426 if (!head) {
1427 state.curlyStack.pop();
1428 }
1429 }
1430
1431 return {
1432 type: Token.Template,
1433 value: {
1434 cooked: cooked,
1435 raw: source.slice(start + 1, index - ((tail) ? 1 : 2))
1436 },
1437 head: head,
1438 tail: tail,
1439 octal: octal,
1440 lineNumber: lineNumber,
1441 lineStart: lineStart,
1442 range: [start, index]
1443 };
1444 }
1445
1446 function testRegExp(pattern, flags) {
1447 var tmp = pattern,
1448 value;
1449
1450 if (flags.indexOf('u') >= 0) {
1451 // Replace each astral symbol and every Unicode code point
1452 // escape sequence with a single ASCII symbol to avoid throwing on
1453 // regular expressions that are only valid in combination with the
1454 // `/u` flag.
1455 // Note: replacing with the ASCII symbol `x` might cause false
1456 // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
1457 // perfectly valid pattern that is equivalent to `[a-b]`, but it
1458 // would be replaced by `[x-b]` which throws an error.
1459 tmp = tmp
1460 .replace(/\\u\{([0-9a-fA-F]+)\}/g, function ($0, $1) {
1461 if (parseInt($1, 16) <= 0x10FFFF) {
1462 return 'x';
1463 }
1464 throwError({}, Messages.InvalidRegExp);
1465 })
1466 .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x');
1467 }
1468
1469 // First, detect invalid regular expressions.
1470 try {
1471 value = new RegExp(tmp);
1472 } catch (e) {
1473 throwError({}, Messages.InvalidRegExp);
1474 }
1475
1476 // Return a regular expression object for this pattern-flag pair, or
1477 // `null` in case the current environment doesn't support the flags it
1478 // uses.
1479 try {
1480 return new RegExp(pattern, flags);
1481 } catch (exception) {
1482 return null;
1483 }
1484 }
1485
1486 function scanRegExpBody() {
1487 var ch, str, classMarker, terminated, body;
1488
1489 ch = source[index];
1490 assert(ch === '/', 'Regular expression literal must start with a slash');
1491 str = source[index++];
1492
1493 classMarker = false;
1494 terminated = false;
1495 while (index < length) {
1496 ch = source[index++];
1497 str += ch;
1498 if (ch === '\\') {
1499 ch = source[index++];
1500 // ECMA-262 7.8.5
1501 if (isLineTerminator(ch.charCodeAt(0))) {
1502 throwError({}, Messages.UnterminatedRegExp);
1503 }
1504 str += ch;
1505 } else if (isLineTerminator(ch.charCodeAt(0))) {
1506 throwError({}, Messages.UnterminatedRegExp);
1507 } else if (classMarker) {
1508 if (ch === ']') {
1509 classMarker = false;
1510 }
1511 } else {
1512 if (ch === '/') {
1513 terminated = true;
1514 break;
1515 } else if (ch === '[') {
1516 classMarker = true;
1517 }
1518 }
1519 }
1520
1521 if (!terminated) {
1522 throwError({}, Messages.UnterminatedRegExp);
1523 }
1524
1525 // Exclude leading and trailing slash.
1526 body = str.substr(1, str.length - 2);
1527 return {
1528 value: body,
1529 literal: str
1530 };
1531 }
1532
1533 function scanRegExpFlags() {
1534 var ch, str, flags, restore;
1535
1536 str = '';
1537 flags = '';
1538 while (index < length) {
1539 ch = source[index];
1540 if (!isIdentifierPart(ch.charCodeAt(0))) {
1541 break;
1542 }
1543
1544 ++index;
1545 if (ch === '\\' && index < length) {
1546 ch = source[index];
1547 if (ch === 'u') {
1548 ++index;
1549 restore = index;
1550 ch = scanHexEscape('u');
1551 if (ch) {
1552 flags += ch;
1553 for (str += '\\u'; restore < index; ++restore) {
1554 str += source[restore];
1555 }
1556 } else {
1557 index = restore;
1558 flags += 'u';
1559 str += '\\u';
1560 }
1561 throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
1562 } else {
1563 str += '\\';
1564 throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
1565 }
1566 } else {
1567 flags += ch;
1568 str += ch;
1569 }
1570 }
1571
1572 return {
1573 value: flags,
1574 literal: str
1575 };
1576 }
1577
1578 function scanRegExp() {
1579 var start, body, flags, value;
1580
1581 lookahead = null;
1582 skipComment();
1583 start = index;
1584
1585 body = scanRegExpBody();
1586 flags = scanRegExpFlags();
1587 value = testRegExp(body.value, flags.value);
1588
1589 if (extra.tokenize) {
1590 return {
1591 type: Token.RegularExpression,
1592 value: value,
1593 regex: {
1594 pattern: body.value,
1595 flags: flags.value
1596 },
1597 lineNumber: lineNumber,
1598 lineStart: lineStart,
1599 range: [start, index]
1600 };
1601 }
1602
1603 return {
1604 literal: body.literal + flags.literal,
1605 value: value,
1606 regex: {
1607 pattern: body.value,
1608 flags: flags.value
1609 },
1610 range: [start, index]
1611 };
1612 }
1613
1614 function isIdentifierName(token) {
1615 return token.type === Token.Identifier ||
1616 token.type === Token.Keyword ||
1617 token.type === Token.BooleanLiteral ||
1618 token.type === Token.NullLiteral;
1619 }
1620
1621 function advanceSlash() {
1622 var prevToken,
1623 checkToken;
1624 // Using the following algorithm:
1625 // https://github.com/mozilla/sweet.js/wiki/design
1626 prevToken = extra.tokens[extra.tokens.length - 1];
1627 if (!prevToken) {
1628 // Nothing before that: it cannot be a division.
1629 return scanRegExp();
1630 }
1631 if (prevToken.type === 'Punctuator') {
1632 if (prevToken.value === ')') {
1633 checkToken = extra.tokens[extra.openParenToken - 1];
1634 if (checkToken &&
1635 checkToken.type === 'Keyword' &&
1636 (checkToken.value === 'if' ||
1637 checkToken.value === 'while' ||
1638 checkToken.value === 'for' ||
1639 checkToken.value === 'with')) {
1640 return scanRegExp();
1641 }
1642 return scanPunctuator();
1643 }
1644 if (prevToken.value === '}') {
1645 // Dividing a function by anything makes little sense,
1646 // but we have to check for that.
1647 if (extra.tokens[extra.openCurlyToken - 3] &&
1648 extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') {
1649 // Anonymous function.
1650 checkToken = extra.tokens[extra.openCurlyToken - 4];
1651 if (!checkToken) {
1652 return scanPunctuator();
1653 }
1654 } else if (extra.tokens[extra.openCurlyToken - 4] &&
1655 extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') {
1656 // Named function.
1657 checkToken = extra.tokens[extra.openCurlyToken - 5];
1658 if (!checkToken) {
1659 return scanRegExp();
1660 }
1661 } else {
1662 return scanPunctuator();
1663 }
1664 // checkToken determines whether the function is
1665 // a declaration or an expression.
1666 if (FnExprTokens.indexOf(checkToken.value) >= 0) {
1667 // It is an expression.
1668 return scanPunctuator();
1669 }
1670 // It is a declaration.
1671 return scanRegExp();
1672 }
1673 return scanRegExp();
1674 }
1675 if (prevToken.type === 'Keyword' && prevToken.value !== 'this') {
1676 return scanRegExp();
1677 }
1678 return scanPunctuator();
1679 }
1680
1681 function advance() {
1682 var ch;
1683
1684 if (!state.inJSXChild) {
1685 skipComment();
1686 }
1687
1688 if (index >= length) {
1689 return {
1690 type: Token.EOF,
1691 lineNumber: lineNumber,
1692 lineStart: lineStart,
1693 range: [index, index]
1694 };
1695 }
1696
1697 if (state.inJSXChild) {
1698 return advanceJSXChild();
1699 }
1700
1701 ch = source.charCodeAt(index);
1702
1703 // Very common: ( and ) and ;
1704 if (ch === 40 || ch === 41 || ch === 58) {
1705 return scanPunctuator();
1706 }
1707
1708 // String literal starts with single quote (#39) or double quote (#34).
1709 if (ch === 39 || ch === 34) {
1710 if (state.inJSXTag) {
1711 return scanJSXStringLiteral();
1712 }
1713 return scanStringLiteral();
1714 }
1715
1716 if (state.inJSXTag && isJSXIdentifierStart(ch)) {
1717 return scanJSXIdentifier();
1718 }
1719
1720 // Template literals start with backtick (#96) for template head
1721 // or close curly (#125) for template middle or template tail.
1722 if (ch === 96 || (ch === 125 && state.curlyStack[state.curlyStack.length - 1] === 'template')) {
1723 return scanTemplate();
1724 }
1725 if (isIdentifierStart(ch)) {
1726 return scanIdentifier();
1727 }
1728
1729 // Dot (.) char #46 can also start a floating-point number, hence the need
1730 // to check the next character.
1731 if (ch === 46) {
1732 if (isDecimalDigit(source.charCodeAt(index + 1))) {
1733 return scanNumericLiteral();
1734 }
1735 return scanPunctuator();
1736 }
1737
1738 if (isDecimalDigit(ch)) {
1739 return scanNumericLiteral();
1740 }
1741
1742 // Slash (/) char #47 can also start a regex.
1743 if (extra.tokenize && ch === 47) {
1744 return advanceSlash();
1745 }
1746
1747 return scanPunctuator();
1748 }
1749
1750 function lex() {
1751 var token;
1752
1753 token = lookahead;
1754 index = token.range[1];
1755 lineNumber = token.lineNumber;
1756 lineStart = token.lineStart;
1757
1758 lookahead = advance();
1759
1760 index = token.range[1];
1761 lineNumber = token.lineNumber;
1762 lineStart = token.lineStart;
1763
1764 return token;
1765 }
1766
1767 function peek() {
1768 var pos, line, start;
1769
1770 pos = index;
1771 line = lineNumber;
1772 start = lineStart;
1773 lookahead = advance();
1774 index = pos;
1775 lineNumber = line;
1776 lineStart = start;
1777 }
1778
1779 function lookahead2() {
1780 var adv, pos, line, start, result;
1781
1782 // If we are collecting the tokens, don't grab the next one yet.
1783 /* istanbul ignore next */
1784 adv = (typeof extra.advance === 'function') ? extra.advance : advance;
1785
1786 pos = index;
1787 line = lineNumber;
1788 start = lineStart;
1789
1790 // Scan for the next immediate token.
1791 /* istanbul ignore if */
1792 if (lookahead === null) {
1793 lookahead = adv();
1794 }
1795 index = lookahead.range[1];
1796 lineNumber = lookahead.lineNumber;
1797 lineStart = lookahead.lineStart;
1798
1799 // Grab the token right after.
1800 result = adv();
1801 index = pos;
1802 lineNumber = line;
1803 lineStart = start;
1804
1805 return result;
1806 }
1807
1808 function rewind(token) {
1809 index = token.range[0];
1810 lineNumber = token.lineNumber;
1811 lineStart = token.lineStart;
1812 lookahead = token;
1813 }
1814
1815 function markerCreate() {
1816 if (!extra.loc && !extra.range) {
1817 return undefined;
1818 }
1819 skipComment();
1820 return {offset: index, line: lineNumber, col: index - lineStart};
1821 }
1822
1823 function markerCreatePreserveWhitespace() {
1824 if (!extra.loc && !extra.range) {
1825 return undefined;
1826 }
1827 return {offset: index, line: lineNumber, col: index - lineStart};
1828 }
1829
1830 function processComment(node) {
1831 var lastChild,
1832 trailingComments,
1833 bottomRight = extra.bottomRightStack,
1834 last = bottomRight[bottomRight.length - 1];
1835
1836 if (node.type === Syntax.Program) {
1837 /* istanbul ignore else */
1838 if (node.body.length > 0) {
1839 return;
1840 }
1841 }
1842
1843 if (extra.trailingComments.length > 0) {
1844 if (extra.trailingComments[0].range[0] >= node.range[1]) {
1845 trailingComments = extra.trailingComments;
1846 extra.trailingComments = [];
1847 } else {
1848 extra.trailingComments.length = 0;
1849 }
1850 } else {
1851 if (last && last.trailingComments && last.trailingComments[0].range[0] >= node.range[1]) {
1852 trailingComments = last.trailingComments;
1853 delete last.trailingComments;
1854 }
1855 }
1856
1857 // Eating the stack.
1858 if (last) {
1859 while (last && last.range[0] >= node.range[0]) {
1860 lastChild = last;
1861 last = bottomRight.pop();
1862 }
1863 }
1864
1865 if (lastChild) {
1866 if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= node.range[0]) {
1867 node.leadingComments = lastChild.leadingComments;
1868 delete lastChild.leadingComments;
1869 }
1870 } else if (extra.leadingComments.length > 0 && extra.leadingComments[extra.leadingComments.length - 1].range[1] <= node.range[0]) {
1871 node.leadingComments = extra.leadingComments;
1872 extra.leadingComments = [];
1873 }
1874
1875 if (trailingComments) {
1876 node.trailingComments = trailingComments;
1877 }
1878
1879 bottomRight.push(node);
1880 }
1881
1882 function markerApply(marker, node) {
1883 if (extra.range) {
1884 node.range = [marker.offset, index];
1885 }
1886 if (extra.loc) {
1887 node.loc = {
1888 start: {
1889 line: marker.line,
1890 column: marker.col
1891 },
1892 end: {
1893 line: lineNumber,
1894 column: index - lineStart
1895 }
1896 };
1897 node = delegate.postProcess(node);
1898 }
1899 if (extra.attachComment) {
1900 processComment(node);
1901 }
1902 return node;
1903 }
1904
1905 SyntaxTreeDelegate = {
1906
1907 name: 'SyntaxTree',
1908
1909 postProcess: function (node) {
1910 return node;
1911 },
1912
1913 createArrayExpression: function (elements) {
1914 return {
1915 type: Syntax.ArrayExpression,
1916 elements: elements
1917 };
1918 },
1919
1920 createAssignmentExpression: function (operator, left, right) {
1921 return {
1922 type: Syntax.AssignmentExpression,
1923 operator: operator,
1924 left: left,
1925 right: right
1926 };
1927 },
1928
1929 createBinaryExpression: function (operator, left, right) {
1930 var type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression :
1931 Syntax.BinaryExpression;
1932 return {
1933 type: type,
1934 operator: operator,
1935 left: left,
1936 right: right
1937 };
1938 },
1939
1940 createBlockStatement: function (body) {
1941 return {
1942 type: Syntax.BlockStatement,
1943 body: body
1944 };
1945 },
1946
1947 createBreakStatement: function (label) {
1948 return {
1949 type: Syntax.BreakStatement,
1950 label: label
1951 };
1952 },
1953
1954 createCallExpression: function (callee, args) {
1955 return {
1956 type: Syntax.CallExpression,
1957 callee: callee,
1958 'arguments': args
1959 };
1960 },
1961
1962 createCatchClause: function (param, body) {
1963 return {
1964 type: Syntax.CatchClause,
1965 param: param,
1966 body: body
1967 };
1968 },
1969
1970 createConditionalExpression: function (test, consequent, alternate) {
1971 return {
1972 type: Syntax.ConditionalExpression,
1973 test: test,
1974 consequent: consequent,
1975 alternate: alternate
1976 };
1977 },
1978
1979 createContinueStatement: function (label) {
1980 return {
1981 type: Syntax.ContinueStatement,
1982 label: label
1983 };
1984 },
1985
1986 createDebuggerStatement: function () {
1987 return {
1988 type: Syntax.DebuggerStatement
1989 };
1990 },
1991
1992 createDoWhileStatement: function (body, test) {
1993 return {
1994 type: Syntax.DoWhileStatement,
1995 body: body,
1996 test: test
1997 };
1998 },
1999
2000 createEmptyStatement: function () {
2001 return {
2002 type: Syntax.EmptyStatement
2003 };
2004 },
2005
2006 createExpressionStatement: function (expression) {
2007 return {
2008 type: Syntax.ExpressionStatement,
2009 expression: expression
2010 };
2011 },
2012
2013 createForStatement: function (init, test, update, body) {
2014 return {
2015 type: Syntax.ForStatement,
2016 init: init,
2017 test: test,
2018 update: update,
2019 body: body
2020 };
2021 },
2022
2023 createForInStatement: function (left, right, body) {
2024 return {
2025 type: Syntax.ForInStatement,
2026 left: left,
2027 right: right,
2028 body: body,
2029 each: false
2030 };
2031 },
2032
2033 createForOfStatement: function (left, right, body) {
2034 return {
2035 type: Syntax.ForOfStatement,
2036 left: left,
2037 right: right,
2038 body: body
2039 };
2040 },
2041
2042 createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression,
2043 isAsync, returnType, typeParameters) {
2044 var funDecl = {
2045 type: Syntax.FunctionDeclaration,
2046 id: id,
2047 params: params,
2048 defaults: defaults,
2049 body: body,
2050 rest: rest,
2051 generator: generator,
2052 expression: expression,
2053 returnType: returnType,
2054 typeParameters: typeParameters
2055 };
2056
2057 if (isAsync) {
2058 funDecl.async = true;
2059 }
2060
2061 return funDecl;
2062 },
2063
2064 createFunctionExpression: function (id, params, defaults, body, rest, generator, expression,
2065 isAsync, returnType, typeParameters) {
2066 var funExpr = {
2067 type: Syntax.FunctionExpression,
2068 id: id,
2069 params: params,
2070 defaults: defaults,
2071 body: body,
2072 rest: rest,
2073 generator: generator,
2074 expression: expression,
2075 returnType: returnType,
2076 typeParameters: typeParameters
2077 };
2078
2079 if (isAsync) {
2080 funExpr.async = true;
2081 }
2082
2083 return funExpr;
2084 },
2085
2086 createIdentifier: function (name) {
2087 return {
2088 type: Syntax.Identifier,
2089 name: name,
2090 // Only here to initialize the shape of the object to ensure
2091 // that the 'typeAnnotation' key is ordered before others that
2092 // are added later (like 'loc' and 'range'). This just helps
2093 // keep the shape of Identifier nodes consistent with everything
2094 // else.
2095 typeAnnotation: undefined,
2096 optional: undefined
2097 };
2098 },
2099
2100 createTypeAnnotation: function (typeAnnotation) {
2101 return {
2102 type: Syntax.TypeAnnotation,
2103 typeAnnotation: typeAnnotation
2104 };
2105 },
2106
2107 createTypeCast: function (expression, typeAnnotation) {
2108 return {
2109 type: Syntax.TypeCastExpression,
2110 expression: expression,
2111 typeAnnotation: typeAnnotation
2112 };
2113 },
2114
2115 createFunctionTypeAnnotation: function (params, returnType, rest, typeParameters) {
2116 return {
2117 type: Syntax.FunctionTypeAnnotation,
2118 params: params,
2119 returnType: returnType,
2120 rest: rest,
2121 typeParameters: typeParameters
2122 };
2123 },
2124
2125 createFunctionTypeParam: function (name, typeAnnotation, optional) {
2126 return {
2127 type: Syntax.FunctionTypeParam,
2128 name: name,
2129 typeAnnotation: typeAnnotation,
2130 optional: optional
2131 };
2132 },
2133
2134 createNullableTypeAnnotation: function (typeAnnotation) {
2135 return {
2136 type: Syntax.NullableTypeAnnotation,
2137 typeAnnotation: typeAnnotation
2138 };
2139 },
2140
2141 createArrayTypeAnnotation: function (elementType) {
2142 return {
2143 type: Syntax.ArrayTypeAnnotation,
2144 elementType: elementType
2145 };
2146 },
2147
2148 createGenericTypeAnnotation: function (id, typeParameters) {
2149 return {
2150 type: Syntax.GenericTypeAnnotation,
2151 id: id,
2152 typeParameters: typeParameters
2153 };
2154 },
2155
2156 createQualifiedTypeIdentifier: function (qualification, id) {
2157 return {
2158 type: Syntax.QualifiedTypeIdentifier,
2159 qualification: qualification,
2160 id: id
2161 };
2162 },
2163
2164 createTypeParameterDeclaration: function (params) {
2165 return {
2166 type: Syntax.TypeParameterDeclaration,
2167 params: params
2168 };
2169 },
2170
2171 createTypeParameterInstantiation: function (params) {
2172 return {
2173 type: Syntax.TypeParameterInstantiation,
2174 params: params
2175 };
2176 },
2177
2178 createAnyTypeAnnotation: function () {
2179 return {
2180 type: Syntax.AnyTypeAnnotation
2181 };
2182 },
2183
2184 createBooleanTypeAnnotation: function () {
2185 return {
2186 type: Syntax.BooleanTypeAnnotation
2187 };
2188 },
2189
2190 createNumberTypeAnnotation: function () {
2191 return {
2192 type: Syntax.NumberTypeAnnotation
2193 };
2194 },
2195
2196 createStringTypeAnnotation: function () {
2197 return {
2198 type: Syntax.StringTypeAnnotation
2199 };
2200 },
2201
2202 createStringLiteralTypeAnnotation: function (token) {
2203 return {
2204 type: Syntax.StringLiteralTypeAnnotation,
2205 value: token.value,
2206 raw: source.slice(token.range[0], token.range[1])
2207 };
2208 },
2209
2210 createVoidTypeAnnotation: function () {
2211 return {
2212 type: Syntax.VoidTypeAnnotation
2213 };
2214 },
2215
2216 createTypeofTypeAnnotation: function (argument) {
2217 return {
2218 type: Syntax.TypeofTypeAnnotation,
2219 argument: argument
2220 };
2221 },
2222
2223 createTupleTypeAnnotation: function (types) {
2224 return {
2225 type: Syntax.TupleTypeAnnotation,
2226 types: types
2227 };
2228 },
2229
2230 createObjectTypeAnnotation: function (properties, indexers, callProperties) {
2231 return {
2232 type: Syntax.ObjectTypeAnnotation,
2233 properties: properties,
2234 indexers: indexers,
2235 callProperties: callProperties
2236 };
2237 },
2238
2239 createObjectTypeIndexer: function (id, key, value, isStatic) {
2240 return {
2241 type: Syntax.ObjectTypeIndexer,
2242 id: id,
2243 key: key,
2244 value: value,
2245 static: isStatic
2246 };
2247 },
2248
2249 createObjectTypeCallProperty: function (value, isStatic) {
2250 return {
2251 type: Syntax.ObjectTypeCallProperty,
2252 value: value,
2253 static: isStatic
2254 };
2255 },
2256
2257 createObjectTypeProperty: function (key, value, optional, isStatic) {
2258 return {
2259 type: Syntax.ObjectTypeProperty,
2260 key: key,
2261 value: value,
2262 optional: optional,
2263 static: isStatic
2264 };
2265 },
2266
2267 createUnionTypeAnnotation: function (types) {
2268 return {
2269 type: Syntax.UnionTypeAnnotation,
2270 types: types
2271 };
2272 },
2273
2274 createIntersectionTypeAnnotation: function (types) {
2275 return {
2276 type: Syntax.IntersectionTypeAnnotation,
2277 types: types
2278 };
2279 },
2280
2281 createTypeAlias: function (id, typeParameters, right) {
2282 return {
2283 type: Syntax.TypeAlias,
2284 id: id,
2285 typeParameters: typeParameters,
2286 right: right
2287 };
2288 },
2289
2290 createInterface: function (id, typeParameters, body, extended) {
2291 return {
2292 type: Syntax.InterfaceDeclaration,
2293 id: id,
2294 typeParameters: typeParameters,
2295 body: body,
2296 extends: extended
2297 };
2298 },
2299
2300 createInterfaceExtends: function (id, typeParameters) {
2301 return {
2302 type: Syntax.InterfaceExtends,
2303 id: id,
2304 typeParameters: typeParameters
2305 };
2306 },
2307
2308 createDeclareFunction: function (id) {
2309 return {
2310 type: Syntax.DeclareFunction,
2311 id: id
2312 };
2313 },
2314
2315 createDeclareVariable: function (id) {
2316 return {
2317 type: Syntax.DeclareVariable,
2318 id: id
2319 };
2320 },
2321
2322 createDeclareModule: function (id, body) {
2323 return {
2324 type: Syntax.DeclareModule,
2325 id: id,
2326 body: body
2327 };
2328 },
2329
2330 createJSXAttribute: function (name, value) {
2331 return {
2332 type: Syntax.JSXAttribute,
2333 name: name,
2334 value: value || null
2335 };
2336 },
2337
2338 createJSXSpreadAttribute: function (argument) {
2339 return {
2340 type: Syntax.JSXSpreadAttribute,
2341 argument: argument
2342 };
2343 },
2344
2345 createJSXIdentifier: function (name) {
2346 return {
2347 type: Syntax.JSXIdentifier,
2348 name: name
2349 };
2350 },
2351
2352 createJSXNamespacedName: function (namespace, name) {
2353 return {
2354 type: Syntax.JSXNamespacedName,
2355 namespace: namespace,
2356 name: name
2357 };
2358 },
2359
2360 createJSXMemberExpression: function (object, property) {
2361 return {
2362 type: Syntax.JSXMemberExpression,
2363 object: object,
2364 property: property
2365 };
2366 },
2367
2368 createJSXElement: function (openingElement, closingElement, children) {
2369 return {
2370 type: Syntax.JSXElement,
2371 openingElement: openingElement,
2372 closingElement: closingElement,
2373 children: children
2374 };
2375 },
2376
2377 createJSXEmptyExpression: function () {
2378 return {
2379 type: Syntax.JSXEmptyExpression
2380 };
2381 },
2382
2383 createJSXExpressionContainer: function (expression) {
2384 return {
2385 type: Syntax.JSXExpressionContainer,
2386 expression: expression
2387 };
2388 },
2389
2390 createJSXOpeningElement: function (name, attributes, selfClosing) {
2391 return {
2392 type: Syntax.JSXOpeningElement,
2393 name: name,
2394 selfClosing: selfClosing,
2395 attributes: attributes
2396 };
2397 },
2398
2399 createJSXClosingElement: function (name) {
2400 return {
2401 type: Syntax.JSXClosingElement,
2402 name: name
2403 };
2404 },
2405
2406 createIfStatement: function (test, consequent, alternate) {
2407 return {
2408 type: Syntax.IfStatement,
2409 test: test,
2410 consequent: consequent,
2411 alternate: alternate
2412 };
2413 },
2414
2415 createLabeledStatement: function (label, body) {
2416 return {
2417 type: Syntax.LabeledStatement,
2418 label: label,
2419 body: body
2420 };
2421 },
2422
2423 createLiteral: function (token) {
2424 var object = {
2425 type: Syntax.Literal,
2426 value: token.value,
2427 raw: source.slice(token.range[0], token.range[1])
2428 };
2429 if (token.regex) {
2430 object.regex = token.regex;
2431 }
2432 return object;
2433 },
2434
2435 createMemberExpression: function (accessor, object, property) {
2436 return {
2437 type: Syntax.MemberExpression,
2438 computed: accessor === '[',
2439 object: object,
2440 property: property
2441 };
2442 },
2443
2444 createNewExpression: function (callee, args) {
2445 return {
2446 type: Syntax.NewExpression,
2447 callee: callee,
2448 'arguments': args
2449 };
2450 },
2451
2452 createObjectExpression: function (properties) {
2453 return {
2454 type: Syntax.ObjectExpression,
2455 properties: properties
2456 };
2457 },
2458
2459 createPostfixExpression: function (operator, argument) {
2460 return {
2461 type: Syntax.UpdateExpression,
2462 operator: operator,
2463 argument: argument,
2464 prefix: false
2465 };
2466 },
2467
2468 createProgram: function (body) {
2469 return {
2470 type: Syntax.Program,
2471 body: body
2472 };
2473 },
2474
2475 createProperty: function (kind, key, value, method, shorthand, computed) {
2476 return {
2477 type: Syntax.Property,
2478 key: key,
2479 value: value,
2480 kind: kind,
2481 method: method,
2482 shorthand: shorthand,
2483 computed: computed
2484 };
2485 },
2486
2487 createReturnStatement: function (argument) {
2488 return {
2489 type: Syntax.ReturnStatement,
2490 argument: argument
2491 };
2492 },
2493
2494 createSequenceExpression: function (expressions) {
2495 return {
2496 type: Syntax.SequenceExpression,
2497 expressions: expressions
2498 };
2499 },
2500
2501 createSwitchCase: function (test, consequent) {
2502 return {
2503 type: Syntax.SwitchCase,
2504 test: test,
2505 consequent: consequent
2506 };
2507 },
2508
2509 createSwitchStatement: function (discriminant, cases) {
2510 return {
2511 type: Syntax.SwitchStatement,
2512 discriminant: discriminant,
2513 cases: cases
2514 };
2515 },
2516
2517 createThisExpression: function () {
2518 return {
2519 type: Syntax.ThisExpression
2520 };
2521 },
2522
2523 createThrowStatement: function (argument) {
2524 return {
2525 type: Syntax.ThrowStatement,
2526 argument: argument
2527 };
2528 },
2529
2530 createTryStatement: function (block, guardedHandlers, handlers, finalizer) {
2531 return {
2532 type: Syntax.TryStatement,
2533 block: block,
2534 guardedHandlers: guardedHandlers,
2535 handlers: handlers,
2536 finalizer: finalizer
2537 };
2538 },
2539
2540 createUnaryExpression: function (operator, argument) {
2541 if (operator === '++' || operator === '--') {
2542 return {
2543 type: Syntax.UpdateExpression,
2544 operator: operator,
2545 argument: argument,
2546 prefix: true
2547 };
2548 }
2549 return {
2550 type: Syntax.UnaryExpression,
2551 operator: operator,
2552 argument: argument,
2553 prefix: true
2554 };
2555 },
2556
2557 createVariableDeclaration: function (declarations, kind) {
2558 return {
2559 type: Syntax.VariableDeclaration,
2560 declarations: declarations,
2561 kind: kind
2562 };
2563 },
2564
2565 createVariableDeclarator: function (id, init) {
2566 return {
2567 type: Syntax.VariableDeclarator,
2568 id: id,
2569 init: init
2570 };
2571 },
2572
2573 createWhileStatement: function (test, body) {
2574 return {
2575 type: Syntax.WhileStatement,
2576 test: test,
2577 body: body
2578 };
2579 },
2580
2581 createWithStatement: function (object, body) {
2582 return {
2583 type: Syntax.WithStatement,
2584 object: object,
2585 body: body
2586 };
2587 },
2588
2589 createTemplateElement: function (value, tail) {
2590 return {
2591 type: Syntax.TemplateElement,
2592 value: value,
2593 tail: tail
2594 };
2595 },
2596
2597 createTemplateLiteral: function (quasis, expressions) {
2598 return {
2599 type: Syntax.TemplateLiteral,
2600 quasis: quasis,
2601 expressions: expressions
2602 };
2603 },
2604
2605 createSpreadElement: function (argument) {
2606 return {
2607 type: Syntax.SpreadElement,
2608 argument: argument
2609 };
2610 },
2611
2612 createSpreadProperty: function (argument) {
2613 return {
2614 type: Syntax.SpreadProperty,
2615 argument: argument
2616 };
2617 },
2618
2619 createTaggedTemplateExpression: function (tag, quasi) {
2620 return {
2621 type: Syntax.TaggedTemplateExpression,
2622 tag: tag,
2623 quasi: quasi
2624 };
2625 },
2626
2627 createArrowFunctionExpression: function (params, defaults, body, rest, expression, isAsync) {
2628 var arrowExpr = {
2629 type: Syntax.ArrowFunctionExpression,
2630 id: null,
2631 params: params,
2632 defaults: defaults,
2633 body: body,
2634 rest: rest,
2635 generator: false,
2636 expression: expression
2637 };
2638
2639 if (isAsync) {
2640 arrowExpr.async = true;
2641 }
2642
2643 return arrowExpr;
2644 },
2645
2646 createMethodDefinition: function (propertyType, kind, key, value, computed) {
2647 return {
2648 type: Syntax.MethodDefinition,
2649 key: key,
2650 value: value,
2651 kind: kind,
2652 'static': propertyType === ClassPropertyType.static,
2653 computed: computed
2654 };
2655 },
2656
2657 createClassProperty: function (key, typeAnnotation, computed, isStatic) {
2658 return {
2659 type: Syntax.ClassProperty,
2660 key: key,
2661 typeAnnotation: typeAnnotation,
2662 computed: computed,
2663 static: isStatic
2664 };
2665 },
2666
2667 createClassBody: function (body) {
2668 return {
2669 type: Syntax.ClassBody,
2670 body: body
2671 };
2672 },
2673
2674 createClassImplements: function (id, typeParameters) {
2675 return {
2676 type: Syntax.ClassImplements,
2677 id: id,
2678 typeParameters: typeParameters
2679 };
2680 },
2681
2682 createClassExpression: function (id, superClass, body, typeParameters, superTypeParameters, implemented) {
2683 return {
2684 type: Syntax.ClassExpression,
2685 id: id,
2686 superClass: superClass,
2687 body: body,
2688 typeParameters: typeParameters,
2689 superTypeParameters: superTypeParameters,
2690 implements: implemented
2691 };
2692 },
2693
2694 createClassDeclaration: function (id, superClass, body, typeParameters, superTypeParameters, implemented) {
2695 return {
2696 type: Syntax.ClassDeclaration,
2697 id: id,
2698 superClass: superClass,
2699 body: body,
2700 typeParameters: typeParameters,
2701 superTypeParameters: superTypeParameters,
2702 implements: implemented
2703 };
2704 },
2705
2706 createExportSpecifier: function (id, name) {
2707 return {
2708 type: Syntax.ExportSpecifier,
2709 id: id,
2710 name: name
2711 };
2712 },
2713
2714 createExportBatchSpecifier: function () {
2715 return {
2716 type: Syntax.ExportBatchSpecifier
2717 };
2718 },
2719
2720 createImportDefaultSpecifier: function (id) {
2721 return {
2722 type: Syntax.ImportDefaultSpecifier,
2723 id: id
2724 };
2725 },
2726
2727 createImportNamespaceSpecifier: function (id) {
2728 return {
2729 type: Syntax.ImportNamespaceSpecifier,
2730 id: id
2731 };
2732 },
2733
2734 createExportDeclaration: function (isDefault, declaration, specifiers, src) {
2735 return {
2736 type: Syntax.ExportDeclaration,
2737 'default': !!isDefault,
2738 declaration: declaration,
2739 specifiers: specifiers,
2740 source: src
2741 };
2742 },
2743
2744 createImportSpecifier: function (id, name) {
2745 return {
2746 type: Syntax.ImportSpecifier,
2747 id: id,
2748 name: name
2749 };
2750 },
2751
2752 createImportDeclaration: function (specifiers, src, isType) {
2753 return {
2754 type: Syntax.ImportDeclaration,
2755 specifiers: specifiers,
2756 source: src,
2757 isType: isType
2758 };
2759 },
2760
2761 createYieldExpression: function (argument, dlg) {
2762 return {
2763 type: Syntax.YieldExpression,
2764 argument: argument,
2765 delegate: dlg
2766 };
2767 },
2768
2769 createAwaitExpression: function (argument) {
2770 return {
2771 type: Syntax.AwaitExpression,
2772 argument: argument
2773 };
2774 },
2775
2776 createComprehensionExpression: function (filter, blocks, body) {
2777 return {
2778 type: Syntax.ComprehensionExpression,
2779 filter: filter,
2780 blocks: blocks,
2781 body: body
2782 };
2783 }
2784
2785 };
2786
2787 // Return true if there is a line terminator before the next token.
2788
2789 function peekLineTerminator() {
2790 var pos, line, start, found;
2791
2792 pos = index;
2793 line = lineNumber;
2794 start = lineStart;
2795 skipComment();
2796 found = lineNumber !== line;
2797 index = pos;
2798 lineNumber = line;
2799 lineStart = start;
2800
2801 return found;
2802 }
2803
2804 // Throw an exception
2805
2806 function throwError(token, messageFormat) {
2807 var error,
2808 args = Array.prototype.slice.call(arguments, 2),
2809 msg = messageFormat.replace(
2810 /%(\d)/g,
2811 function (whole, idx) {
2812 assert(idx < args.length, 'Message reference must be in range');
2813 return args[idx];
2814 }
2815 );
2816
2817 if (typeof token.lineNumber === 'number') {
2818 error = new Error('Line ' + token.lineNumber + ': ' + msg);
2819 error.index = token.range[0];
2820 error.lineNumber = token.lineNumber;
2821 error.column = token.range[0] - lineStart + 1;
2822 } else {
2823 error = new Error('Line ' + lineNumber + ': ' + msg);
2824 error.index = index;
2825 error.lineNumber = lineNumber;
2826 error.column = index - lineStart + 1;
2827 }
2828
2829 error.description = msg;
2830 throw error;
2831 }
2832
2833 function throwErrorTolerant() {
2834 try {
2835 throwError.apply(null, arguments);
2836 } catch (e) {
2837 if (extra.errors) {
2838 extra.errors.push(e);
2839 } else {
2840 throw e;
2841 }
2842 }
2843 }
2844
2845
2846 // Throw an exception because of the token.
2847
2848 function throwUnexpected(token) {
2849 if (token.type === Token.EOF) {
2850 throwError(token, Messages.UnexpectedEOS);
2851 }
2852
2853 if (token.type === Token.NumericLiteral) {
2854 throwError(token, Messages.UnexpectedNumber);
2855 }
2856
2857 if (token.type === Token.StringLiteral || token.type === Token.JSXText) {
2858 throwError(token, Messages.UnexpectedString);
2859 }
2860
2861 if (token.type === Token.Identifier) {
2862 throwError(token, Messages.UnexpectedIdentifier);
2863 }
2864
2865 if (token.type === Token.Keyword) {
2866 if (isFutureReservedWord(token.value)) {
2867 throwError(token, Messages.UnexpectedReserved);
2868 } else if (strict && isStrictModeReservedWord(token.value)) {
2869 throwErrorTolerant(token, Messages.StrictReservedWord);
2870 return;
2871 }
2872 throwError(token, Messages.UnexpectedToken, token.value);
2873 }
2874
2875 if (token.type === Token.Template) {
2876 throwError(token, Messages.UnexpectedTemplate, token.value.raw);
2877 }
2878
2879 // BooleanLiteral, NullLiteral, or Punctuator.
2880 throwError(token, Messages.UnexpectedToken, token.value);
2881 }
2882
2883 // Expect the next token to match the specified punctuator.
2884 // If not, an exception will be thrown.
2885
2886 function expect(value) {
2887 var token = lex();
2888 if (token.type !== Token.Punctuator || token.value !== value) {
2889 throwUnexpected(token);
2890 }
2891 }
2892
2893 // Expect the next token to match the specified keyword.
2894 // If not, an exception will be thrown.
2895
2896 function expectKeyword(keyword, contextual) {
2897 var token = lex();
2898 if (token.type !== (contextual ? Token.Identifier : Token.Keyword) ||
2899 token.value !== keyword) {
2900 throwUnexpected(token);
2901 }
2902 }
2903
2904 // Expect the next token to match the specified contextual keyword.
2905 // If not, an exception will be thrown.
2906
2907 function expectContextualKeyword(keyword) {
2908 return expectKeyword(keyword, true);
2909 }
2910
2911 // Return true if the next token matches the specified punctuator.
2912
2913 function match(value) {
2914 return lookahead.type === Token.Punctuator && lookahead.value === value;
2915 }
2916
2917 // Return true if the next token matches the specified keyword
2918
2919 function matchKeyword(keyword, contextual) {
2920 var expectedType = contextual ? Token.Identifier : Token.Keyword;
2921 return lookahead.type === expectedType && lookahead.value === keyword;
2922 }
2923
2924 // Return true if the next token matches the specified contextual keyword
2925
2926 function matchContextualKeyword(keyword) {
2927 return matchKeyword(keyword, true);
2928 }
2929
2930 // Return true if the next token is an assignment operator
2931
2932 function matchAssign() {
2933 var op;
2934
2935 if (lookahead.type !== Token.Punctuator) {
2936 return false;
2937 }
2938 op = lookahead.value;
2939 return op === '=' ||
2940 op === '*=' ||
2941 op === '/=' ||
2942 op === '%=' ||
2943 op === '+=' ||
2944 op === '-=' ||
2945 op === '<<=' ||
2946 op === '>>=' ||
2947 op === '>>>=' ||
2948 op === '&=' ||
2949 op === '^=' ||
2950 op === '|=';
2951 }
2952
2953 // Note that 'yield' is treated as a keyword in strict mode, but a
2954 // contextual keyword (identifier) in non-strict mode, so we need to
2955 // use matchKeyword('yield', false) and matchKeyword('yield', true)
2956 // (i.e. matchContextualKeyword) appropriately.
2957 function matchYield() {
2958 return state.yieldAllowed && matchKeyword('yield', !strict);
2959 }
2960
2961 function matchAsync() {
2962 var backtrackToken = lookahead, matches = false;
2963
2964 if (matchContextualKeyword('async')) {
2965 lex(); // Make sure peekLineTerminator() starts after 'async'.
2966 matches = !peekLineTerminator();
2967 rewind(backtrackToken); // Revert the lex().
2968 }
2969
2970 return matches;
2971 }
2972
2973 function matchAwait() {
2974 return state.awaitAllowed && matchContextualKeyword('await');
2975 }
2976
2977 function consumeSemicolon() {
2978 var line, oldIndex = index, oldLineNumber = lineNumber,
2979 oldLineStart = lineStart, oldLookahead = lookahead;
2980
2981 // Catch the very common case first: immediately a semicolon (char #59).
2982 if (source.charCodeAt(index) === 59) {
2983 lex();
2984 return;
2985 }
2986
2987 line = lineNumber;
2988 skipComment();
2989 if (lineNumber !== line) {
2990 index = oldIndex;
2991 lineNumber = oldLineNumber;
2992 lineStart = oldLineStart;
2993 lookahead = oldLookahead;
2994 return;
2995 }
2996
2997 if (match(';')) {
2998 lex();
2999 return;
3000 }
3001
3002 if (lookahead.type !== Token.EOF && !match('}')) {
3003 throwUnexpected(lookahead);
3004 }
3005 }
3006
3007 // Return true if provided expression is LeftHandSideExpression
3008
3009 function isLeftHandSide(expr) {
3010 return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
3011 }
3012
3013 function isAssignableLeftHandSide(expr) {
3014 return isLeftHandSide(expr) || expr.type === Syntax.ObjectPattern || expr.type === Syntax.ArrayPattern;
3015 }
3016
3017 // 11.1.4 Array Initialiser
3018
3019 function parseArrayInitialiser() {
3020 var elements = [], blocks = [], filter = null, tmp, possiblecomprehension = true,
3021 marker = markerCreate();
3022
3023 expect('[');
3024 while (!match(']')) {
3025 if (lookahead.value === 'for' &&
3026 lookahead.type === Token.Keyword) {
3027 if (!possiblecomprehension) {
3028 throwError({}, Messages.ComprehensionError);
3029 }
3030 matchKeyword('for');
3031 tmp = parseForStatement({ignoreBody: true});
3032 tmp.of = tmp.type === Syntax.ForOfStatement;
3033 tmp.type = Syntax.ComprehensionBlock;
3034 if (tmp.left.kind) { // can't be let or const
3035 throwError({}, Messages.ComprehensionError);
3036 }
3037 blocks.push(tmp);
3038 } else if (lookahead.value === 'if' &&
3039 lookahead.type === Token.Keyword) {
3040 if (!possiblecomprehension) {
3041 throwError({}, Messages.ComprehensionError);
3042 }
3043 expectKeyword('if');
3044 expect('(');
3045 filter = parseExpression();
3046 expect(')');
3047 } else if (lookahead.value === ',' &&
3048 lookahead.type === Token.Punctuator) {
3049 possiblecomprehension = false; // no longer allowed.
3050 lex();
3051 elements.push(null);
3052 } else {
3053 tmp = parseSpreadOrAssignmentExpression();
3054 elements.push(tmp);
3055 if (tmp && tmp.type === Syntax.SpreadElement) {
3056 if (!match(']')) {
3057 throwError({}, Messages.ElementAfterSpreadElement);
3058 }
3059 } else if (!(match(']') || matchKeyword('for') || matchKeyword('if'))) {
3060 expect(','); // this lexes.
3061 possiblecomprehension = false;
3062 }
3063 }
3064 }
3065
3066 expect(']');
3067
3068 if (filter && !blocks.length) {
3069 throwError({}, Messages.ComprehensionRequiresBlock);
3070 }
3071
3072 if (blocks.length) {
3073 if (elements.length !== 1) {
3074 throwError({}, Messages.ComprehensionError);
3075 }
3076 return markerApply(marker, delegate.createComprehensionExpression(filter, blocks, elements[0]));
3077 }
3078 return markerApply(marker, delegate.createArrayExpression(elements));
3079 }
3080
3081 // 11.1.5 Object Initialiser
3082
3083 function parsePropertyFunction(options) {
3084 var previousStrict, previousYieldAllowed, previousAwaitAllowed,
3085 params, defaults, body, marker = markerCreate();
3086
3087 previousStrict = strict;
3088 previousYieldAllowed = state.yieldAllowed;
3089 state.yieldAllowed = options.generator;
3090 previousAwaitAllowed = state.awaitAllowed;
3091 state.awaitAllowed = options.async;
3092 params = options.params || [];
3093 defaults = options.defaults || [];
3094
3095 body = parseConciseBody();
3096 if (options.name && strict && isRestrictedWord(params[0].name)) {
3097 throwErrorTolerant(options.name, Messages.StrictParamName);
3098 }
3099 strict = previousStrict;
3100 state.yieldAllowed = previousYieldAllowed;
3101 state.awaitAllowed = previousAwaitAllowed;
3102
3103 return markerApply(marker, delegate.createFunctionExpression(
3104 null,
3105 params,
3106 defaults,
3107 body,
3108 options.rest || null,
3109 options.generator,
3110 body.type !== Syntax.BlockStatement,
3111 options.async,
3112 options.returnType,
3113 options.typeParameters
3114 ));
3115 }
3116
3117
3118 function parsePropertyMethodFunction(options) {
3119 var previousStrict, tmp, method;
3120
3121 previousStrict = strict;
3122 strict = true;
3123
3124 tmp = parseParams();
3125
3126 if (tmp.stricted) {
3127 throwErrorTolerant(tmp.stricted, tmp.message);
3128 }
3129
3130 method = parsePropertyFunction({
3131 params: tmp.params,
3132 defaults: tmp.defaults,
3133 rest: tmp.rest,
3134 generator: options.generator,
3135 async: options.async,
3136 returnType: tmp.returnType,
3137 typeParameters: options.typeParameters
3138 });
3139
3140 strict = previousStrict;
3141
3142 return method;
3143 }
3144
3145
3146 function parseObjectPropertyKey() {
3147 var marker = markerCreate(),
3148 token = lex(),
3149 propertyKey,
3150 result;
3151
3152 // Note: This function is called only from parseObjectProperty(), where
3153 // EOF and Punctuator tokens are already filtered out.
3154
3155 if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
3156 if (strict && token.octal) {
3157 throwErrorTolerant(token, Messages.StrictOctalLiteral);
3158 }
3159 return markerApply(marker, delegate.createLiteral(token));
3160 }
3161
3162 if (token.type === Token.Punctuator && token.value === '[') {
3163 // For computed properties we should skip the [ and ], and
3164 // capture in marker only the assignment expression itself.
3165 marker = markerCreate();
3166 propertyKey = parseAssignmentExpression();
3167 result = markerApply(marker, propertyKey);
3168 expect(']');
3169 return result;
3170 }
3171
3172 return markerApply(marker, delegate.createIdentifier(token.value));
3173 }
3174
3175 function parseObjectProperty() {
3176 var token, key, id, param, computed,
3177 marker = markerCreate(), returnType, typeParameters;
3178
3179 token = lookahead;
3180 computed = (token.value === '[' && token.type === Token.Punctuator);
3181
3182 if (token.type === Token.Identifier || computed || matchAsync()) {
3183 id = parseObjectPropertyKey();
3184
3185 if (match(':')) {
3186 lex();
3187
3188 return markerApply(
3189 marker,
3190 delegate.createProperty(
3191 'init',
3192 id,
3193 parseAssignmentExpression(),
3194 false,
3195 false,
3196 computed
3197 )
3198 );
3199 }
3200
3201 if (match('(') || match('<')) {
3202 if (match('<')) {
3203 typeParameters = parseTypeParameterDeclaration();
3204 }
3205 return markerApply(
3206 marker,
3207 delegate.createProperty(
3208 'init',
3209 id,
3210 parsePropertyMethodFunction({
3211 generator: false,
3212 async: false,
3213 typeParameters: typeParameters
3214 }),
3215 true,
3216 false,
3217 computed
3218 )
3219 );
3220 }
3221
3222 // Property Assignment: Getter and Setter.
3223
3224 if (token.value === 'get') {
3225 computed = (lookahead.value === '[');
3226 key = parseObjectPropertyKey();
3227
3228 expect('(');
3229 expect(')');
3230 if (match(':')) {
3231 returnType = parseTypeAnnotation();
3232 }
3233
3234 return markerApply(
3235 marker,
3236 delegate.createProperty(
3237 'get',
3238 key,
3239 parsePropertyFunction({
3240 generator: false,
3241 async: false,
3242 returnType: returnType
3243 }),
3244 false,
3245 false,
3246 computed
3247 )
3248 );
3249 }
3250
3251 if (token.value === 'set') {
3252 computed = (lookahead.value === '[');
3253 key = parseObjectPropertyKey();
3254
3255 expect('(');
3256 token = lookahead;
3257 param = [ parseTypeAnnotatableIdentifier() ];
3258 expect(')');
3259 if (match(':')) {
3260 returnType = parseTypeAnnotation();
3261 }
3262
3263 return markerApply(
3264 marker,
3265 delegate.createProperty(
3266 'set',
3267 key,
3268 parsePropertyFunction({
3269 params: param,
3270 generator: false,
3271 async: false,
3272 name: token,
3273 returnType: returnType
3274 }),
3275 false,
3276 false,
3277 computed
3278 )
3279 );
3280 }
3281
3282 if (token.value === 'async') {
3283 computed = (lookahead.value === '[');
3284 key = parseObjectPropertyKey();
3285
3286 if (match('<')) {
3287 typeParameters = parseTypeParameterDeclaration();
3288 }
3289
3290 return markerApply(
3291 marker,
3292 delegate.createProperty(
3293 'init',
3294 key,
3295 parsePropertyMethodFunction({
3296 generator: false,
3297 async: true,
3298 typeParameters: typeParameters
3299 }),
3300 true,
3301 false,
3302 computed
3303 )
3304 );
3305 }
3306
3307 if (computed) {
3308 // Computed properties can only be used with full notation.
3309 throwUnexpected(lookahead);
3310 }
3311
3312 return markerApply(
3313 marker,
3314 delegate.createProperty('init', id, id, false, true, false)
3315 );
3316 }
3317
3318 if (token.type === Token.EOF || token.type === Token.Punctuator) {
3319 if (!match('*')) {
3320 throwUnexpected(token);
3321 }
3322 lex();
3323
3324 computed = (lookahead.type === Token.Punctuator && lookahead.value === '[');
3325
3326 id = parseObjectPropertyKey();
3327
3328 if (match('<')) {
3329 typeParameters = parseTypeParameterDeclaration();
3330 }
3331
3332 if (!match('(')) {
3333 throwUnexpected(lex());
3334 }
3335
3336 return markerApply(marker, delegate.createProperty(
3337 'init',
3338 id,
3339 parsePropertyMethodFunction({
3340 generator: true,
3341 typeParameters: typeParameters
3342 }),
3343 true,
3344 false,
3345 computed
3346 ));
3347 }
3348 key = parseObjectPropertyKey();
3349 if (match(':')) {
3350 lex();
3351 return markerApply(marker, delegate.createProperty('init', key, parseAssignmentExpression(), false, false, false));
3352 }
3353 if (match('(') || match('<')) {
3354 if (match('<')) {
3355 typeParameters = parseTypeParameterDeclaration();
3356 }
3357 return markerApply(marker, delegate.createProperty(
3358 'init',
3359 key,
3360 parsePropertyMethodFunction({
3361 generator: false,
3362 typeParameters: typeParameters
3363 }),
3364 true,
3365 false,
3366 false
3367 ));
3368 }
3369 throwUnexpected(lex());
3370 }
3371
3372 function parseObjectSpreadProperty() {
3373 var marker = markerCreate();
3374 expect('...');
3375 return markerApply(marker, delegate.createSpreadProperty(parseAssignmentExpression()));
3376 }
3377
3378 function getFieldName(key) {
3379 var toString = String;
3380 if (key.type === Syntax.Identifier) {
3381 return key.name;
3382 }
3383 return toString(key.value);
3384 }
3385
3386 function parseObjectInitialiser() {
3387 var properties = [], property, name, kind, storedKind, map = new StringMap(),
3388 marker = markerCreate(), toString = String;
3389
3390 expect('{');
3391
3392 while (!match('}')) {
3393 if (match('...')) {
3394 property = parseObjectSpreadProperty();
3395 } else {
3396 property = parseObjectProperty();
3397
3398 if (property.key.type === Syntax.Identifier) {
3399 name = property.key.name;
3400 } else {
3401 name = toString(property.key.value);
3402 }
3403 kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
3404
3405 if (map.has(name)) {
3406 storedKind = map.get(name);
3407 if (storedKind === PropertyKind.Data) {
3408 if (strict && kind === PropertyKind.Data) {
3409 throwErrorTolerant({}, Messages.StrictDuplicateProperty);
3410 } else if (kind !== PropertyKind.Data) {
3411 throwErrorTolerant({}, Messages.AccessorDataProperty);
3412 }
3413 } else {
3414 if (kind === PropertyKind.Data) {
3415 throwErrorTolerant({}, Messages.AccessorDataProperty);
3416 } else if (storedKind & kind) {
3417 throwErrorTolerant({}, Messages.AccessorGetSet);
3418 }
3419 }
3420 map.set(name, storedKind | kind);
3421 } else {
3422 map.set(name, kind);
3423 }
3424 }
3425
3426 properties.push(property);
3427
3428 if (!match('}')) {
3429 expect(',');
3430 }
3431 }
3432
3433 expect('}');
3434
3435 return markerApply(marker, delegate.createObjectExpression(properties));
3436 }
3437
3438 function parseTemplateElement(option) {
3439 var marker, token;
3440
3441 if (lookahead.type !== Token.Template || (option.head && !lookahead.head)) {
3442 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
3443 }
3444
3445 marker = markerCreate();
3446 token = lex();
3447
3448 if (strict && token.octal) {
3449 throwError(token, Messages.StrictOctalLiteral);
3450 }
3451 return markerApply(marker, delegate.createTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail));
3452 }
3453
3454 function parseTemplateLiteral() {
3455 var quasi, quasis, expressions, marker = markerCreate();
3456
3457 quasi = parseTemplateElement({ head: true });
3458 quasis = [ quasi ];
3459 expressions = [];
3460
3461 while (!quasi.tail) {
3462 expressions.push(parseExpression());
3463 quasi = parseTemplateElement({ head: false });
3464 quasis.push(quasi);
3465 }
3466
3467 return markerApply(marker, delegate.createTemplateLiteral(quasis, expressions));
3468 }
3469
3470 // 11.1.6 The Grouping Operator
3471
3472 function parseGroupExpression() {
3473 var expr, marker, typeAnnotation;
3474
3475 expect('(');
3476
3477 ++state.parenthesizedCount;
3478
3479 marker = markerCreate();
3480
3481 expr = parseExpression();
3482
3483 if (match(':')) {
3484 typeAnnotation = parseTypeAnnotation();
3485 expr = markerApply(marker, delegate.createTypeCast(
3486 expr,
3487 typeAnnotation
3488 ));
3489 }
3490
3491 expect(')');
3492
3493 return expr;
3494 }
3495
3496 function matchAsyncFuncExprOrDecl() {
3497 var token;
3498
3499 if (matchAsync()) {
3500 token = lookahead2();
3501 if (token.type === Token.Keyword && token.value === 'function') {
3502 return true;
3503 }
3504 }
3505
3506 return false;
3507 }
3508
3509 // 11.1 Primary Expressions
3510
3511 function parsePrimaryExpression() {
3512 var marker, type, token, expr;
3513
3514 type = lookahead.type;
3515
3516 if (type === Token.Identifier) {
3517 marker = markerCreate();
3518 return markerApply(marker, delegate.createIdentifier(lex().value));
3519 }
3520
3521 if (type === Token.StringLiteral || type === Token.NumericLiteral) {
3522 if (strict && lookahead.octal) {
3523 throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
3524 }
3525 marker = markerCreate();
3526 return markerApply(marker, delegate.createLiteral(lex()));
3527 }
3528
3529 if (type === Token.Keyword) {
3530 if (matchKeyword('this')) {
3531 marker = markerCreate();
3532 lex();
3533 return markerApply(marker, delegate.createThisExpression());
3534 }
3535
3536 if (matchKeyword('function')) {
3537 return parseFunctionExpression();
3538 }
3539
3540 if (matchKeyword('class')) {
3541 return parseClassExpression();
3542 }
3543
3544 if (matchKeyword('super')) {
3545 marker = markerCreate();
3546 lex();
3547 return markerApply(marker, delegate.createIdentifier('super'));
3548 }
3549 }
3550
3551 if (type === Token.BooleanLiteral) {
3552 marker = markerCreate();
3553 token = lex();
3554 token.value = (token.value === 'true');
3555 return markerApply(marker, delegate.createLiteral(token));
3556 }
3557
3558 if (type === Token.NullLiteral) {
3559 marker = markerCreate();
3560 token = lex();
3561 token.value = null;
3562 return markerApply(marker, delegate.createLiteral(token));
3563 }
3564
3565 if (match('[')) {
3566 return parseArrayInitialiser();
3567 }
3568
3569 if (match('{')) {
3570 return parseObjectInitialiser();
3571 }
3572
3573 if (match('(')) {
3574 return parseGroupExpression();
3575 }
3576
3577 if (match('/') || match('/=')) {
3578 marker = markerCreate();
3579 expr = delegate.createLiteral(scanRegExp());
3580 peek();
3581 return markerApply(marker, expr);
3582 }
3583
3584 if (type === Token.Template) {
3585 return parseTemplateLiteral();
3586 }
3587
3588 if (match('<')) {
3589 return parseJSXElement();
3590 }
3591
3592 throwUnexpected(lex());
3593 }
3594
3595 // 11.2 Left-Hand-Side Expressions
3596
3597 function parseArguments() {
3598 var args = [], arg;
3599
3600 expect('(');
3601
3602 if (!match(')')) {
3603 while (index < length) {
3604 arg = parseSpreadOrAssignmentExpression();
3605 args.push(arg);
3606
3607 if (arg.type === Syntax.SpreadElement) {
3608 if (match(')')) {
3609 break;
3610 } else {
3611 throwError({}, Messages.ElementAfterSpreadElement);
3612 }
3613 }
3614
3615 if (match(')')) {
3616 break;
3617 } else {
3618 expect(',');
3619 if (match(')')) {
3620 break;
3621 }
3622 }
3623 }
3624 }
3625
3626 expect(')');
3627
3628 return args;
3629 }
3630
3631 function parseSpreadOrAssignmentExpression() {
3632 if (match('...')) {
3633 var marker = markerCreate();
3634 lex();
3635 return markerApply(marker, delegate.createSpreadElement(parseAssignmentExpression()));
3636 }
3637 return parseAssignmentExpression();
3638 }
3639
3640 function parseNonComputedProperty() {
3641 var marker = markerCreate(),
3642 token = lex();
3643
3644 if (!isIdentifierName(token)) {
3645 throwUnexpected(token);
3646 }
3647
3648 return markerApply(marker, delegate.createIdentifier(token.value));
3649 }
3650
3651 function parseNonComputedMember() {
3652 expect('.');
3653
3654 return parseNonComputedProperty();
3655 }
3656
3657 function parseComputedMember() {
3658 var expr;
3659
3660 expect('[');
3661
3662 expr = parseExpression();
3663
3664 expect(']');
3665
3666 return expr;
3667 }
3668
3669 function parseNewExpression() {
3670 var callee, args, marker = markerCreate();
3671
3672 expectKeyword('new');
3673 callee = parseLeftHandSideExpression();
3674 args = match('(') ? parseArguments() : [];
3675
3676 return markerApply(marker, delegate.createNewExpression(callee, args));
3677 }
3678
3679 function parseLeftHandSideExpressionAllowCall() {
3680 var expr, args, marker = markerCreate();
3681
3682 expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
3683
3684 while (match('.') || match('[') || match('(') || (lookahead.type === Token.Template && lookahead.head)) {
3685 if (match('(')) {
3686 args = parseArguments();
3687 expr = markerApply(marker, delegate.createCallExpression(expr, args));
3688 } else if (match('[')) {
3689 expr = markerApply(marker, delegate.createMemberExpression('[', expr, parseComputedMember()));
3690 } else if (match('.')) {
3691 expr = markerApply(marker, delegate.createMemberExpression('.', expr, parseNonComputedMember()));
3692 } else {
3693 expr = markerApply(marker, delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()));
3694 }
3695 }
3696
3697 return expr;
3698 }
3699
3700 function parseLeftHandSideExpression() {
3701 var expr, marker = markerCreate();
3702
3703 expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
3704
3705 while (match('.') || match('[') || (lookahead.type === Token.Template && lookahead.head)) {
3706 if (match('[')) {
3707 expr = markerApply(marker, delegate.createMemberExpression('[', expr, parseComputedMember()));
3708 } else if (match('.')) {
3709 expr = markerApply(marker, delegate.createMemberExpression('.', expr, parseNonComputedMember()));
3710 } else {
3711 expr = markerApply(marker, delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()));
3712 }
3713 }
3714
3715 return expr;
3716 }
3717
3718 // 11.3 Postfix Expressions
3719
3720 function parsePostfixExpression() {
3721 var marker = markerCreate(),
3722 expr = parseLeftHandSideExpressionAllowCall(),
3723 token;
3724
3725 if (lookahead.type !== Token.Punctuator) {
3726 return expr;
3727 }
3728
3729 if ((match('++') || match('--')) && !peekLineTerminator()) {
3730 // 11.3.1, 11.3.2
3731 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
3732 throwErrorTolerant({}, Messages.StrictLHSPostfix);
3733 }
3734
3735 if (!isLeftHandSide(expr)) {
3736 throwError({}, Messages.InvalidLHSInAssignment);
3737 }
3738
3739 token = lex();
3740 expr = markerApply(marker, delegate.createPostfixExpression(token.value, expr));
3741 }
3742
3743 return expr;
3744 }
3745
3746 // 11.4 Unary Operators
3747
3748 function parseUnaryExpression() {
3749 var marker, token, expr;
3750
3751 if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) {
3752 return parsePostfixExpression();
3753 }
3754
3755 if (match('++') || match('--')) {
3756 marker = markerCreate();
3757 token = lex();
3758 expr = parseUnaryExpression();
3759 // 11.4.4, 11.4.5
3760 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
3761 throwErrorTolerant({}, Messages.StrictLHSPrefix);
3762 }
3763
3764 if (!isLeftHandSide(expr)) {
3765 throwError({}, Messages.InvalidLHSInAssignment);
3766 }
3767
3768 return markerApply(marker, delegate.createUnaryExpression(token.value, expr));
3769 }
3770
3771 if (match('+') || match('-') || match('~') || match('!')) {
3772 marker = markerCreate();
3773 token = lex();
3774 expr = parseUnaryExpression();
3775 return markerApply(marker, delegate.createUnaryExpression(token.value, expr));
3776 }
3777
3778 if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
3779 marker = markerCreate();
3780 token = lex();
3781 expr = parseUnaryExpression();
3782 expr = markerApply(marker, delegate.createUnaryExpression(token.value, expr));
3783 if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) {
3784 throwErrorTolerant({}, Messages.StrictDelete);
3785 }
3786 return expr;
3787 }
3788
3789 return parsePostfixExpression();
3790 }
3791
3792 function binaryPrecedence(token, allowIn) {
3793 var prec = 0;
3794
3795 if (token.type !== Token.Punctuator && token.type !== Token.Keyword) {
3796 return 0;
3797 }
3798
3799 switch (token.value) {
3800 case '||':
3801 prec = 1;
3802 break;
3803
3804 case '&&':
3805 prec = 2;
3806 break;
3807
3808 case '|':
3809 prec = 3;
3810 break;
3811
3812 case '^':
3813 prec = 4;
3814 break;
3815
3816 case '&':
3817 prec = 5;
3818 break;
3819
3820 case '==':
3821 case '!=':
3822 case '===':
3823 case '!==':
3824 prec = 6;
3825 break;
3826
3827 case '<':
3828 case '>':
3829 case '<=':
3830 case '>=':
3831 case 'instanceof':
3832 prec = 7;
3833 break;
3834
3835 case 'in':
3836 prec = allowIn ? 7 : 0;
3837 break;
3838
3839 case '<<':
3840 case '>>':
3841 case '>>>':
3842 prec = 8;
3843 break;
3844
3845 case '+':
3846 case '-':
3847 prec = 9;
3848 break;
3849
3850 case '*':
3851 case '/':
3852 case '%':
3853 prec = 11;
3854 break;
3855
3856 default:
3857 break;
3858 }
3859
3860 return prec;
3861 }
3862
3863 // 11.5 Multiplicative Operators
3864 // 11.6 Additive Operators
3865 // 11.7 Bitwise Shift Operators
3866 // 11.8 Relational Operators
3867 // 11.9 Equality Operators
3868 // 11.10 Binary Bitwise Operators
3869 // 11.11 Binary Logical Operators
3870
3871 function parseBinaryExpression() {
3872 var expr, token, prec, previousAllowIn, stack, right, operator, left, i,
3873 marker, markers;
3874
3875 previousAllowIn = state.allowIn;
3876 state.allowIn = true;
3877
3878 marker = markerCreate();
3879 left = parseUnaryExpression();
3880
3881 token = lookahead;
3882 prec = binaryPrecedence(token, previousAllowIn);
3883 if (prec === 0) {
3884 return left;
3885 }
3886 token.prec = prec;
3887 lex();
3888
3889 markers = [marker, markerCreate()];
3890 right = parseUnaryExpression();
3891
3892 stack = [left, token, right];
3893
3894 while ((prec = binaryPrecedence(lookahead, previousAllowIn)) > 0) {
3895
3896 // Reduce: make a binary expression from the three topmost entries.
3897 while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
3898 right = stack.pop();
3899 operator = stack.pop().value;
3900 left = stack.pop();
3901 expr = delegate.createBinaryExpression(operator, left, right);
3902 markers.pop();
3903 marker = markers.pop();
3904 markerApply(marker, expr);
3905 stack.push(expr);
3906 markers.push(marker);
3907 }
3908
3909 // Shift.
3910 token = lex();
3911 token.prec = prec;
3912 stack.push(token);
3913 markers.push(markerCreate());
3914 expr = parseUnaryExpression();
3915 stack.push(expr);
3916 }
3917
3918 state.allowIn = previousAllowIn;
3919
3920 // Final reduce to clean-up the stack.
3921 i = stack.length - 1;
3922 expr = stack[i];
3923 markers.pop();
3924 while (i > 1) {
3925 expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
3926 i -= 2;
3927 marker = markers.pop();
3928 markerApply(marker, expr);
3929 }
3930
3931 return expr;
3932 }
3933
3934
3935 // 11.12 Conditional Operator
3936
3937 function parseConditionalExpression() {
3938 var expr, previousAllowIn, consequent, alternate, marker = markerCreate();
3939 expr = parseBinaryExpression();
3940
3941 if (match('?')) {
3942 lex();
3943 previousAllowIn = state.allowIn;
3944 state.allowIn = true;
3945 consequent = parseAssignmentExpression();
3946 state.allowIn = previousAllowIn;
3947 expect(':');
3948 alternate = parseAssignmentExpression();
3949
3950 expr = markerApply(marker, delegate.createConditionalExpression(expr, consequent, alternate));
3951 }
3952
3953 return expr;
3954 }
3955
3956 // 11.13 Assignment Operators
3957
3958 // 12.14.5 AssignmentPattern
3959
3960 function reinterpretAsAssignmentBindingPattern(expr) {
3961 var i, len, property, element;
3962
3963 if (expr.type === Syntax.ObjectExpression) {
3964 expr.type = Syntax.ObjectPattern;
3965 for (i = 0, len = expr.properties.length; i < len; i += 1) {
3966 property = expr.properties[i];
3967 if (property.type === Syntax.SpreadProperty) {
3968 if (i < len - 1) {
3969 throwError({}, Messages.PropertyAfterSpreadProperty);
3970 }
3971 reinterpretAsAssignmentBindingPattern(property.argument);
3972 } else {
3973 if (property.kind !== 'init') {
3974 throwError({}, Messages.InvalidLHSInAssignment);
3975 }
3976 reinterpretAsAssignmentBindingPattern(property.value);
3977 }
3978 }
3979 } else if (expr.type === Syntax.ArrayExpression) {
3980 expr.type = Syntax.ArrayPattern;
3981 for (i = 0, len = expr.elements.length; i < len; i += 1) {
3982 element = expr.elements[i];
3983 /* istanbul ignore else */
3984 if (element) {
3985 reinterpretAsAssignmentBindingPattern(element);
3986 }
3987 }
3988 } else if (expr.type === Syntax.Identifier) {
3989 if (isRestrictedWord(expr.name)) {
3990 throwError({}, Messages.InvalidLHSInAssignment);
3991 }
3992 } else if (expr.type === Syntax.SpreadElement) {
3993 reinterpretAsAssignmentBindingPattern(expr.argument);
3994 if (expr.argument.type === Syntax.ObjectPattern) {
3995 throwError({}, Messages.ObjectPatternAsSpread);
3996 }
3997 } else {
3998 /* istanbul ignore else */
3999 if (expr.type !== Syntax.MemberExpression && expr.type !== Syntax.CallExpression && expr.type !== Syntax.NewExpression) {
4000 throwError({}, Messages.InvalidLHSInAssignment);
4001 }
4002 }
4003 }
4004
4005 // 13.2.3 BindingPattern
4006
4007 function reinterpretAsDestructuredParameter(options, expr) {
4008 var i, len, property, element;
4009
4010 if (expr.type === Syntax.ObjectExpression) {
4011 expr.type = Syntax.ObjectPattern;
4012 for (i = 0, len = expr.properties.length; i < len; i += 1) {
4013 property = expr.properties[i];
4014 if (property.type === Syntax.SpreadProperty) {
4015 if (i < len - 1) {
4016 throwError({}, Messages.PropertyAfterSpreadProperty);
4017 }
4018 reinterpretAsDestructuredParameter(options, property.argument);
4019 } else {
4020 if (property.kind !== 'init') {
4021 throwError({}, Messages.InvalidLHSInFormalsList);
4022 }
4023 reinterpretAsDestructuredParameter(options, property.value);
4024 }
4025 }
4026 } else if (expr.type === Syntax.ArrayExpression) {
4027 expr.type = Syntax.ArrayPattern;
4028 for (i = 0, len = expr.elements.length; i < len; i += 1) {
4029 element = expr.elements[i];
4030 if (element) {
4031 reinterpretAsDestructuredParameter(options, element);
4032 }
4033 }
4034 } else if (expr.type === Syntax.Identifier) {
4035 validateParam(options, expr, expr.name);
4036 } else if (expr.type === Syntax.SpreadElement) {
4037 // BindingRestElement only allows BindingIdentifier
4038 if (expr.argument.type !== Syntax.Identifier) {
4039 throwError({}, Messages.InvalidLHSInFormalsList);
4040 }
4041 validateParam(options, expr.argument, expr.argument.name);
4042 } else {
4043 throwError({}, Messages.InvalidLHSInFormalsList);
4044 }
4045 }
4046
4047 function reinterpretAsCoverFormalsList(expressions) {
4048 var i, len, param, params, defaults, defaultCount, options, rest;
4049
4050 params = [];
4051 defaults = [];
4052 defaultCount = 0;
4053 rest = null;
4054 options = {
4055 paramSet: new StringMap()
4056 };
4057
4058 for (i = 0, len = expressions.length; i < len; i += 1) {
4059 param = expressions[i];
4060 if (param.type === Syntax.Identifier) {
4061 params.push(param);
4062 defaults.push(null);
4063 validateParam(options, param, param.name);
4064 } else if (param.type === Syntax.ObjectExpression || param.type === Syntax.ArrayExpression) {
4065 reinterpretAsDestructuredParameter(options, param);
4066 params.push(param);
4067 defaults.push(null);
4068 } else if (param.type === Syntax.SpreadElement) {
4069 assert(i === len - 1, 'It is guaranteed that SpreadElement is last element by parseExpression');
4070 if (param.argument.type !== Syntax.Identifier) {
4071 throwError({}, Messages.InvalidLHSInFormalsList);
4072 }
4073 reinterpretAsDestructuredParameter(options, param.argument);
4074 rest = param.argument;
4075 } else if (param.type === Syntax.AssignmentExpression) {
4076 params.push(param.left);
4077 defaults.push(param.right);
4078 ++defaultCount;
4079 validateParam(options, param.left, param.left.name);
4080 } else {
4081 return null;
4082 }
4083 }
4084
4085 if (options.message === Messages.StrictParamDupe) {
4086 throwError(
4087 strict ? options.stricted : options.firstRestricted,
4088 options.message
4089 );
4090 }
4091
4092 if (defaultCount === 0) {
4093 defaults = [];
4094 }
4095
4096 return {
4097 params: params,
4098 defaults: defaults,
4099 rest: rest,
4100 stricted: options.stricted,
4101 firstRestricted: options.firstRestricted,
4102 message: options.message
4103 };
4104 }
4105
4106 function parseArrowFunctionExpression(options, marker) {
4107 var previousStrict, previousYieldAllowed, previousAwaitAllowed, body;
4108
4109 expect('=>');
4110
4111 previousStrict = strict;
4112 previousYieldAllowed = state.yieldAllowed;
4113 state.yieldAllowed = false;
4114 previousAwaitAllowed = state.awaitAllowed;
4115 state.awaitAllowed = !!options.async;
4116 body = parseConciseBody();
4117
4118 if (strict && options.firstRestricted) {
4119 throwError(options.firstRestricted, options.message);
4120 }
4121 if (strict && options.stricted) {
4122 throwErrorTolerant(options.stricted, options.message);
4123 }
4124
4125 strict = previousStrict;
4126 state.yieldAllowed = previousYieldAllowed;
4127 state.awaitAllowed = previousAwaitAllowed;
4128
4129 return markerApply(marker, delegate.createArrowFunctionExpression(
4130 options.params,
4131 options.defaults,
4132 body,
4133 options.rest,
4134 body.type !== Syntax.BlockStatement,
4135 !!options.async
4136 ));
4137 }
4138
4139 function parseAssignmentExpression() {
4140 var marker, expr, token, params, oldParenthesizedCount,
4141 startsWithParen = false, backtrackToken = lookahead,
4142 possiblyAsync = false;
4143
4144 if (matchYield()) {
4145 return parseYieldExpression();
4146 }
4147
4148 if (matchAwait()) {
4149 return parseAwaitExpression();
4150 }
4151
4152 oldParenthesizedCount = state.parenthesizedCount;
4153
4154 marker = markerCreate();
4155
4156 if (matchAsyncFuncExprOrDecl()) {
4157 return parseFunctionExpression();
4158 }
4159
4160 if (matchAsync()) {
4161 // We can't be completely sure that this 'async' token is
4162 // actually a contextual keyword modifying a function
4163 // expression, so we might have to un-lex() it later by
4164 // calling rewind(backtrackToken).
4165 possiblyAsync = true;
4166 lex();
4167 }
4168
4169 if (match('(')) {
4170 token = lookahead2();
4171 if ((token.type === Token.Punctuator && token.value === ')') || token.value === '...') {
4172 params = parseParams();
4173 if (!match('=>')) {
4174 throwUnexpected(lex());
4175 }
4176 params.async = possiblyAsync;
4177 return parseArrowFunctionExpression(params, marker);
4178 }
4179 startsWithParen = true;
4180 }
4181
4182 token = lookahead;
4183
4184 // If the 'async' keyword is not followed by a '(' character or an
4185 // identifier, then it can't be an arrow function modifier, and we
4186 // should interpret it as a normal identifer.
4187 if (possiblyAsync && !match('(') && token.type !== Token.Identifier) {
4188 possiblyAsync = false;
4189 rewind(backtrackToken);
4190 }
4191
4192 expr = parseConditionalExpression();
4193
4194 if (match('=>') &&
4195 (state.parenthesizedCount === oldParenthesizedCount ||
4196 state.parenthesizedCount === (oldParenthesizedCount + 1))) {
4197 if (expr.type === Syntax.Identifier) {
4198 params = reinterpretAsCoverFormalsList([ expr ]);
4199 } else if (expr.type === Syntax.AssignmentExpression ||
4200 expr.type === Syntax.ArrayExpression ||
4201 expr.type === Syntax.ObjectExpression) {
4202 if (!startsWithParen) {
4203 throwUnexpected(lex());
4204 }
4205 params = reinterpretAsCoverFormalsList([ expr ]);
4206 } else if (expr.type === Syntax.SequenceExpression) {
4207 params = reinterpretAsCoverFormalsList(expr.expressions);
4208 }
4209 if (params) {
4210 params.async = possiblyAsync;
4211 return parseArrowFunctionExpression(params, marker);
4212 }
4213 }
4214
4215 // If we haven't returned by now, then the 'async' keyword was not
4216 // a function modifier, and we should rewind and interpret it as a
4217 // normal identifier.
4218 if (possiblyAsync) {
4219 possiblyAsync = false;
4220 rewind(backtrackToken);
4221 expr = parseConditionalExpression();
4222 }
4223
4224 if (matchAssign()) {
4225 // 11.13.1
4226 if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
4227 throwErrorTolerant(token, Messages.StrictLHSAssignment);
4228 }
4229
4230 // ES.next draf 11.13 Runtime Semantics step 1
4231 if (match('=') && (expr.type === Syntax.ObjectExpression || expr.type === Syntax.ArrayExpression)) {
4232 reinterpretAsAssignmentBindingPattern(expr);
4233 } else if (!isLeftHandSide(expr)) {
4234 throwError({}, Messages.InvalidLHSInAssignment);
4235 }
4236
4237 expr = markerApply(marker, delegate.createAssignmentExpression(lex().value, expr, parseAssignmentExpression()));
4238 }
4239
4240 return expr;
4241 }
4242
4243 // 11.14 Comma Operator
4244
4245 function parseExpression() {
4246 var marker, expr, expressions, sequence, spreadFound, possibleArrow;
4247
4248 marker = markerCreate();
4249 expr = parseAssignmentExpression();
4250 expressions = [ expr ];
4251
4252 if (match(',')) {
4253 while (index < length) {
4254 if (!match(',')) {
4255 break;
4256 }
4257
4258 lex();
4259
4260 if (match(')')) {
4261 possibleArrow = lookahead2();
4262 if (
4263 possibleArrow.type === Token.Punctuator &&
4264 possibleArrow.value === '=>'
4265 ) {
4266 break;
4267 }
4268 }
4269
4270 expr = parseSpreadOrAssignmentExpression();
4271 expressions.push(expr);
4272
4273 if (expr.type === Syntax.SpreadElement) {
4274 spreadFound = true;
4275 if (!match(')')) {
4276 throwError({}, Messages.ElementAfterSpreadElement);
4277 }
4278 break;
4279 }
4280 }
4281
4282 if (expressions.length > 1) {
4283 sequence = markerApply(marker, delegate.createSequenceExpression(expressions));
4284 }
4285 }
4286
4287 if (spreadFound && lookahead2().value !== '=>') {
4288 throwError({}, Messages.IllegalSpread);
4289 }
4290
4291 return sequence || expr;
4292 }
4293
4294 // 12.1 Block
4295
4296 function parseStatementList() {
4297 var list = [],
4298 statement;
4299
4300 while (index < length) {
4301 if (match('}')) {
4302 break;
4303 }
4304 statement = parseSourceElement();
4305 if (typeof statement === 'undefined') {
4306 break;
4307 }
4308 list.push(statement);
4309 }
4310
4311 return list;
4312 }
4313
4314 function parseBlock() {
4315 var block, marker = markerCreate();
4316
4317 expect('{');
4318
4319 block = parseStatementList();
4320
4321 expect('}');
4322
4323 return markerApply(marker, delegate.createBlockStatement(block));
4324 }
4325
4326 // 12.2 Variable Statement
4327
4328 function parseTypeParameterDeclaration() {
4329 var marker = markerCreate(), paramTypes = [];
4330
4331 expect('<');
4332 while (!match('>')) {
4333 paramTypes.push(parseTypeAnnotatableIdentifier());
4334 if (!match('>')) {
4335 expect(',');
4336 }
4337 }
4338 expect('>');
4339
4340 return markerApply(marker, delegate.createTypeParameterDeclaration(
4341 paramTypes
4342 ));
4343 }
4344
4345 function parseTypeParameterInstantiation() {
4346 var marker = markerCreate(), oldInType = state.inType, paramTypes = [];
4347
4348 state.inType = true;
4349
4350 expect('<');
4351 while (!match('>')) {
4352 paramTypes.push(parseType());
4353 if (!match('>')) {
4354 expect(',');
4355 }
4356 }
4357 expect('>');
4358
4359 state.inType = oldInType;
4360
4361 return markerApply(marker, delegate.createTypeParameterInstantiation(
4362 paramTypes
4363 ));
4364 }
4365
4366 function parseObjectTypeIndexer(marker, isStatic) {
4367 var id, key, value;
4368
4369 expect('[');
4370 id = parseObjectPropertyKey();
4371 expect(':');
4372 key = parseType();
4373 expect(']');
4374 expect(':');
4375 value = parseType();
4376
4377 return markerApply(marker, delegate.createObjectTypeIndexer(
4378 id,
4379 key,
4380 value,
4381 isStatic
4382 ));
4383 }
4384
4385 function parseObjectTypeMethodish(marker) {
4386 var params = [], rest = null, returnType, typeParameters = null;
4387 if (match('<')) {
4388 typeParameters = parseTypeParameterDeclaration();
4389 }
4390
4391 expect('(');
4392 while (lookahead.type === Token.Identifier) {
4393 params.push(parseFunctionTypeParam());
4394 if (!match(')')) {
4395 expect(',');
4396 }
4397 }
4398
4399 if (match('...')) {
4400 lex();
4401 rest = parseFunctionTypeParam();
4402 }
4403 expect(')');
4404 expect(':');
4405 returnType = parseType();
4406
4407 return markerApply(marker, delegate.createFunctionTypeAnnotation(
4408 params,
4409 returnType,
4410 rest,
4411 typeParameters
4412 ));
4413 }
4414
4415 function parseObjectTypeMethod(marker, isStatic, key) {
4416 var optional = false, value;
4417 value = parseObjectTypeMethodish(marker);
4418
4419 return markerApply(marker, delegate.createObjectTypeProperty(
4420 key,
4421 value,
4422 optional,
4423 isStatic
4424 ));
4425 }
4426
4427 function parseObjectTypeCallProperty(marker, isStatic) {
4428 var valueMarker = markerCreate();
4429 return markerApply(marker, delegate.createObjectTypeCallProperty(
4430 parseObjectTypeMethodish(valueMarker),
4431 isStatic
4432 ));
4433 }
4434
4435 function parseObjectType(allowStatic) {
4436 var callProperties = [], indexers = [], marker, optional = false,
4437 properties = [], propertyKey, propertyTypeAnnotation,
4438 token, isStatic, matchStatic;
4439
4440 expect('{');
4441
4442 while (!match('}')) {
4443 marker = markerCreate();
4444 matchStatic =
4445 strict
4446 ? matchKeyword('static')
4447 : matchContextualKeyword('static');
4448
4449 if (allowStatic && matchStatic) {
4450 token = lex();
4451 isStatic = true;
4452 }
4453
4454 if (match('[')) {
4455 indexers.push(parseObjectTypeIndexer(marker, isStatic));
4456 } else if (match('(') || match('<')) {
4457 callProperties.push(parseObjectTypeCallProperty(marker, allowStatic));
4458 } else {
4459 if (isStatic && match(':')) {
4460 propertyKey = markerApply(marker, delegate.createIdentifier(token));
4461 throwErrorTolerant(token, Messages.StrictReservedWord);
4462 } else {
4463 propertyKey = parseObjectPropertyKey();
4464 }
4465 if (match('<') || match('(')) {
4466 // This is a method property
4467 properties.push(parseObjectTypeMethod(marker, isStatic, propertyKey));
4468 } else {
4469 if (match('?')) {
4470 lex();
4471 optional = true;
4472 }
4473 expect(':');
4474 propertyTypeAnnotation = parseType();
4475 properties.push(markerApply(marker, delegate.createObjectTypeProperty(
4476 propertyKey,
4477 propertyTypeAnnotation,
4478 optional,
4479 isStatic
4480 )));
4481 }
4482 }
4483
4484 if (match(';') || match(',')) {
4485 lex();
4486 } else if (!match('}')) {
4487 throwUnexpected(lookahead);
4488 }
4489 }
4490
4491 expect('}');
4492
4493 return delegate.createObjectTypeAnnotation(
4494 properties,
4495 indexers,
4496 callProperties
4497 );
4498 }
4499
4500 function parseGenericType() {
4501 var marker = markerCreate(),
4502 typeParameters = null, typeIdentifier;
4503
4504 typeIdentifier = parseVariableIdentifier();
4505
4506 while (match('.')) {
4507 expect('.');
4508 typeIdentifier = markerApply(marker, delegate.createQualifiedTypeIdentifier(
4509 typeIdentifier,
4510 parseVariableIdentifier()
4511 ));
4512 }
4513
4514 if (match('<')) {
4515 typeParameters = parseTypeParameterInstantiation();
4516 }
4517
4518 return markerApply(marker, delegate.createGenericTypeAnnotation(
4519 typeIdentifier,
4520 typeParameters
4521 ));
4522 }
4523
4524 function parseVoidType() {
4525 var marker = markerCreate();
4526 expectKeyword('void');
4527 return markerApply(marker, delegate.createVoidTypeAnnotation());
4528 }
4529
4530 function parseTypeofType() {
4531 var argument, marker = markerCreate();
4532 expectKeyword('typeof');
4533 argument = parsePrimaryType();
4534 return markerApply(marker, delegate.createTypeofTypeAnnotation(
4535 argument
4536 ));
4537 }
4538
4539 function parseTupleType() {
4540 var marker = markerCreate(), types = [];
4541 expect('[');
4542 // We allow trailing commas
4543 while (index < length && !match(']')) {
4544 types.push(parseType());
4545 if (match(']')) {
4546 break;
4547 }
4548 expect(',');
4549 }
4550 expect(']');
4551 return markerApply(marker, delegate.createTupleTypeAnnotation(
4552 types
4553 ));
4554 }
4555
4556 function parseFunctionTypeParam() {
4557 var marker = markerCreate(), name, optional = false, typeAnnotation;
4558 name = parseVariableIdentifier();
4559 if (match('?')) {
4560 lex();
4561 optional = true;
4562 }
4563 expect(':');
4564 typeAnnotation = parseType();
4565 return markerApply(marker, delegate.createFunctionTypeParam(
4566 name,
4567 typeAnnotation,
4568 optional
4569 ));
4570 }
4571
4572 function parseFunctionTypeParams() {
4573 var ret = { params: [], rest: null };
4574 while (lookahead.type === Token.Identifier) {
4575 ret.params.push(parseFunctionTypeParam());
4576 if (!match(')')) {
4577 expect(',');
4578 }
4579 }
4580
4581 if (match('...')) {
4582 lex();
4583 ret.rest = parseFunctionTypeParam();
4584 }
4585 return ret;
4586 }
4587
4588 // The parsing of types roughly parallels the parsing of expressions, and
4589 // primary types are kind of like primary expressions...they're the
4590 // primitives with which other types are constructed.
4591 function parsePrimaryType() {
4592 var params = null, returnType = null,
4593 marker = markerCreate(), rest = null, tmp,
4594 typeParameters, token, type, isGroupedType = false;
4595
4596 switch (lookahead.type) {
4597 case Token.Identifier:
4598 switch (lookahead.value) {
4599 case 'any':
4600 lex();
4601 return markerApply(marker, delegate.createAnyTypeAnnotation());
4602 case 'bool': // fallthrough
4603 case 'boolean':
4604 lex();
4605 return markerApply(marker, delegate.createBooleanTypeAnnotation());
4606 case 'number':
4607 lex();
4608 return markerApply(marker, delegate.createNumberTypeAnnotation());
4609 case 'string':
4610 lex();
4611 return markerApply(marker, delegate.createStringTypeAnnotation());
4612 }
4613 return markerApply(marker, parseGenericType());
4614 case Token.Punctuator:
4615 switch (lookahead.value) {
4616 case '{':
4617 return markerApply(marker, parseObjectType());
4618 case '[':
4619 return parseTupleType();
4620 case '<':
4621 typeParameters = parseTypeParameterDeclaration();
4622 expect('(');
4623 tmp = parseFunctionTypeParams();
4624 params = tmp.params;
4625 rest = tmp.rest;
4626 expect(')');
4627
4628 expect('=>');
4629
4630 returnType = parseType();
4631
4632 return markerApply(marker, delegate.createFunctionTypeAnnotation(
4633 params,
4634 returnType,
4635 rest,
4636 typeParameters
4637 ));
4638 case '(':
4639 lex();
4640 // Check to see if this is actually a grouped type
4641 if (!match(')') && !match('...')) {
4642 if (lookahead.type === Token.Identifier) {
4643 token = lookahead2();
4644 isGroupedType = token.value !== '?' && token.value !== ':';
4645 } else {
4646 isGroupedType = true;
4647 }
4648 }
4649
4650 if (isGroupedType) {
4651 type = parseType();
4652 expect(')');
4653
4654 // If we see a => next then someone was probably confused about
4655 // function types, so we can provide a better error message
4656 if (match('=>')) {
4657 throwError({}, Messages.ConfusedAboutFunctionType);
4658 }
4659
4660 return type;
4661 }
4662
4663 tmp = parseFunctionTypeParams();
4664 params = tmp.params;
4665 rest = tmp.rest;
4666
4667 expect(')');
4668
4669 expect('=>');
4670
4671 returnType = parseType();
4672
4673 return markerApply(marker, delegate.createFunctionTypeAnnotation(
4674 params,
4675 returnType,
4676 rest,
4677 null /* typeParameters */
4678 ));
4679 }
4680 break;
4681 case Token.Keyword:
4682 switch (lookahead.value) {
4683 case 'void':
4684 return markerApply(marker, parseVoidType());
4685 case 'typeof':
4686 return markerApply(marker, parseTypeofType());
4687 }
4688 break;
4689 case Token.StringLiteral:
4690 token = lex();
4691 if (token.octal) {
4692 throwError(token, Messages.StrictOctalLiteral);
4693 }
4694 return markerApply(marker, delegate.createStringLiteralTypeAnnotation(
4695 token
4696 ));
4697 }
4698
4699 throwUnexpected(lookahead);
4700 }
4701
4702 function parsePostfixType() {
4703 var marker = markerCreate(), t = parsePrimaryType();
4704 if (match('[')) {
4705 expect('[');
4706 expect(']');
4707 return markerApply(marker, delegate.createArrayTypeAnnotation(t));
4708 }
4709 return t;
4710 }
4711
4712 function parsePrefixType() {
4713 var marker = markerCreate();
4714 if (match('?')) {
4715 lex();
4716 return markerApply(marker, delegate.createNullableTypeAnnotation(
4717 parsePrefixType()
4718 ));
4719 }
4720 return parsePostfixType();
4721 }
4722
4723
4724 function parseIntersectionType() {
4725 var marker = markerCreate(), type, types;
4726 type = parsePrefixType();
4727 types = [type];
4728 while (match('&')) {
4729 lex();
4730 types.push(parsePrefixType());
4731 }
4732
4733 return types.length === 1 ?
4734 type :
4735 markerApply(marker, delegate.createIntersectionTypeAnnotation(
4736 types
4737 ));
4738 }
4739
4740 function parseUnionType() {
4741 var marker = markerCreate(), type, types;
4742 type = parseIntersectionType();
4743 types = [type];
4744 while (match('|')) {
4745 lex();
4746 types.push(parseIntersectionType());
4747 }
4748 return types.length === 1 ?
4749 type :
4750 markerApply(marker, delegate.createUnionTypeAnnotation(
4751 types
4752 ));
4753 }
4754
4755 function parseType() {
4756 var oldInType = state.inType, type;
4757 state.inType = true;
4758
4759 type = parseUnionType();
4760
4761 state.inType = oldInType;
4762 return type;
4763 }
4764
4765 function parseTypeAnnotation() {
4766 var marker = markerCreate(), type;
4767
4768 expect(':');
4769 type = parseType();
4770
4771 return markerApply(marker, delegate.createTypeAnnotation(type));
4772 }
4773
4774 function parseVariableIdentifier() {
4775 var marker = markerCreate(),
4776 token = lex();
4777
4778 if (token.type !== Token.Identifier) {
4779 throwUnexpected(token);
4780 }
4781
4782 return markerApply(marker, delegate.createIdentifier(token.value));
4783 }
4784
4785 function parseTypeAnnotatableIdentifier(requireTypeAnnotation, canBeOptionalParam) {
4786 var marker = markerCreate(),
4787 ident = parseVariableIdentifier(),
4788 isOptionalParam = false;
4789
4790 if (canBeOptionalParam && match('?')) {
4791 expect('?');
4792 isOptionalParam = true;
4793 }
4794
4795 if (requireTypeAnnotation || match(':')) {
4796 ident.typeAnnotation = parseTypeAnnotation();
4797 ident = markerApply(marker, ident);
4798 }
4799
4800 if (isOptionalParam) {
4801 ident.optional = true;
4802 ident = markerApply(marker, ident);
4803 }
4804
4805 return ident;
4806 }
4807
4808 function parseVariableDeclaration(kind) {
4809 var id,
4810 marker = markerCreate(),
4811 init = null,
4812 typeAnnotationMarker = markerCreate();
4813 if (match('{')) {
4814 id = parseObjectInitialiser();
4815 reinterpretAsAssignmentBindingPattern(id);
4816 if (match(':')) {
4817 id.typeAnnotation = parseTypeAnnotation();
4818 markerApply(typeAnnotationMarker, id);
4819 }
4820 } else if (match('[')) {
4821 id = parseArrayInitialiser();
4822 reinterpretAsAssignmentBindingPattern(id);
4823 if (match(':')) {
4824 id.typeAnnotation = parseTypeAnnotation();
4825 markerApply(typeAnnotationMarker, id);
4826 }
4827 } else {
4828 /* istanbul ignore next */
4829 id = state.allowKeyword ? parseNonComputedProperty() : parseTypeAnnotatableIdentifier();
4830 // 12.2.1
4831 if (strict && isRestrictedWord(id.name)) {
4832 throwErrorTolerant({}, Messages.StrictVarName);
4833 }
4834 }
4835
4836 if (kind === 'const') {
4837 if (!match('=')) {
4838 throwError({}, Messages.NoUninitializedConst);
4839 }
4840 expect('=');
4841 init = parseAssignmentExpression();
4842 } else if (match('=')) {
4843 lex();
4844 init = parseAssignmentExpression();
4845 }
4846
4847 return markerApply(marker, delegate.createVariableDeclarator(id, init));
4848 }
4849
4850 function parseVariableDeclarationList(kind) {
4851 var list = [];
4852
4853 do {
4854 list.push(parseVariableDeclaration(kind));
4855 if (!match(',')) {
4856 break;
4857 }
4858 lex();
4859 } while (index < length);
4860
4861 return list;
4862 }
4863
4864 function parseVariableStatement() {
4865 var declarations, marker = markerCreate();
4866
4867 expectKeyword('var');
4868
4869 declarations = parseVariableDeclarationList();
4870
4871 consumeSemicolon();
4872
4873 return markerApply(marker, delegate.createVariableDeclaration(declarations, 'var'));
4874 }
4875
4876 // kind may be `const` or `let`
4877 // Both are experimental and not in the specification yet.
4878 // see http://wiki.ecmascript.org/doku.php?id=harmony:const
4879 // and http://wiki.ecmascript.org/doku.php?id=harmony:let
4880 function parseConstLetDeclaration(kind) {
4881 var declarations, marker = markerCreate();
4882
4883 expectKeyword(kind);
4884
4885 declarations = parseVariableDeclarationList(kind);
4886
4887 consumeSemicolon();
4888
4889 return markerApply(marker, delegate.createVariableDeclaration(declarations, kind));
4890 }
4891
4892 // people.mozilla.org/~jorendorff/es6-draft.html
4893
4894 function parseModuleSpecifier() {
4895 var marker = markerCreate(),
4896 specifier;
4897
4898 if (lookahead.type !== Token.StringLiteral) {
4899 throwError({}, Messages.InvalidModuleSpecifier);
4900 }
4901 specifier = delegate.createLiteral(lex());
4902 return markerApply(marker, specifier);
4903 }
4904
4905 function parseExportBatchSpecifier() {
4906 var marker = markerCreate();
4907 expect('*');
4908 return markerApply(marker, delegate.createExportBatchSpecifier());
4909 }
4910
4911 function parseExportSpecifier() {
4912 var id, name = null, marker = markerCreate();
4913 if (matchKeyword('default')) {
4914 lex();
4915 id = markerApply(marker, delegate.createIdentifier('default'));
4916 // export {default} from "something";
4917 } else {
4918 id = parseVariableIdentifier();
4919 }
4920 if (matchContextualKeyword('as')) {
4921 lex();
4922 name = parseNonComputedProperty();
4923 }
4924
4925 return markerApply(marker, delegate.createExportSpecifier(id, name));
4926 }
4927
4928 function parseExportDeclaration() {
4929 var declaration = null,
4930 possibleIdentifierToken, sourceElement,
4931 isExportFromIdentifier,
4932 src = null, specifiers = [],
4933 marker = markerCreate();
4934
4935 expectKeyword('export');
4936
4937 if (matchKeyword('default')) {
4938 // covers:
4939 // export default ...
4940 lex();
4941 if (matchKeyword('function') || matchKeyword('class')) {
4942 possibleIdentifierToken = lookahead2();
4943 if (isIdentifierName(possibleIdentifierToken)) {
4944 // covers:
4945 // export default function foo () {}
4946 // export default class foo {}
4947 sourceElement = parseSourceElement();
4948 return markerApply(marker, delegate.createExportDeclaration(true, sourceElement, [sourceElement.id], null));
4949 }
4950 // covers:
4951 // export default function () {}
4952 // export default class {}
4953 switch (lookahead.value) {
4954 case 'class':
4955 return markerApply(marker, delegate.createExportDeclaration(true, parseClassExpression(), [], null));
4956 case 'function':
4957 return markerApply(marker, delegate.createExportDeclaration(true, parseFunctionExpression(), [], null));
4958 }
4959 }
4960
4961 if (matchContextualKeyword('from')) {
4962 throwError({}, Messages.UnexpectedToken, lookahead.value);
4963 }
4964
4965 // covers:
4966 // export default {};
4967 // export default [];
4968 if (match('{')) {
4969 declaration = parseObjectInitialiser();
4970 } else if (match('[')) {
4971 declaration = parseArrayInitialiser();
4972 } else {
4973 declaration = parseAssignmentExpression();
4974 }
4975 consumeSemicolon();
4976 return markerApply(marker, delegate.createExportDeclaration(true, declaration, [], null));
4977 }
4978
4979 // non-default export
4980 if (lookahead.type === Token.Keyword || matchContextualKeyword('type')) {
4981 // covers:
4982 // export var f = 1;
4983 switch (lookahead.value) {
4984 case 'type':
4985 case 'let':
4986 case 'const':
4987 case 'var':
4988 case 'class':
4989 case 'function':
4990 return markerApply(marker, delegate.createExportDeclaration(false, parseSourceElement(), specifiers, null));
4991 }
4992 }
4993
4994 if (match('*')) {
4995 // covers:
4996 // export * from "foo";
4997 specifiers.push(parseExportBatchSpecifier());
4998
4999 if (!matchContextualKeyword('from')) {
5000 throwError({}, lookahead.value ?
5001 Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
5002 }
5003 lex();
5004 src = parseModuleSpecifier();
5005 consumeSemicolon();
5006
5007 return markerApply(marker, delegate.createExportDeclaration(false, null, specifiers, src));
5008 }
5009
5010 expect('{');
5011 if (!match('}')) {
5012 do {
5013 isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default');
5014 specifiers.push(parseExportSpecifier());
5015 } while (match(',') && lex());
5016 }
5017 expect('}');
5018
5019 if (matchContextualKeyword('from')) {
5020 // covering:
5021 // export {default} from "foo";
5022 // export {foo} from "foo";
5023 lex();
5024 src = parseModuleSpecifier();
5025 consumeSemicolon();
5026 } else if (isExportFromIdentifier) {
5027 // covering:
5028 // export {default}; // missing fromClause
5029 throwError({}, lookahead.value ?
5030 Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
5031 } else {
5032 // cover
5033 // export {foo};
5034 consumeSemicolon();
5035 }
5036 return markerApply(marker, delegate.createExportDeclaration(false, declaration, specifiers, src));
5037 }
5038
5039
5040 function parseImportSpecifier() {
5041 // import {<foo as bar>} ...;
5042 var id, name = null, marker = markerCreate();
5043
5044 id = parseNonComputedProperty();
5045 if (matchContextualKeyword('as')) {
5046 lex();
5047 name = parseVariableIdentifier();
5048 }
5049
5050 return markerApply(marker, delegate.createImportSpecifier(id, name));
5051 }
5052
5053 function parseNamedImports() {
5054 var specifiers = [];
5055 // {foo, bar as bas}
5056 expect('{');
5057 if (!match('}')) {
5058 do {
5059 specifiers.push(parseImportSpecifier());
5060 } while (match(',') && lex());
5061 }
5062 expect('}');
5063 return specifiers;
5064 }
5065
5066 function parseImportDefaultSpecifier() {
5067 // import <foo> ...;
5068 var id, marker = markerCreate();
5069
5070 id = parseNonComputedProperty();
5071
5072 return markerApply(marker, delegate.createImportDefaultSpecifier(id));
5073 }
5074
5075 function parseImportNamespaceSpecifier() {
5076 // import <* as foo> ...;
5077 var id, marker = markerCreate();
5078
5079 expect('*');
5080 if (!matchContextualKeyword('as')) {
5081 throwError({}, Messages.NoAsAfterImportNamespace);
5082 }
5083 lex();
5084 id = parseNonComputedProperty();
5085
5086 return markerApply(marker, delegate.createImportNamespaceSpecifier(id));
5087 }
5088
5089 function parseImportDeclaration() {
5090 var specifiers, src, marker = markerCreate(), isType = false, token2;
5091
5092 expectKeyword('import');
5093
5094 if (matchContextualKeyword('type')) {
5095 token2 = lookahead2();
5096 if ((token2.type === Token.Identifier && token2.value !== 'from') ||
5097 (token2.type === Token.Punctuator &&
5098 (token2.value === '{' || token2.value === '*'))) {
5099 isType = true;
5100 lex();
5101 }
5102 }
5103
5104 specifiers = [];
5105
5106 if (lookahead.type === Token.StringLiteral) {
5107 // covers:
5108 // import "foo";
5109 src = parseModuleSpecifier();
5110 consumeSemicolon();
5111 return markerApply(marker, delegate.createImportDeclaration(specifiers, src, isType));
5112 }
5113
5114 if (!matchKeyword('default') && isIdentifierName(lookahead)) {
5115 // covers:
5116 // import foo
5117 // import foo, ...
5118 specifiers.push(parseImportDefaultSpecifier());
5119 if (match(',')) {
5120 lex();
5121 }
5122 }
5123 if (match('*')) {
5124 // covers:
5125 // import foo, * as foo
5126 // import * as foo
5127 specifiers.push(parseImportNamespaceSpecifier());
5128 } else if (match('{')) {
5129 // covers:
5130 // import foo, {bar}
5131 // import {bar}
5132 specifiers = specifiers.concat(parseNamedImports());
5133 }
5134
5135 if (!matchContextualKeyword('from')) {
5136 throwError({}, lookahead.value ?
5137 Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
5138 }
5139 lex();
5140 src = parseModuleSpecifier();
5141 consumeSemicolon();
5142
5143 return markerApply(marker, delegate.createImportDeclaration(specifiers, src, isType));
5144 }
5145
5146 // 12.3 Empty Statement
5147
5148 function parseEmptyStatement() {
5149 var marker = markerCreate();
5150 expect(';');
5151 return markerApply(marker, delegate.createEmptyStatement());
5152 }
5153
5154 // 12.4 Expression Statement
5155
5156 function parseExpressionStatement() {
5157 var marker = markerCreate(), expr = parseExpression();
5158 consumeSemicolon();
5159 return markerApply(marker, delegate.createExpressionStatement(expr));
5160 }
5161
5162 // 12.5 If statement
5163
5164 function parseIfStatement() {
5165 var test, consequent, alternate, marker = markerCreate();
5166
5167 expectKeyword('if');
5168
5169 expect('(');
5170
5171 test = parseExpression();
5172
5173 expect(')');
5174
5175 consequent = parseStatement();
5176
5177 if (matchKeyword('else')) {
5178 lex();
5179 alternate = parseStatement();
5180 } else {
5181 alternate = null;
5182 }
5183
5184 return markerApply(marker, delegate.createIfStatement(test, consequent, alternate));
5185 }
5186
5187 // 12.6 Iteration Statements
5188
5189 function parseDoWhileStatement() {
5190 var body, test, oldInIteration, marker = markerCreate();
5191
5192 expectKeyword('do');
5193
5194 oldInIteration = state.inIteration;
5195 state.inIteration = true;
5196
5197 body = parseStatement();
5198
5199 state.inIteration = oldInIteration;
5200
5201 expectKeyword('while');
5202
5203 expect('(');
5204
5205 test = parseExpression();
5206
5207 expect(')');
5208
5209 if (match(';')) {
5210 lex();
5211 }
5212
5213 return markerApply(marker, delegate.createDoWhileStatement(body, test));
5214 }
5215
5216 function parseWhileStatement() {
5217 var test, body, oldInIteration, marker = markerCreate();
5218
5219 expectKeyword('while');
5220
5221 expect('(');
5222
5223 test = parseExpression();
5224
5225 expect(')');
5226
5227 oldInIteration = state.inIteration;
5228 state.inIteration = true;
5229
5230 body = parseStatement();
5231
5232 state.inIteration = oldInIteration;
5233
5234 return markerApply(marker, delegate.createWhileStatement(test, body));
5235 }
5236
5237 function parseForVariableDeclaration() {
5238 var marker = markerCreate(),
5239 token = lex(),
5240 declarations = parseVariableDeclarationList();
5241
5242 return markerApply(marker, delegate.createVariableDeclaration(declarations, token.value));
5243 }
5244
5245 function parseForStatement(opts) {
5246 var init, test, update, left, right, body, operator, oldInIteration,
5247 marker = markerCreate();
5248 init = test = update = null;
5249 expectKeyword('for');
5250
5251 // http://wiki.ecmascript.org/doku.php?id=proposals:iterators_and_generators&s=each
5252 if (matchContextualKeyword('each')) {
5253 throwError({}, Messages.EachNotAllowed);
5254 }
5255
5256 expect('(');
5257
5258 if (match(';')) {
5259 lex();
5260 } else {
5261 if (matchKeyword('var') || matchKeyword('let') || matchKeyword('const')) {
5262 state.allowIn = false;
5263 init = parseForVariableDeclaration();
5264 state.allowIn = true;
5265
5266 if (init.declarations.length === 1) {
5267 if (matchKeyword('in') || matchContextualKeyword('of')) {
5268 operator = lookahead;
5269 if (!((operator.value === 'in' || init.kind !== 'var') && init.declarations[0].init)) {
5270 lex();
5271 left = init;
5272 right = parseExpression();
5273 init = null;
5274 }
5275 }
5276 }
5277 } else {
5278 state.allowIn = false;
5279 init = parseExpression();
5280 state.allowIn = true;
5281
5282 if (matchContextualKeyword('of')) {
5283 operator = lex();
5284 left = init;
5285 right = parseExpression();
5286 init = null;
5287 } else if (matchKeyword('in')) {
5288 // LeftHandSideExpression
5289 if (!isAssignableLeftHandSide(init)) {
5290 throwError({}, Messages.InvalidLHSInForIn);
5291 }
5292 operator = lex();
5293 left = init;
5294 right = parseExpression();
5295 init = null;
5296 }
5297 }
5298
5299 if (typeof left === 'undefined') {
5300 expect(';');
5301 }
5302 }
5303
5304 if (typeof left === 'undefined') {
5305
5306 if (!match(';')) {
5307 test = parseExpression();
5308 }
5309 expect(';');
5310
5311 if (!match(')')) {
5312 update = parseExpression();
5313 }
5314 }
5315
5316 expect(')');
5317
5318 oldInIteration = state.inIteration;
5319 state.inIteration = true;
5320
5321 if (!(opts !== undefined && opts.ignoreBody)) {
5322 body = parseStatement();
5323 }
5324
5325 state.inIteration = oldInIteration;
5326
5327 if (typeof left === 'undefined') {
5328 return markerApply(marker, delegate.createForStatement(init, test, update, body));
5329 }
5330
5331 if (operator.value === 'in') {
5332 return markerApply(marker, delegate.createForInStatement(left, right, body));
5333 }
5334 return markerApply(marker, delegate.createForOfStatement(left, right, body));
5335 }
5336
5337 // 12.7 The continue statement
5338
5339 function parseContinueStatement() {
5340 var label = null, marker = markerCreate();
5341
5342 expectKeyword('continue');
5343
5344 // Optimize the most common form: 'continue;'.
5345 if (source.charCodeAt(index) === 59) {
5346 lex();
5347
5348 if (!state.inIteration) {
5349 throwError({}, Messages.IllegalContinue);
5350 }
5351
5352 return markerApply(marker, delegate.createContinueStatement(null));
5353 }
5354
5355 if (peekLineTerminator()) {
5356 if (!state.inIteration) {
5357 throwError({}, Messages.IllegalContinue);
5358 }
5359
5360 return markerApply(marker, delegate.createContinueStatement(null));
5361 }
5362
5363 if (lookahead.type === Token.Identifier) {
5364 label = parseVariableIdentifier();
5365
5366 if (!state.labelSet.has(label.name)) {
5367 throwError({}, Messages.UnknownLabel, label.name);
5368 }
5369 }
5370
5371 consumeSemicolon();
5372
5373 if (label === null && !state.inIteration) {
5374 throwError({}, Messages.IllegalContinue);
5375 }
5376
5377 return markerApply(marker, delegate.createContinueStatement(label));
5378 }
5379
5380 // 12.8 The break statement
5381
5382 function parseBreakStatement() {
5383 var label = null, marker = markerCreate();
5384
5385 expectKeyword('break');
5386
5387 // Catch the very common case first: immediately a semicolon (char #59).
5388 if (source.charCodeAt(index) === 59) {
5389 lex();
5390
5391 if (!(state.inIteration || state.inSwitch)) {
5392 throwError({}, Messages.IllegalBreak);
5393 }
5394
5395 return markerApply(marker, delegate.createBreakStatement(null));
5396 }
5397
5398 if (peekLineTerminator()) {
5399 if (!(state.inIteration || state.inSwitch)) {
5400 throwError({}, Messages.IllegalBreak);
5401 }
5402
5403 return markerApply(marker, delegate.createBreakStatement(null));
5404 }
5405
5406 if (lookahead.type === Token.Identifier) {
5407 label = parseVariableIdentifier();
5408
5409 if (!state.labelSet.has(label.name)) {
5410 throwError({}, Messages.UnknownLabel, label.name);
5411 }
5412 }
5413
5414 consumeSemicolon();
5415
5416 if (label === null && !(state.inIteration || state.inSwitch)) {
5417 throwError({}, Messages.IllegalBreak);
5418 }
5419
5420 return markerApply(marker, delegate.createBreakStatement(label));
5421 }
5422
5423 // 12.9 The return statement
5424
5425 function parseReturnStatement() {
5426 var argument = null, marker = markerCreate();
5427
5428 expectKeyword('return');
5429
5430 if (!state.inFunctionBody) {
5431 throwErrorTolerant({}, Messages.IllegalReturn);
5432 }
5433
5434 // 'return' followed by a space and an identifier is very common.
5435 if (source.charCodeAt(index) === 32) {
5436 if (isIdentifierStart(source.charCodeAt(index + 1))) {
5437 argument = parseExpression();
5438 consumeSemicolon();
5439 return markerApply(marker, delegate.createReturnStatement(argument));
5440 }
5441 }
5442
5443 if (peekLineTerminator()) {
5444 return markerApply(marker, delegate.createReturnStatement(null));
5445 }
5446
5447 if (!match(';')) {
5448 if (!match('}') && lookahead.type !== Token.EOF) {
5449 argument = parseExpression();
5450 }
5451 }
5452
5453 consumeSemicolon();
5454
5455 return markerApply(marker, delegate.createReturnStatement(argument));
5456 }
5457
5458 // 12.10 The with statement
5459
5460 function parseWithStatement() {
5461 var object, body, marker = markerCreate();
5462
5463 if (strict) {
5464 throwErrorTolerant({}, Messages.StrictModeWith);
5465 }
5466
5467 expectKeyword('with');
5468
5469 expect('(');
5470
5471 object = parseExpression();
5472
5473 expect(')');
5474
5475 body = parseStatement();
5476
5477 return markerApply(marker, delegate.createWithStatement(object, body));
5478 }
5479
5480 // 12.10 The swith statement
5481
5482 function parseSwitchCase() {
5483 var test,
5484 consequent = [],
5485 sourceElement,
5486 marker = markerCreate();
5487
5488 if (matchKeyword('default')) {
5489 lex();
5490 test = null;
5491 } else {
5492 expectKeyword('case');
5493 test = parseExpression();
5494 }
5495 expect(':');
5496
5497 while (index < length) {
5498 if (match('}') || matchKeyword('default') || matchKeyword('case')) {
5499 break;
5500 }
5501 sourceElement = parseSourceElement();
5502 if (typeof sourceElement === 'undefined') {
5503 break;
5504 }
5505 consequent.push(sourceElement);
5506 }
5507
5508 return markerApply(marker, delegate.createSwitchCase(test, consequent));
5509 }
5510
5511 function parseSwitchStatement() {
5512 var discriminant, cases, clause, oldInSwitch, defaultFound, marker = markerCreate();
5513
5514 expectKeyword('switch');
5515
5516 expect('(');
5517
5518 discriminant = parseExpression();
5519
5520 expect(')');
5521
5522 expect('{');
5523
5524 cases = [];
5525
5526 if (match('}')) {
5527 lex();
5528 return markerApply(marker, delegate.createSwitchStatement(discriminant, cases));
5529 }
5530
5531 oldInSwitch = state.inSwitch;
5532 state.inSwitch = true;
5533 defaultFound = false;
5534
5535 while (index < length) {
5536 if (match('}')) {
5537 break;
5538 }
5539 clause = parseSwitchCase();
5540 if (clause.test === null) {
5541 if (defaultFound) {
5542 throwError({}, Messages.MultipleDefaultsInSwitch);
5543 }
5544 defaultFound = true;
5545 }
5546 cases.push(clause);
5547 }
5548
5549 state.inSwitch = oldInSwitch;
5550
5551 expect('}');
5552
5553 return markerApply(marker, delegate.createSwitchStatement(discriminant, cases));
5554 }
5555
5556 // 12.13 The throw statement
5557
5558 function parseThrowStatement() {
5559 var argument, marker = markerCreate();
5560
5561 expectKeyword('throw');
5562
5563 if (peekLineTerminator()) {
5564 throwError({}, Messages.NewlineAfterThrow);
5565 }
5566
5567 argument = parseExpression();
5568
5569 consumeSemicolon();
5570
5571 return markerApply(marker, delegate.createThrowStatement(argument));
5572 }
5573
5574 // 12.14 The try statement
5575
5576 function parseCatchClause() {
5577 var param, body, marker = markerCreate();
5578
5579 expectKeyword('catch');
5580
5581 expect('(');
5582 if (match(')')) {
5583 throwUnexpected(lookahead);
5584 }
5585
5586 param = parseExpression();
5587 // 12.14.1
5588 if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) {
5589 throwErrorTolerant({}, Messages.StrictCatchVariable);
5590 }
5591
5592 expect(')');
5593 body = parseBlock();
5594 return markerApply(marker, delegate.createCatchClause(param, body));
5595 }
5596
5597 function parseTryStatement() {
5598 var block, handlers = [], finalizer = null, marker = markerCreate();
5599
5600 expectKeyword('try');
5601
5602 block = parseBlock();
5603
5604 if (matchKeyword('catch')) {
5605 handlers.push(parseCatchClause());
5606 }
5607
5608 if (matchKeyword('finally')) {
5609 lex();
5610 finalizer = parseBlock();
5611 }
5612
5613 if (handlers.length === 0 && !finalizer) {
5614 throwError({}, Messages.NoCatchOrFinally);
5615 }
5616
5617 return markerApply(marker, delegate.createTryStatement(block, [], handlers, finalizer));
5618 }
5619
5620 // 12.15 The debugger statement
5621
5622 function parseDebuggerStatement() {
5623 var marker = markerCreate();
5624 expectKeyword('debugger');
5625
5626 consumeSemicolon();
5627
5628 return markerApply(marker, delegate.createDebuggerStatement());
5629 }
5630
5631 // 12 Statements
5632
5633 function parseStatement() {
5634 var type = lookahead.type,
5635 marker,
5636 expr,
5637 labeledBody;
5638
5639 if (type === Token.EOF) {
5640 throwUnexpected(lookahead);
5641 }
5642
5643 if (type === Token.Punctuator) {
5644 switch (lookahead.value) {
5645 case ';':
5646 return parseEmptyStatement();
5647 case '{':
5648 return parseBlock();
5649 case '(':
5650 return parseExpressionStatement();
5651 default:
5652 break;
5653 }
5654 }
5655
5656 if (type === Token.Keyword) {
5657 switch (lookahead.value) {
5658 case 'break':
5659 return parseBreakStatement();
5660 case 'continue':
5661 return parseContinueStatement();
5662 case 'debugger':
5663 return parseDebuggerStatement();
5664 case 'do':
5665 return parseDoWhileStatement();
5666 case 'for':
5667 return parseForStatement();
5668 case 'function':
5669 return parseFunctionDeclaration();
5670 case 'class':
5671 return parseClassDeclaration();
5672 case 'if':
5673 return parseIfStatement();
5674 case 'return':
5675 return parseReturnStatement();
5676 case 'switch':
5677 return parseSwitchStatement();
5678 case 'throw':
5679 return parseThrowStatement();
5680 case 'try':
5681 return parseTryStatement();
5682 case 'var':
5683 return parseVariableStatement();
5684 case 'while':
5685 return parseWhileStatement();
5686 case 'with':
5687 return parseWithStatement();
5688 default:
5689 break;
5690 }
5691 }
5692
5693 if (matchAsyncFuncExprOrDecl()) {
5694 return parseFunctionDeclaration();
5695 }
5696
5697 marker = markerCreate();
5698 expr = parseExpression();
5699
5700 // 12.12 Labelled Statements
5701 if ((expr.type === Syntax.Identifier) && match(':')) {
5702 lex();
5703
5704 if (state.labelSet.has(expr.name)) {
5705 throwError({}, Messages.Redeclaration, 'Label', expr.name);
5706 }
5707
5708 state.labelSet.set(expr.name, true);
5709 labeledBody = parseStatement();
5710 state.labelSet.delete(expr.name);
5711 return markerApply(marker, delegate.createLabeledStatement(expr, labeledBody));
5712 }
5713
5714 consumeSemicolon();
5715
5716 return markerApply(marker, delegate.createExpressionStatement(expr));
5717 }
5718
5719 // 13 Function Definition
5720
5721 function parseConciseBody() {
5722 if (match('{')) {
5723 return parseFunctionSourceElements();
5724 }
5725 return parseAssignmentExpression();
5726 }
5727
5728 function parseFunctionSourceElements() {
5729 var sourceElement, sourceElements = [], token, directive, firstRestricted,
5730 oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesizedCount,
5731 marker = markerCreate();
5732
5733 expect('{');
5734
5735 while (index < length) {
5736 if (lookahead.type !== Token.StringLiteral) {
5737 break;
5738 }
5739 token = lookahead;
5740
5741 sourceElement = parseSourceElement();
5742 sourceElements.push(sourceElement);
5743 if (sourceElement.expression.type !== Syntax.Literal) {
5744 // this is not directive
5745 break;
5746 }
5747 directive = source.slice(token.range[0] + 1, token.range[1] - 1);
5748 if (directive === 'use strict') {
5749 strict = true;
5750 if (firstRestricted) {
5751 throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
5752 }
5753 } else {
5754 if (!firstRestricted && token.octal) {
5755 firstRestricted = token;
5756 }
5757 }
5758 }
5759
5760 oldLabelSet = state.labelSet;
5761 oldInIteration = state.inIteration;
5762 oldInSwitch = state.inSwitch;
5763 oldInFunctionBody = state.inFunctionBody;
5764 oldParenthesizedCount = state.parenthesizedCount;
5765
5766 state.labelSet = new StringMap();
5767 state.inIteration = false;
5768 state.inSwitch = false;
5769 state.inFunctionBody = true;
5770 state.parenthesizedCount = 0;
5771
5772 while (index < length) {
5773 if (match('}')) {
5774 break;
5775 }
5776 sourceElement = parseSourceElement();
5777 if (typeof sourceElement === 'undefined') {
5778 break;
5779 }
5780 sourceElements.push(sourceElement);
5781 }
5782
5783 expect('}');
5784
5785 state.labelSet = oldLabelSet;
5786 state.inIteration = oldInIteration;
5787 state.inSwitch = oldInSwitch;
5788 state.inFunctionBody = oldInFunctionBody;
5789 state.parenthesizedCount = oldParenthesizedCount;
5790
5791 return markerApply(marker, delegate.createBlockStatement(sourceElements));
5792 }
5793
5794 function validateParam(options, param, name) {
5795 if (strict) {
5796 if (isRestrictedWord(name)) {
5797 options.stricted = param;
5798 options.message = Messages.StrictParamName;
5799 }
5800 if (options.paramSet.has(name)) {
5801 options.stricted = param;
5802 options.message = Messages.StrictParamDupe;
5803 }
5804 } else if (!options.firstRestricted) {
5805 if (isRestrictedWord(name)) {
5806 options.firstRestricted = param;
5807 options.message = Messages.StrictParamName;
5808 } else if (isStrictModeReservedWord(name)) {
5809 options.firstRestricted = param;
5810 options.message = Messages.StrictReservedWord;
5811 } else if (options.paramSet.has(name)) {
5812 options.firstRestricted = param;
5813 options.message = Messages.StrictParamDupe;
5814 }
5815 }
5816 options.paramSet.set(name, true);
5817 }
5818
5819 function parseParam(options) {
5820 var marker, token, rest, param, def;
5821
5822 token = lookahead;
5823 if (token.value === '...') {
5824 token = lex();
5825 rest = true;
5826 }
5827
5828 if (match('[')) {
5829 marker = markerCreate();
5830 param = parseArrayInitialiser();
5831 reinterpretAsDestructuredParameter(options, param);
5832 if (match(':')) {
5833 param.typeAnnotation = parseTypeAnnotation();
5834 markerApply(marker, param);
5835 }
5836 } else if (match('{')) {
5837 marker = markerCreate();
5838 if (rest) {
5839 throwError({}, Messages.ObjectPatternAsRestParameter);
5840 }
5841 param = parseObjectInitialiser();
5842 reinterpretAsDestructuredParameter(options, param);
5843 if (match(':')) {
5844 param.typeAnnotation = parseTypeAnnotation();
5845 markerApply(marker, param);
5846 }
5847 } else {
5848 param =
5849 rest
5850 ? parseTypeAnnotatableIdentifier(
5851 false, /* requireTypeAnnotation */
5852 false /* canBeOptionalParam */
5853 )
5854 : parseTypeAnnotatableIdentifier(
5855 false, /* requireTypeAnnotation */
5856 true /* canBeOptionalParam */
5857 );
5858
5859 validateParam(options, token, token.value);
5860 }
5861
5862 if (match('=')) {
5863 if (rest) {
5864 throwErrorTolerant(lookahead, Messages.DefaultRestParameter);
5865 }
5866 lex();
5867 def = parseAssignmentExpression();
5868 ++options.defaultCount;
5869 }
5870
5871 if (rest) {
5872 if (!match(')')) {
5873 throwError({}, Messages.ParameterAfterRestParameter);
5874 }
5875 options.rest = param;
5876 return false;
5877 }
5878
5879 options.params.push(param);
5880 options.defaults.push(def);
5881 return !match(')');
5882 }
5883
5884 function parseParams(firstRestricted) {
5885 var options, marker = markerCreate();
5886
5887 options = {
5888 params: [],
5889 defaultCount: 0,
5890 defaults: [],
5891 rest: null,
5892 firstRestricted: firstRestricted
5893 };
5894
5895 expect('(');
5896
5897 if (!match(')')) {
5898 options.paramSet = new StringMap();
5899 while (index < length) {
5900 if (!parseParam(options)) {
5901 break;
5902 }
5903 expect(',');
5904 if (!options.rest && match(')')) {
5905 break;
5906 }
5907 }
5908 }
5909
5910 expect(')');
5911
5912 if (options.defaultCount === 0) {
5913 options.defaults = [];
5914 }
5915
5916 if (match(':')) {
5917 options.returnType = parseTypeAnnotation();
5918 }
5919
5920 return markerApply(marker, options);
5921 }
5922
5923 function parseFunctionDeclaration() {
5924 var id, body, token, tmp, firstRestricted, message, generator, isAsync,
5925 previousStrict, previousYieldAllowed, previousAwaitAllowed,
5926 marker = markerCreate(), typeParameters;
5927
5928 isAsync = false;
5929 if (matchAsync()) {
5930 lex();
5931 isAsync = true;
5932 }
5933
5934 expectKeyword('function');
5935
5936 generator = false;
5937 if (match('*')) {
5938 lex();
5939 generator = true;
5940 }
5941
5942 token = lookahead;
5943
5944 id = parseVariableIdentifier();
5945
5946 if (match('<')) {
5947 typeParameters = parseTypeParameterDeclaration();
5948 }
5949
5950 if (strict) {
5951 if (isRestrictedWord(token.value)) {
5952 throwErrorTolerant(token, Messages.StrictFunctionName);
5953 }
5954 } else {
5955 if (isRestrictedWord(token.value)) {
5956 firstRestricted = token;
5957 message = Messages.StrictFunctionName;
5958 } else if (isStrictModeReservedWord(token.value)) {
5959 firstRestricted = token;
5960 message = Messages.StrictReservedWord;
5961 }
5962 }
5963
5964 tmp = parseParams(firstRestricted);
5965 firstRestricted = tmp.firstRestricted;
5966 if (tmp.message) {
5967 message = tmp.message;
5968 }
5969
5970 previousStrict = strict;
5971 previousYieldAllowed = state.yieldAllowed;
5972 state.yieldAllowed = generator;
5973 previousAwaitAllowed = state.awaitAllowed;
5974 state.awaitAllowed = isAsync;
5975
5976 body = parseFunctionSourceElements();
5977
5978 if (strict && firstRestricted) {
5979 throwError(firstRestricted, message);
5980 }
5981 if (strict && tmp.stricted) {
5982 throwErrorTolerant(tmp.stricted, message);
5983 }
5984 strict = previousStrict;
5985 state.yieldAllowed = previousYieldAllowed;
5986 state.awaitAllowed = previousAwaitAllowed;
5987
5988 return markerApply(
5989 marker,
5990 delegate.createFunctionDeclaration(
5991 id,
5992 tmp.params,
5993 tmp.defaults,
5994 body,
5995 tmp.rest,
5996 generator,
5997 false,
5998 isAsync,
5999 tmp.returnType,
6000 typeParameters
6001 )
6002 );
6003 }
6004
6005 function parseFunctionExpression() {
6006 var token, id = null, firstRestricted, message, tmp, body, generator, isAsync,
6007 previousStrict, previousYieldAllowed, previousAwaitAllowed,
6008 marker = markerCreate(), typeParameters;
6009
6010 isAsync = false;
6011 if (matchAsync()) {
6012 lex();
6013 isAsync = true;
6014 }
6015
6016 expectKeyword('function');
6017
6018 generator = false;
6019
6020 if (match('*')) {
6021 lex();
6022 generator = true;
6023 }
6024
6025 if (!match('(')) {
6026 if (!match('<')) {
6027 token = lookahead;
6028 id = parseVariableIdentifier();
6029
6030 if (strict) {
6031 if (isRestrictedWord(token.value)) {
6032 throwErrorTolerant(token, Messages.StrictFunctionName);
6033 }
6034 } else {
6035 if (isRestrictedWord(token.value)) {
6036 firstRestricted = token;
6037 message = Messages.StrictFunctionName;
6038 } else if (isStrictModeReservedWord(token.value)) {
6039 firstRestricted = token;
6040 message = Messages.StrictReservedWord;
6041 }
6042 }
6043 }
6044
6045 if (match('<')) {
6046 typeParameters = parseTypeParameterDeclaration();
6047 }
6048 }
6049
6050 tmp = parseParams(firstRestricted);
6051 firstRestricted = tmp.firstRestricted;
6052 if (tmp.message) {
6053 message = tmp.message;
6054 }
6055
6056 previousStrict = strict;
6057 previousYieldAllowed = state.yieldAllowed;
6058 state.yieldAllowed = generator;
6059 previousAwaitAllowed = state.awaitAllowed;
6060 state.awaitAllowed = isAsync;
6061
6062 body = parseFunctionSourceElements();
6063
6064 if (strict && firstRestricted) {
6065 throwError(firstRestricted, message);
6066 }
6067 if (strict && tmp.stricted) {
6068 throwErrorTolerant(tmp.stricted, message);
6069 }
6070 strict = previousStrict;
6071 state.yieldAllowed = previousYieldAllowed;
6072 state.awaitAllowed = previousAwaitAllowed;
6073
6074 return markerApply(
6075 marker,
6076 delegate.createFunctionExpression(
6077 id,
6078 tmp.params,
6079 tmp.defaults,
6080 body,
6081 tmp.rest,
6082 generator,
6083 false,
6084 isAsync,
6085 tmp.returnType,
6086 typeParameters
6087 )
6088 );
6089 }
6090
6091 function parseYieldExpression() {
6092 var delegateFlag, expr, marker = markerCreate();
6093
6094 expectKeyword('yield', !strict);
6095
6096 delegateFlag = false;
6097 if (match('*')) {
6098 lex();
6099 delegateFlag = true;
6100 }
6101
6102 expr = parseAssignmentExpression();
6103
6104 return markerApply(marker, delegate.createYieldExpression(expr, delegateFlag));
6105 }
6106
6107 function parseAwaitExpression() {
6108 var expr, marker = markerCreate();
6109 expectContextualKeyword('await');
6110 expr = parseAssignmentExpression();
6111 return markerApply(marker, delegate.createAwaitExpression(expr));
6112 }
6113
6114 // 14 Functions and classes
6115
6116 // 14.1 Functions is defined above (13 in ES5)
6117 // 14.2 Arrow Functions Definitions is defined in (7.3 assignments)
6118
6119 // 14.3 Method Definitions
6120 // 14.3.7
6121 function specialMethod(methodDefinition) {
6122 return methodDefinition.kind === 'get' ||
6123 methodDefinition.kind === 'set' ||
6124 methodDefinition.value.generator;
6125 }
6126
6127 function parseMethodDefinition(key, isStatic, generator, computed) {
6128 var token, param, propType,
6129 isAsync, typeParameters, tokenValue, returnType;
6130
6131 propType = isStatic ? ClassPropertyType.static : ClassPropertyType.prototype;
6132
6133 if (generator) {
6134 return delegate.createMethodDefinition(
6135 propType,
6136 '',
6137 key,
6138 parsePropertyMethodFunction({ generator: true }),
6139 computed
6140 );
6141 }
6142
6143 tokenValue = key.type === 'Identifier' && key.name;
6144
6145 if (tokenValue === 'get' && !match('(')) {
6146 key = parseObjectPropertyKey();
6147
6148 expect('(');
6149 expect(')');
6150 if (match(':')) {
6151 returnType = parseTypeAnnotation();
6152 }
6153 return delegate.createMethodDefinition(
6154 propType,
6155 'get',
6156 key,
6157 parsePropertyFunction({ generator: false, returnType: returnType }),
6158 computed
6159 );
6160 }
6161 if (tokenValue === 'set' && !match('(')) {
6162 key = parseObjectPropertyKey();
6163
6164 expect('(');
6165 token = lookahead;
6166 param = [ parseTypeAnnotatableIdentifier() ];
6167 expect(')');
6168 if (match(':')) {
6169 returnType = parseTypeAnnotation();
6170 }
6171 return delegate.createMethodDefinition(
6172 propType,
6173 'set',
6174 key,
6175 parsePropertyFunction({
6176 params: param,
6177 generator: false,
6178 name: token,
6179 returnType: returnType
6180 }),
6181 computed
6182 );
6183 }
6184
6185 if (match('<')) {
6186 typeParameters = parseTypeParameterDeclaration();
6187 }
6188
6189 isAsync = tokenValue === 'async' && !match('(');
6190 if (isAsync) {
6191 key = parseObjectPropertyKey();
6192 }
6193
6194 return delegate.createMethodDefinition(
6195 propType,
6196 '',
6197 key,
6198 parsePropertyMethodFunction({
6199 generator: false,
6200 async: isAsync,
6201 typeParameters: typeParameters
6202 }),
6203 computed
6204 );
6205 }
6206
6207 function parseClassProperty(key, computed, isStatic) {
6208 var typeAnnotation;
6209
6210 typeAnnotation = parseTypeAnnotation();
6211 expect(';');
6212
6213 return delegate.createClassProperty(
6214 key,
6215 typeAnnotation,
6216 computed,
6217 isStatic
6218 );
6219 }
6220
6221 function parseClassElement() {
6222 var computed = false, generator = false, key, marker = markerCreate(),
6223 isStatic = false, possiblyOpenBracketToken;
6224 if (match(';')) {
6225 lex();
6226 return undefined;
6227 }
6228
6229 if (lookahead.value === 'static') {
6230 lex();
6231 isStatic = true;
6232 }
6233
6234 if (match('*')) {
6235 lex();
6236 generator = true;
6237 }
6238
6239 possiblyOpenBracketToken = lookahead;
6240 if (matchContextualKeyword('get') || matchContextualKeyword('set')) {
6241 possiblyOpenBracketToken = lookahead2();
6242 }
6243
6244 if (possiblyOpenBracketToken.type === Token.Punctuator
6245 && possiblyOpenBracketToken.value === '[') {
6246 computed = true;
6247 }
6248
6249 key = parseObjectPropertyKey();
6250
6251 if (!generator && lookahead.value === ':') {
6252 return markerApply(marker, parseClassProperty(key, computed, isStatic));
6253 }
6254
6255 return markerApply(marker, parseMethodDefinition(
6256 key,
6257 isStatic,
6258 generator,
6259 computed
6260 ));
6261 }
6262
6263 function parseClassBody() {
6264 var classElement, classElements = [], existingProps = {},
6265 marker = markerCreate(), propName, propType;
6266
6267 existingProps[ClassPropertyType.static] = new StringMap();
6268 existingProps[ClassPropertyType.prototype] = new StringMap();
6269
6270 expect('{');
6271
6272 while (index < length) {
6273 if (match('}')) {
6274 break;
6275 }
6276 classElement = parseClassElement(existingProps);
6277
6278 if (typeof classElement !== 'undefined') {
6279 classElements.push(classElement);
6280
6281 propName = !classElement.computed && getFieldName(classElement.key);
6282 if (propName !== false) {
6283 propType = classElement.static ?
6284 ClassPropertyType.static :
6285 ClassPropertyType.prototype;
6286
6287 if (classElement.type === Syntax.MethodDefinition) {
6288 if (propName === 'constructor' && !classElement.static) {
6289 if (specialMethod(classElement)) {
6290 throwError(classElement, Messages.IllegalClassConstructorProperty);
6291 }
6292 if (existingProps[ClassPropertyType.prototype].has('constructor')) {
6293 throwError(classElement.key, Messages.IllegalDuplicateClassProperty);
6294 }
6295 }
6296 existingProps[propType].set(propName, true);
6297 }
6298 }
6299 }
6300 }
6301
6302 expect('}');
6303
6304 return markerApply(marker, delegate.createClassBody(classElements));
6305 }
6306
6307 function parseClassImplements() {
6308 var id, implemented = [], marker, typeParameters;
6309 if (strict) {
6310 expectKeyword('implements');
6311 } else {
6312 expectContextualKeyword('implements');
6313 }
6314 while (index < length) {
6315 marker = markerCreate();
6316 id = parseVariableIdentifier();
6317 if (match('<')) {
6318 typeParameters = parseTypeParameterInstantiation();
6319 } else {
6320 typeParameters = null;
6321 }
6322 implemented.push(markerApply(marker, delegate.createClassImplements(
6323 id,
6324 typeParameters
6325 )));
6326 if (!match(',')) {
6327 break;
6328 }
6329 expect(',');
6330 }
6331 return implemented;
6332 }
6333
6334 function parseClassExpression() {
6335 var id, implemented, previousYieldAllowed, superClass = null,
6336 superTypeParameters, marker = markerCreate(), typeParameters,
6337 matchImplements;
6338
6339 expectKeyword('class');
6340
6341 matchImplements =
6342 strict
6343 ? matchKeyword('implements')
6344 : matchContextualKeyword('implements');
6345
6346 if (!matchKeyword('extends') && !matchImplements && !match('{')) {
6347 id = parseVariableIdentifier();
6348 }
6349
6350 if (match('<')) {
6351 typeParameters = parseTypeParameterDeclaration();
6352 }
6353
6354 if (matchKeyword('extends')) {
6355 expectKeyword('extends');
6356 previousYieldAllowed = state.yieldAllowed;
6357 state.yieldAllowed = false;
6358 superClass = parseLeftHandSideExpressionAllowCall();
6359 if (match('<')) {
6360 superTypeParameters = parseTypeParameterInstantiation();
6361 }
6362 state.yieldAllowed = previousYieldAllowed;
6363 }
6364
6365 if (strict ? matchKeyword('implements') : matchContextualKeyword('implements')) {
6366 implemented = parseClassImplements();
6367 }
6368
6369 return markerApply(marker, delegate.createClassExpression(
6370 id,
6371 superClass,
6372 parseClassBody(),
6373 typeParameters,
6374 superTypeParameters,
6375 implemented
6376 ));
6377 }
6378
6379 function parseClassDeclaration() {
6380 var id, implemented, previousYieldAllowed, superClass = null,
6381 superTypeParameters, marker = markerCreate(), typeParameters;
6382
6383 expectKeyword('class');
6384
6385 id = parseVariableIdentifier();
6386
6387 if (match('<')) {
6388 typeParameters = parseTypeParameterDeclaration();
6389 }
6390
6391 if (matchKeyword('extends')) {
6392 expectKeyword('extends');
6393 previousYieldAllowed = state.yieldAllowed;
6394 state.yieldAllowed = false;
6395 superClass = parseLeftHandSideExpressionAllowCall();
6396 if (match('<')) {
6397 superTypeParameters = parseTypeParameterInstantiation();
6398 }
6399 state.yieldAllowed = previousYieldAllowed;
6400 }
6401
6402 if (strict ? matchKeyword('implements') : matchContextualKeyword('implements')) {
6403 implemented = parseClassImplements();
6404 }
6405
6406 return markerApply(marker, delegate.createClassDeclaration(
6407 id,
6408 superClass,
6409 parseClassBody(),
6410 typeParameters,
6411 superTypeParameters,
6412 implemented
6413 ));
6414 }
6415
6416 // 15 Program
6417
6418 function parseSourceElement() {
6419 var token;
6420 if (lookahead.type === Token.Keyword) {
6421 switch (lookahead.value) {
6422 case 'const':
6423 case 'let':
6424 return parseConstLetDeclaration(lookahead.value);
6425 case 'function':
6426 return parseFunctionDeclaration();
6427 case 'export':
6428 throwErrorTolerant({}, Messages.IllegalExportDeclaration);
6429 return parseExportDeclaration();
6430 case 'import':
6431 throwErrorTolerant({}, Messages.IllegalImportDeclaration);
6432 return parseImportDeclaration();
6433 case 'interface':
6434 if (lookahead2().type === Token.Identifier) {
6435 return parseInterface();
6436 }
6437 return parseStatement();
6438 default:
6439 return parseStatement();
6440 }
6441 }
6442
6443 if (matchContextualKeyword('type')
6444 && lookahead2().type === Token.Identifier) {
6445 return parseTypeAlias();
6446 }
6447
6448 if (matchContextualKeyword('interface')
6449 && lookahead2().type === Token.Identifier) {
6450 return parseInterface();
6451 }
6452
6453 if (matchContextualKeyword('declare')) {
6454 token = lookahead2();
6455 if (token.type === Token.Keyword) {
6456 switch (token.value) {
6457 case 'class':
6458 return parseDeclareClass();
6459 case 'function':
6460 return parseDeclareFunction();
6461 case 'var':
6462 return parseDeclareVariable();
6463 }
6464 } else if (token.type === Token.Identifier
6465 && token.value === 'module') {
6466 return parseDeclareModule();
6467 }
6468 }
6469
6470 if (lookahead.type !== Token.EOF) {
6471 return parseStatement();
6472 }
6473 }
6474
6475 function parseProgramElement() {
6476 var isModule = extra.sourceType === 'module' || extra.sourceType === 'nonStrictModule';
6477
6478 if (isModule && lookahead.type === Token.Keyword) {
6479 switch (lookahead.value) {
6480 case 'export':
6481 return parseExportDeclaration();
6482 case 'import':
6483 return parseImportDeclaration();
6484 }
6485 }
6486
6487 return parseSourceElement();
6488 }
6489
6490 function parseProgramElements() {
6491 var sourceElement, sourceElements = [], token, directive, firstRestricted;
6492
6493 while (index < length) {
6494 token = lookahead;
6495 if (token.type !== Token.StringLiteral) {
6496 break;
6497 }
6498
6499 sourceElement = parseProgramElement();
6500 sourceElements.push(sourceElement);
6501 if (sourceElement.expression.type !== Syntax.Literal) {
6502 // this is not directive
6503 break;
6504 }
6505 directive = source.slice(token.range[0] + 1, token.range[1] - 1);
6506 if (directive === 'use strict') {
6507 strict = true;
6508 if (firstRestricted) {
6509 throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
6510 }
6511 } else {
6512 if (!firstRestricted && token.octal) {
6513 firstRestricted = token;
6514 }
6515 }
6516 }
6517
6518 while (index < length) {
6519 sourceElement = parseProgramElement();
6520 if (typeof sourceElement === 'undefined') {
6521 break;
6522 }
6523 sourceElements.push(sourceElement);
6524 }
6525 return sourceElements;
6526 }
6527
6528 function parseProgram() {
6529 var body, marker = markerCreate();
6530 strict = extra.sourceType === 'module';
6531 peek();
6532 body = parseProgramElements();
6533 return markerApply(marker, delegate.createProgram(body));
6534 }
6535
6536 // 16 JSX
6537
6538 XHTMLEntities = {
6539 quot: '\u0022',
6540 amp: '&',
6541 apos: '\u0027',
6542 lt: '<',
6543 gt: '>',
6544 nbsp: '\u00A0',
6545 iexcl: '\u00A1',
6546 cent: '\u00A2',
6547 pound: '\u00A3',
6548 curren: '\u00A4',
6549 yen: '\u00A5',
6550 brvbar: '\u00A6',
6551 sect: '\u00A7',
6552 uml: '\u00A8',
6553 copy: '\u00A9',
6554 ordf: '\u00AA',
6555 laquo: '\u00AB',
6556 not: '\u00AC',
6557 shy: '\u00AD',
6558 reg: '\u00AE',
6559 macr: '\u00AF',
6560 deg: '\u00B0',
6561 plusmn: '\u00B1',
6562 sup2: '\u00B2',
6563 sup3: '\u00B3',
6564 acute: '\u00B4',
6565 micro: '\u00B5',
6566 para: '\u00B6',
6567 middot: '\u00B7',
6568 cedil: '\u00B8',
6569 sup1: '\u00B9',
6570 ordm: '\u00BA',
6571 raquo: '\u00BB',
6572 frac14: '\u00BC',
6573 frac12: '\u00BD',
6574 frac34: '\u00BE',
6575 iquest: '\u00BF',
6576 Agrave: '\u00C0',
6577 Aacute: '\u00C1',
6578 Acirc: '\u00C2',
6579 Atilde: '\u00C3',
6580 Auml: '\u00C4',
6581 Aring: '\u00C5',
6582 AElig: '\u00C6',
6583 Ccedil: '\u00C7',
6584 Egrave: '\u00C8',
6585 Eacute: '\u00C9',
6586 Ecirc: '\u00CA',
6587 Euml: '\u00CB',
6588 Igrave: '\u00CC',
6589 Iacute: '\u00CD',
6590 Icirc: '\u00CE',
6591 Iuml: '\u00CF',
6592 ETH: '\u00D0',
6593 Ntilde: '\u00D1',
6594 Ograve: '\u00D2',
6595 Oacute: '\u00D3',
6596 Ocirc: '\u00D4',
6597 Otilde: '\u00D5',
6598 Ouml: '\u00D6',
6599 times: '\u00D7',
6600 Oslash: '\u00D8',
6601 Ugrave: '\u00D9',
6602 Uacute: '\u00DA',
6603 Ucirc: '\u00DB',
6604 Uuml: '\u00DC',
6605 Yacute: '\u00DD',
6606 THORN: '\u00DE',
6607 szlig: '\u00DF',
6608 agrave: '\u00E0',
6609 aacute: '\u00E1',
6610 acirc: '\u00E2',
6611 atilde: '\u00E3',
6612 auml: '\u00E4',
6613 aring: '\u00E5',
6614 aelig: '\u00E6',
6615 ccedil: '\u00E7',
6616 egrave: '\u00E8',
6617 eacute: '\u00E9',
6618 ecirc: '\u00EA',
6619 euml: '\u00EB',
6620 igrave: '\u00EC',
6621 iacute: '\u00ED',
6622 icirc: '\u00EE',
6623 iuml: '\u00EF',
6624 eth: '\u00F0',
6625 ntilde: '\u00F1',
6626 ograve: '\u00F2',
6627 oacute: '\u00F3',
6628 ocirc: '\u00F4',
6629 otilde: '\u00F5',
6630 ouml: '\u00F6',
6631 divide: '\u00F7',
6632 oslash: '\u00F8',
6633 ugrave: '\u00F9',
6634 uacute: '\u00FA',
6635 ucirc: '\u00FB',
6636 uuml: '\u00FC',
6637 yacute: '\u00FD',
6638 thorn: '\u00FE',
6639 yuml: '\u00FF',
6640 OElig: '\u0152',
6641 oelig: '\u0153',
6642 Scaron: '\u0160',
6643 scaron: '\u0161',
6644 Yuml: '\u0178',
6645 fnof: '\u0192',
6646 circ: '\u02C6',
6647 tilde: '\u02DC',
6648 Alpha: '\u0391',
6649 Beta: '\u0392',
6650 Gamma: '\u0393',
6651 Delta: '\u0394',
6652 Epsilon: '\u0395',
6653 Zeta: '\u0396',
6654 Eta: '\u0397',
6655 Theta: '\u0398',
6656 Iota: '\u0399',
6657 Kappa: '\u039A',
6658 Lambda: '\u039B',
6659 Mu: '\u039C',
6660 Nu: '\u039D',
6661 Xi: '\u039E',
6662 Omicron: '\u039F',
6663 Pi: '\u03A0',
6664 Rho: '\u03A1',
6665 Sigma: '\u03A3',
6666 Tau: '\u03A4',
6667 Upsilon: '\u03A5',
6668 Phi: '\u03A6',
6669 Chi: '\u03A7',
6670 Psi: '\u03A8',
6671 Omega: '\u03A9',
6672 alpha: '\u03B1',
6673 beta: '\u03B2',
6674 gamma: '\u03B3',
6675 delta: '\u03B4',
6676 epsilon: '\u03B5',
6677 zeta: '\u03B6',
6678 eta: '\u03B7',
6679 theta: '\u03B8',
6680 iota: '\u03B9',
6681 kappa: '\u03BA',
6682 lambda: '\u03BB',
6683 mu: '\u03BC',
6684 nu: '\u03BD',
6685 xi: '\u03BE',
6686 omicron: '\u03BF',
6687 pi: '\u03C0',
6688 rho: '\u03C1',
6689 sigmaf: '\u03C2',
6690 sigma: '\u03C3',
6691 tau: '\u03C4',
6692 upsilon: '\u03C5',
6693 phi: '\u03C6',
6694 chi: '\u03C7',
6695 psi: '\u03C8',
6696 omega: '\u03C9',
6697 thetasym: '\u03D1',
6698 upsih: '\u03D2',
6699 piv: '\u03D6',
6700 ensp: '\u2002',
6701 emsp: '\u2003',
6702 thinsp: '\u2009',
6703 zwnj: '\u200C',
6704 zwj: '\u200D',
6705 lrm: '\u200E',
6706 rlm: '\u200F',
6707 ndash: '\u2013',
6708 mdash: '\u2014',
6709 lsquo: '\u2018',
6710 rsquo: '\u2019',
6711 sbquo: '\u201A',
6712 ldquo: '\u201C',
6713 rdquo: '\u201D',
6714 bdquo: '\u201E',
6715 dagger: '\u2020',
6716 Dagger: '\u2021',
6717 bull: '\u2022',
6718 hellip: '\u2026',
6719 permil: '\u2030',
6720 prime: '\u2032',
6721 Prime: '\u2033',
6722 lsaquo: '\u2039',
6723 rsaquo: '\u203A',
6724 oline: '\u203E',
6725 frasl: '\u2044',
6726 euro: '\u20AC',
6727 image: '\u2111',
6728 weierp: '\u2118',
6729 real: '\u211C',
6730 trade: '\u2122',
6731 alefsym: '\u2135',
6732 larr: '\u2190',
6733 uarr: '\u2191',
6734 rarr: '\u2192',
6735 darr: '\u2193',
6736 harr: '\u2194',
6737 crarr: '\u21B5',
6738 lArr: '\u21D0',
6739 uArr: '\u21D1',
6740 rArr: '\u21D2',
6741 dArr: '\u21D3',
6742 hArr: '\u21D4',
6743 forall: '\u2200',
6744 part: '\u2202',
6745 exist: '\u2203',
6746 empty: '\u2205',
6747 nabla: '\u2207',
6748 isin: '\u2208',
6749 notin: '\u2209',
6750 ni: '\u220B',
6751 prod: '\u220F',
6752 sum: '\u2211',
6753 minus: '\u2212',
6754 lowast: '\u2217',
6755 radic: '\u221A',
6756 prop: '\u221D',
6757 infin: '\u221E',
6758 ang: '\u2220',
6759 and: '\u2227',
6760 or: '\u2228',
6761 cap: '\u2229',
6762 cup: '\u222A',
6763 'int': '\u222B',
6764 there4: '\u2234',
6765 sim: '\u223C',
6766 cong: '\u2245',
6767 asymp: '\u2248',
6768 ne: '\u2260',
6769 equiv: '\u2261',
6770 le: '\u2264',
6771 ge: '\u2265',
6772 sub: '\u2282',
6773 sup: '\u2283',
6774 nsub: '\u2284',
6775 sube: '\u2286',
6776 supe: '\u2287',
6777 oplus: '\u2295',
6778 otimes: '\u2297',
6779 perp: '\u22A5',
6780 sdot: '\u22C5',
6781 lceil: '\u2308',
6782 rceil: '\u2309',
6783 lfloor: '\u230A',
6784 rfloor: '\u230B',
6785 lang: '\u2329',
6786 rang: '\u232A',
6787 loz: '\u25CA',
6788 spades: '\u2660',
6789 clubs: '\u2663',
6790 hearts: '\u2665',
6791 diams: '\u2666'
6792 };
6793
6794 function getQualifiedJSXName(object) {
6795 if (object.type === Syntax.JSXIdentifier) {
6796 return object.name;
6797 }
6798 if (object.type === Syntax.JSXNamespacedName) {
6799 return object.namespace.name + ':' + object.name.name;
6800 }
6801 /* istanbul ignore else */
6802 if (object.type === Syntax.JSXMemberExpression) {
6803 return (
6804 getQualifiedJSXName(object.object) + '.' +
6805 getQualifiedJSXName(object.property)
6806 );
6807 }
6808 /* istanbul ignore next */
6809 throwUnexpected(object);
6810 }
6811
6812 function isJSXIdentifierStart(ch) {
6813 // exclude backslash (\)
6814 return (ch !== 92) && isIdentifierStart(ch);
6815 }
6816
6817 function isJSXIdentifierPart(ch) {
6818 // exclude backslash (\) and add hyphen (-)
6819 return (ch !== 92) && (ch === 45 || isIdentifierPart(ch));
6820 }
6821
6822 function scanJSXIdentifier() {
6823 var ch, start, value = '';
6824
6825 start = index;
6826 while (index < length) {
6827 ch = source.charCodeAt(index);
6828 if (!isJSXIdentifierPart(ch)) {
6829 break;
6830 }
6831 value += source[index++];
6832 }
6833
6834 return {
6835 type: Token.JSXIdentifier,
6836 value: value,
6837 lineNumber: lineNumber,
6838 lineStart: lineStart,
6839 range: [start, index]
6840 };
6841 }
6842
6843 function scanJSXEntity() {
6844 var ch, str = '', start = index, count = 0, code;
6845 ch = source[index];
6846 assert(ch === '&', 'Entity must start with an ampersand');
6847 index++;
6848 while (index < length && count++ < 10) {
6849 ch = source[index++];
6850 if (ch === ';') {
6851 break;
6852 }
6853 str += ch;
6854 }
6855
6856 // Well-formed entity (ending was found).
6857 if (ch === ';') {
6858 // Numeric entity.
6859 if (str[0] === '#') {
6860 if (str[1] === 'x') {
6861 code = +('0' + str.substr(1));
6862 } else {
6863 // Removing leading zeros in order to avoid treating as octal in old browsers.
6864 code = +str.substr(1).replace(Regex.LeadingZeros, '');
6865 }
6866
6867 if (!isNaN(code)) {
6868 return String.fromCharCode(code);
6869 }
6870 /* istanbul ignore else */
6871 } else if (XHTMLEntities[str]) {
6872 return XHTMLEntities[str];
6873 }
6874 }
6875
6876 // Treat non-entity sequences as regular text.
6877 index = start + 1;
6878 return '&';
6879 }
6880
6881 function scanJSXText(stopChars) {
6882 var ch, str = '', start;
6883 start = index;
6884 while (index < length) {
6885 ch = source[index];
6886 if (stopChars.indexOf(ch) !== -1) {
6887 break;
6888 }
6889 if (ch === '&') {
6890 str += scanJSXEntity();
6891 } else {
6892 index++;
6893 if (ch === '\r' && source[index] === '\n') {
6894 str += ch;
6895 ch = source[index];
6896 index++;
6897 }
6898 if (isLineTerminator(ch.charCodeAt(0))) {
6899 ++lineNumber;
6900 lineStart = index;
6901 }
6902 str += ch;
6903 }
6904 }
6905 return {
6906 type: Token.JSXText,
6907 value: str,
6908 lineNumber: lineNumber,
6909 lineStart: lineStart,
6910 range: [start, index]
6911 };
6912 }
6913
6914 function scanJSXStringLiteral() {
6915 var innerToken, quote, start;
6916
6917 quote = source[index];
6918 assert((quote === '\'' || quote === '"'),
6919 'String literal must starts with a quote');
6920
6921 start = index;
6922 ++index;
6923
6924 innerToken = scanJSXText([quote]);
6925
6926 if (quote !== source[index]) {
6927 throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
6928 }
6929
6930 ++index;
6931
6932 innerToken.range = [start, index];
6933
6934 return innerToken;
6935 }
6936
6937 /**
6938 * Between JSX opening and closing tags (e.g. <foo>HERE</foo>), anything that
6939 * is not another JSX tag and is not an expression wrapped by {} is text.
6940 */
6941 function advanceJSXChild() {
6942 var ch = source.charCodeAt(index);
6943
6944 // '<' 60, '>' 62, '{' 123, '}' 125
6945 if (ch !== 60 && ch !== 62 && ch !== 123 && ch !== 125) {
6946 return scanJSXText(['<', '>', '{', '}']);
6947 }
6948
6949 return scanPunctuator();
6950 }
6951
6952 function parseJSXIdentifier() {
6953 var token, marker = markerCreate();
6954
6955 if (lookahead.type !== Token.JSXIdentifier) {
6956 throwUnexpected(lookahead);
6957 }
6958
6959 token = lex();
6960 return markerApply(marker, delegate.createJSXIdentifier(token.value));
6961 }
6962
6963 function parseJSXNamespacedName() {
6964 var namespace, name, marker = markerCreate();
6965
6966 namespace = parseJSXIdentifier();
6967 expect(':');
6968 name = parseJSXIdentifier();
6969
6970 return markerApply(marker, delegate.createJSXNamespacedName(namespace, name));
6971 }
6972
6973 function parseJSXMemberExpression() {
6974 var marker = markerCreate(),
6975 expr = parseJSXIdentifier();
6976
6977 while (match('.')) {
6978 lex();
6979 expr = markerApply(marker, delegate.createJSXMemberExpression(expr, parseJSXIdentifier()));
6980 }
6981
6982 return expr;
6983 }
6984
6985 function parseJSXElementName() {
6986 if (lookahead2().value === ':') {
6987 return parseJSXNamespacedName();
6988 }
6989 if (lookahead2().value === '.') {
6990 return parseJSXMemberExpression();
6991 }
6992
6993 return parseJSXIdentifier();
6994 }
6995
6996 function parseJSXAttributeName() {
6997 if (lookahead2().value === ':') {
6998 return parseJSXNamespacedName();
6999 }
7000
7001 return parseJSXIdentifier();
7002 }
7003
7004 function parseJSXAttributeValue() {
7005 var value, marker;
7006 if (match('{')) {
7007 value = parseJSXExpressionContainer();
7008 if (value.expression.type === Syntax.JSXEmptyExpression) {
7009 throwError(
7010 value,
7011 'JSX attributes must only be assigned a non-empty ' +
7012 'expression'
7013 );
7014 }
7015 } else if (match('<')) {
7016 value = parseJSXElement();
7017 } else if (lookahead.type === Token.JSXText) {
7018 marker = markerCreate();
7019 value = markerApply(marker, delegate.createLiteral(lex()));
7020 } else {
7021 throwError({}, Messages.InvalidJSXAttributeValue);
7022 }
7023 return value;
7024 }
7025
7026 function parseJSXEmptyExpression() {
7027 var ch, marker = markerCreatePreserveWhitespace();
7028 while (index < length) {
7029 ch = source.charCodeAt(index);
7030 if (ch === 125) {
7031 break;
7032 } else if (isLineTerminator(ch)) {
7033 if (ch === 13 && source.charCodeAt(index + 1) === 10) {
7034 ++index;
7035 }
7036 ++lineNumber;
7037 lineStart = index;
7038 }
7039 ++index;
7040 }
7041 return markerApply(marker, delegate.createJSXEmptyExpression());
7042 }
7043
7044 function parseJSXExpressionContainer() {
7045 var expression, origInJSXChild, origInJSXTag, marker = markerCreate();
7046
7047 origInJSXChild = state.inJSXChild;
7048 origInJSXTag = state.inJSXTag;
7049 state.inJSXChild = false;
7050 state.inJSXTag = false;
7051
7052 expect('{');
7053
7054 if (match('}')) {
7055 expression = parseJSXEmptyExpression();
7056 } else {
7057 expression = parseExpression();
7058 }
7059
7060 state.inJSXChild = origInJSXChild;
7061 state.inJSXTag = origInJSXTag;
7062
7063 expect('}');
7064
7065 return markerApply(marker, delegate.createJSXExpressionContainer(expression));
7066 }
7067
7068 function parseJSXSpreadAttribute() {
7069 var expression, origInJSXChild, origInJSXTag, marker = markerCreate();
7070
7071 origInJSXChild = state.inJSXChild;
7072 origInJSXTag = state.inJSXTag;
7073 state.inJSXChild = false;
7074 state.inJSXTag = false;
7075
7076 expect('{');
7077 expect('...');
7078
7079 expression = parseAssignmentExpression();
7080
7081 state.inJSXChild = origInJSXChild;
7082 state.inJSXTag = origInJSXTag;
7083
7084 expect('}');
7085
7086 return markerApply(marker, delegate.createJSXSpreadAttribute(expression));
7087 }
7088
7089 function parseJSXAttribute() {
7090 var name, marker;
7091
7092 if (match('{')) {
7093 return parseJSXSpreadAttribute();
7094 }
7095
7096 marker = markerCreate();
7097
7098 name = parseJSXAttributeName();
7099
7100 // HTML empty attribute
7101 if (match('=')) {
7102 lex();
7103 return markerApply(marker, delegate.createJSXAttribute(name, parseJSXAttributeValue()));
7104 }
7105
7106 return markerApply(marker, delegate.createJSXAttribute(name));
7107 }
7108
7109 function parseJSXChild() {
7110 var token, marker;
7111 if (match('{')) {
7112 token = parseJSXExpressionContainer();
7113 } else if (lookahead.type === Token.JSXText) {
7114 marker = markerCreatePreserveWhitespace();
7115 token = markerApply(marker, delegate.createLiteral(lex()));
7116 } else if (match('<')) {
7117 token = parseJSXElement();
7118 } else {
7119 throwUnexpected(lookahead);
7120 }
7121 return token;
7122 }
7123
7124 function parseJSXClosingElement() {
7125 var name, origInJSXChild, origInJSXTag, marker = markerCreate();
7126 origInJSXChild = state.inJSXChild;
7127 origInJSXTag = state.inJSXTag;
7128 state.inJSXChild = false;
7129 state.inJSXTag = true;
7130 expect('<');
7131 expect('/');
7132 name = parseJSXElementName();
7133 // Because advance() (called by lex() called by expect()) expects there
7134 // to be a valid token after >, it needs to know whether to look for a
7135 // standard JS token or an JSX text node
7136 state.inJSXChild = origInJSXChild;
7137 state.inJSXTag = origInJSXTag;
7138 expect('>');
7139 return markerApply(marker, delegate.createJSXClosingElement(name));
7140 }
7141
7142 function parseJSXOpeningElement() {
7143 var name, attributes = [], selfClosing = false, origInJSXChild, origInJSXTag, marker = markerCreate();
7144
7145 origInJSXChild = state.inJSXChild;
7146 origInJSXTag = state.inJSXTag;
7147 state.inJSXChild = false;
7148 state.inJSXTag = true;
7149
7150 expect('<');
7151
7152 name = parseJSXElementName();
7153
7154 while (index < length &&
7155 lookahead.value !== '/' &&
7156 lookahead.value !== '>') {
7157 attributes.push(parseJSXAttribute());
7158 }
7159
7160 state.inJSXTag = origInJSXTag;
7161
7162 if (lookahead.value === '/') {
7163 expect('/');
7164 // Because advance() (called by lex() called by expect()) expects
7165 // there to be a valid token after >, it needs to know whether to
7166 // look for a standard JS token or an JSX text node
7167 state.inJSXChild = origInJSXChild;
7168 expect('>');
7169 selfClosing = true;
7170 } else {
7171 state.inJSXChild = true;
7172 expect('>');
7173 }
7174 return markerApply(marker, delegate.createJSXOpeningElement(name, attributes, selfClosing));
7175 }
7176
7177 function parseJSXElement() {
7178 var openingElement, closingElement = null, children = [], origInJSXChild, origInJSXTag, marker = markerCreate();
7179
7180 origInJSXChild = state.inJSXChild;
7181 origInJSXTag = state.inJSXTag;
7182 openingElement = parseJSXOpeningElement();
7183
7184 if (!openingElement.selfClosing) {
7185 while (index < length) {
7186 state.inJSXChild = false; // Call lookahead2() with inJSXChild = false because </ should not be considered in the child
7187 if (lookahead.value === '<' && lookahead2().value === '/') {
7188 break;
7189 }
7190 state.inJSXChild = true;
7191 children.push(parseJSXChild());
7192 }
7193 state.inJSXChild = origInJSXChild;
7194 state.inJSXTag = origInJSXTag;
7195 closingElement = parseJSXClosingElement();
7196 if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
7197 throwError({}, Messages.ExpectedJSXClosingTag, getQualifiedJSXName(openingElement.name));
7198 }
7199 }
7200
7201 // When (erroneously) writing two adjacent tags like
7202 //
7203 // var x = <div>one</div><div>two</div>;
7204 //
7205 // the default error message is a bit incomprehensible. Since it's
7206 // rarely (never?) useful to write a less-than sign after an JSX
7207 // element, we disallow it here in the parser in order to provide a
7208 // better error message. (In the rare case that the less-than operator
7209 // was intended, the left tag can be wrapped in parentheses.)
7210 if (!origInJSXChild && match('<')) {
7211 throwError(lookahead, Messages.AdjacentJSXElements);
7212 }
7213
7214 return markerApply(marker, delegate.createJSXElement(openingElement, closingElement, children));
7215 }
7216
7217 function parseTypeAlias() {
7218 var id, marker = markerCreate(), typeParameters = null, right;
7219 expectContextualKeyword('type');
7220 id = parseVariableIdentifier();
7221 if (match('<')) {
7222 typeParameters = parseTypeParameterDeclaration();
7223 }
7224 expect('=');
7225 right = parseType();
7226 consumeSemicolon();
7227 return markerApply(marker, delegate.createTypeAlias(id, typeParameters, right));
7228 }
7229
7230 function parseInterfaceExtends() {
7231 var marker = markerCreate(), id, typeParameters = null;
7232
7233 id = parseVariableIdentifier();
7234 if (match('<')) {
7235 typeParameters = parseTypeParameterInstantiation();
7236 }
7237
7238 return markerApply(marker, delegate.createInterfaceExtends(
7239 id,
7240 typeParameters
7241 ));
7242 }
7243
7244 function parseInterfaceish(marker, allowStatic) {
7245 var body, bodyMarker, extended = [], id,
7246 typeParameters = null;
7247
7248 id = parseVariableIdentifier();
7249 if (match('<')) {
7250 typeParameters = parseTypeParameterDeclaration();
7251 }
7252
7253 if (matchKeyword('extends')) {
7254 expectKeyword('extends');
7255
7256 while (index < length) {
7257 extended.push(parseInterfaceExtends());
7258 if (!match(',')) {
7259 break;
7260 }
7261 expect(',');
7262 }
7263 }
7264
7265 bodyMarker = markerCreate();
7266 body = markerApply(bodyMarker, parseObjectType(allowStatic));
7267
7268 return markerApply(marker, delegate.createInterface(
7269 id,
7270 typeParameters,
7271 body,
7272 extended
7273 ));
7274 }
7275
7276 function parseInterface() {
7277 var marker = markerCreate();
7278
7279 if (strict) {
7280 expectKeyword('interface');
7281 } else {
7282 expectContextualKeyword('interface');
7283 }
7284
7285 return parseInterfaceish(marker, /* allowStatic */false);
7286 }
7287
7288 function parseDeclareClass() {
7289 var marker = markerCreate(), ret;
7290 expectContextualKeyword('declare');
7291 expectKeyword('class');
7292
7293 ret = parseInterfaceish(marker, /* allowStatic */true);
7294 ret.type = Syntax.DeclareClass;
7295 return ret;
7296 }
7297
7298 function parseDeclareFunction() {
7299 var id, idMarker,
7300 marker = markerCreate(), params, returnType, rest, tmp,
7301 typeParameters = null, value, valueMarker;
7302
7303 expectContextualKeyword('declare');
7304 expectKeyword('function');
7305 idMarker = markerCreate();
7306 id = parseVariableIdentifier();
7307
7308 valueMarker = markerCreate();
7309 if (match('<')) {
7310 typeParameters = parseTypeParameterDeclaration();
7311 }
7312 expect('(');
7313 tmp = parseFunctionTypeParams();
7314 params = tmp.params;
7315 rest = tmp.rest;
7316 expect(')');
7317
7318 expect(':');
7319 returnType = parseType();
7320
7321 value = markerApply(valueMarker, delegate.createFunctionTypeAnnotation(
7322 params,
7323 returnType,
7324 rest,
7325 typeParameters
7326 ));
7327
7328 id.typeAnnotation = markerApply(valueMarker, delegate.createTypeAnnotation(
7329 value
7330 ));
7331 markerApply(idMarker, id);
7332
7333 consumeSemicolon();
7334
7335 return markerApply(marker, delegate.createDeclareFunction(
7336 id
7337 ));
7338 }
7339
7340 function parseDeclareVariable() {
7341 var id, marker = markerCreate();
7342 expectContextualKeyword('declare');
7343 expectKeyword('var');
7344 id = parseTypeAnnotatableIdentifier();
7345
7346 consumeSemicolon();
7347
7348 return markerApply(marker, delegate.createDeclareVariable(
7349 id
7350 ));
7351 }
7352
7353 function parseDeclareModule() {
7354 var body = [], bodyMarker, id, idMarker, marker = markerCreate(), token;
7355 expectContextualKeyword('declare');
7356 expectContextualKeyword('module');
7357
7358 if (lookahead.type === Token.StringLiteral) {
7359 if (strict && lookahead.octal) {
7360 throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
7361 }
7362 idMarker = markerCreate();
7363 id = markerApply(idMarker, delegate.createLiteral(lex()));
7364 } else {
7365 id = parseVariableIdentifier();
7366 }
7367
7368 bodyMarker = markerCreate();
7369 expect('{');
7370 while (index < length && !match('}')) {
7371 token = lookahead2();
7372 switch (token.value) {
7373 case 'class':
7374 body.push(parseDeclareClass());
7375 break;
7376 case 'function':
7377 body.push(parseDeclareFunction());
7378 break;
7379 case 'var':
7380 body.push(parseDeclareVariable());
7381 break;
7382 default:
7383 throwUnexpected(lookahead);
7384 }
7385 }
7386 expect('}');
7387
7388 return markerApply(marker, delegate.createDeclareModule(
7389 id,
7390 markerApply(bodyMarker, delegate.createBlockStatement(body))
7391 ));
7392 }
7393
7394 function collectToken() {
7395 var loc, token, range, value, entry;
7396
7397 /* istanbul ignore else */
7398 if (!state.inJSXChild) {
7399 skipComment();
7400 }
7401
7402 loc = {
7403 start: {
7404 line: lineNumber,
7405 column: index - lineStart
7406 }
7407 };
7408
7409 token = extra.advance();
7410 loc.end = {
7411 line: lineNumber,
7412 column: index - lineStart
7413 };
7414
7415 if (token.type !== Token.EOF) {
7416 range = [token.range[0], token.range[1]];
7417 value = source.slice(token.range[0], token.range[1]);
7418 entry = {
7419 type: TokenName[token.type],
7420 value: value,
7421 range: range,
7422 loc: loc
7423 };
7424 if (token.regex) {
7425 entry.regex = {
7426 pattern: token.regex.pattern,
7427 flags: token.regex.flags
7428 };
7429 }
7430 extra.tokens.push(entry);
7431 }
7432
7433 return token;
7434 }
7435
7436 function collectRegex() {
7437 var pos, loc, regex, token;
7438
7439 skipComment();
7440
7441 pos = index;
7442 loc = {
7443 start: {
7444 line: lineNumber,
7445 column: index - lineStart
7446 }
7447 };
7448
7449 regex = extra.scanRegExp();
7450 loc.end = {
7451 line: lineNumber,
7452 column: index - lineStart
7453 };
7454
7455 if (!extra.tokenize) {
7456 /* istanbul ignore next */
7457 // Pop the previous token, which is likely '/' or '/='
7458 if (extra.tokens.length > 0) {
7459 token = extra.tokens[extra.tokens.length - 1];
7460 if (token.range[0] === pos && token.type === 'Punctuator') {
7461 if (token.value === '/' || token.value === '/=') {
7462 extra.tokens.pop();
7463 }
7464 }
7465 }
7466
7467 extra.tokens.push({
7468 type: 'RegularExpression',
7469 value: regex.literal,
7470 regex: regex.regex,
7471 range: [pos, index],
7472 loc: loc
7473 });
7474 }
7475
7476 return regex;
7477 }
7478
7479 function filterTokenLocation() {
7480 var i, entry, token, tokens = [];
7481
7482 for (i = 0; i < extra.tokens.length; ++i) {
7483 entry = extra.tokens[i];
7484 token = {
7485 type: entry.type,
7486 value: entry.value
7487 };
7488 if (entry.regex) {
7489 token.regex = {
7490 pattern: entry.regex.pattern,
7491 flags: entry.regex.flags
7492 };
7493 }
7494 if (extra.range) {
7495 token.range = entry.range;
7496 }
7497 if (extra.loc) {
7498 token.loc = entry.loc;
7499 }
7500 tokens.push(token);
7501 }
7502
7503 extra.tokens = tokens;
7504 }
7505
7506 function patch() {
7507 if (typeof extra.tokens !== 'undefined') {
7508 extra.advance = advance;
7509 extra.scanRegExp = scanRegExp;
7510
7511 advance = collectToken;
7512 scanRegExp = collectRegex;
7513 }
7514 }
7515
7516 function unpatch() {
7517 if (typeof extra.scanRegExp === 'function') {
7518 advance = extra.advance;
7519 scanRegExp = extra.scanRegExp;
7520 }
7521 }
7522
7523 // This is used to modify the delegate.
7524
7525 function extend(object, properties) {
7526 var entry, result = {};
7527
7528 for (entry in object) {
7529 /* istanbul ignore else */
7530 if (object.hasOwnProperty(entry)) {
7531 result[entry] = object[entry];
7532 }
7533 }
7534
7535 for (entry in properties) {
7536 /* istanbul ignore else */
7537 if (properties.hasOwnProperty(entry)) {
7538 result[entry] = properties[entry];
7539 }
7540 }
7541
7542 return result;
7543 }
7544
7545 function tokenize(code, options) {
7546 var toString,
7547 token,
7548 tokens;
7549
7550 toString = String;
7551 if (typeof code !== 'string' && !(code instanceof String)) {
7552 code = toString(code);
7553 }
7554
7555 delegate = SyntaxTreeDelegate;
7556 source = code;
7557 index = 0;
7558 lineNumber = (source.length > 0) ? 1 : 0;
7559 lineStart = 0;
7560 length = source.length;
7561 lookahead = null;
7562 state = {
7563 allowKeyword: true,
7564 allowIn: true,
7565 labelSet: new StringMap(),
7566 inFunctionBody: false,
7567 inIteration: false,
7568 inSwitch: false,
7569 lastCommentStart: -1,
7570 curlyStack: [],
7571 curlyLastIndex: 0
7572 };
7573
7574 extra = {};
7575
7576 // Options matching.
7577 options = options || {};
7578
7579 // Of course we collect tokens here.
7580 options.tokens = true;
7581 extra.tokens = [];
7582 extra.tokenize = true;
7583 // The following two fields are necessary to compute the Regex tokens.
7584 extra.openParenToken = -1;
7585 extra.openCurlyToken = -1;
7586
7587 extra.range = (typeof options.range === 'boolean') && options.range;
7588 extra.loc = (typeof options.loc === 'boolean') && options.loc;
7589
7590 if (typeof options.comment === 'boolean' && options.comment) {
7591 extra.comments = [];
7592 }
7593 if (typeof options.tolerant === 'boolean' && options.tolerant) {
7594 extra.errors = [];
7595 }
7596
7597 patch();
7598
7599 try {
7600 peek();
7601 if (lookahead.type === Token.EOF) {
7602 return extra.tokens;
7603 }
7604
7605 token = lex();
7606 while (lookahead.type !== Token.EOF) {
7607 try {
7608 token = lex();
7609 } catch (lexError) {
7610 token = lookahead;
7611 if (extra.errors) {
7612 extra.errors.push(lexError);
7613 // We have to break on the first error
7614 // to avoid infinite loops.
7615 break;
7616 } else {
7617 throw lexError;
7618 }
7619 }
7620 }
7621
7622 filterTokenLocation();
7623 tokens = extra.tokens;
7624 if (typeof extra.comments !== 'undefined') {
7625 tokens.comments = extra.comments;
7626 }
7627 if (typeof extra.errors !== 'undefined') {
7628 tokens.errors = extra.errors;
7629 }
7630 } catch (e) {
7631 throw e;
7632 } finally {
7633 unpatch();
7634 extra = {};
7635 }
7636 return tokens;
7637 }
7638
7639 function parse(code, options) {
7640 var program, toString;
7641
7642 toString = String;
7643 if (typeof code !== 'string' && !(code instanceof String)) {
7644 code = toString(code);
7645 }
7646
7647 delegate = SyntaxTreeDelegate;
7648 source = code;
7649 index = 0;
7650 lineNumber = (source.length > 0) ? 1 : 0;
7651 lineStart = 0;
7652 length = source.length;
7653 lookahead = null;
7654 state = {
7655 allowKeyword: false,
7656 allowIn: true,
7657 labelSet: new StringMap(),
7658 parenthesizedCount: 0,
7659 inFunctionBody: false,
7660 inIteration: false,
7661 inSwitch: false,
7662 inJSXChild: false,
7663 inJSXTag: false,
7664 inType: false,
7665 lastCommentStart: -1,
7666 yieldAllowed: false,
7667 awaitAllowed: false,
7668 curlyPosition: 0,
7669 curlyStack: [],
7670 curlyLastIndex: 0
7671 };
7672
7673 extra = {};
7674 if (typeof options !== 'undefined') {
7675 extra.range = (typeof options.range === 'boolean') && options.range;
7676 extra.loc = (typeof options.loc === 'boolean') && options.loc;
7677 extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment;
7678
7679 if (extra.loc && options.source !== null && options.source !== undefined) {
7680 delegate = extend(delegate, {
7681 'postProcess': function (node) {
7682 node.loc.source = toString(options.source);
7683 return node;
7684 }
7685 });
7686 }
7687
7688 extra.sourceType = options.sourceType;
7689 if (typeof options.tokens === 'boolean' && options.tokens) {
7690 extra.tokens = [];
7691 }
7692 if (typeof options.comment === 'boolean' && options.comment) {
7693 extra.comments = [];
7694 }
7695 if (typeof options.tolerant === 'boolean' && options.tolerant) {
7696 extra.errors = [];
7697 }
7698 if (extra.attachComment) {
7699 extra.range = true;
7700 extra.comments = [];
7701 extra.bottomRightStack = [];
7702 extra.trailingComments = [];
7703 extra.leadingComments = [];
7704 }
7705 }
7706
7707 patch();
7708 try {
7709 program = parseProgram();
7710 if (typeof extra.comments !== 'undefined') {
7711 program.comments = extra.comments;
7712 }
7713 if (typeof extra.tokens !== 'undefined') {
7714 filterTokenLocation();
7715 program.tokens = extra.tokens;
7716 }
7717 if (typeof extra.errors !== 'undefined') {
7718 program.errors = extra.errors;
7719 }
7720 } catch (e) {
7721 throw e;
7722 } finally {
7723 unpatch();
7724 extra = {};
7725 }
7726
7727 return program;
7728 }
7729
7730 // Sync with *.json manifests.
7731 exports.version = '14001.1.0-dev-harmony-fb';
7732
7733 exports.tokenize = tokenize;
7734
7735 exports.parse = parse;
7736
7737 // Deep copy.
7738 /* istanbul ignore next */
7739 exports.Syntax = (function () {
7740 var name, types = {};
7741
7742 if (typeof Object.create === 'function') {
7743 types = Object.create(null);
7744 }
7745
7746 for (name in Syntax) {
7747 if (Syntax.hasOwnProperty(name)) {
7748 types[name] = Syntax[name];
7749 }
7750 }
7751
7752 if (typeof Object.freeze === 'function') {
7753 Object.freeze(types);
7754 }
7755
7756 return types;
7757 }());
7758
7759}));
7760/* vim: set sw=4 ts=4 et tw=80 : */
7761
\No newline at end of file