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