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