UNPKG

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