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