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