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