UNPKG

87.6 kBJavaScriptView Raw
1/**
2 * Copyright 2014 Shape Security, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17"use strict";
18
19// istanbul ignore next
20
21var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
22
23// istanbul ignore next
24
25var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
26
27// istanbul ignore next
28
29function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
30
31// istanbul ignore next
32
33function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
34
35var _errors = require("./errors");
36
37var _tokenizer = require("./tokenizer");
38
39// Empty parameter list for ArrowExpression
40var ARROW_EXPRESSION_PARAMS = "CoverParenthesizedExpressionAndArrowParameterList";
41
42var Precedence = {
43 Sequence: 0,
44 Yield: 1,
45 Assignment: 1,
46 Conditional: 2,
47 ArrowFunction: 2,
48 LogicalOR: 3,
49 LogicalAND: 4,
50 BitwiseOR: 5,
51 BitwiseXOR: 6,
52 BitwiseAND: 7,
53 Equality: 8,
54 Relational: 9,
55 BitwiseSHIFT: 10,
56 Additive: 11,
57 Multiplicative: 12,
58 Unary: 13,
59 Postfix: 14,
60 Call: 15,
61 New: 16,
62 TaggedTemplate: 17,
63 Member: 18,
64 Primary: 19
65};
66
67var BinaryPrecedence = {
68 "||": Precedence.LogicalOR,
69 "&&": Precedence.LogicalAND,
70 "|": Precedence.BitwiseOR,
71 "^": Precedence.BitwiseXOR,
72 "&": Precedence.BitwiseAND,
73 "==": Precedence.Equality,
74 "!=": Precedence.Equality,
75 "===": Precedence.Equality,
76 "!==": Precedence.Equality,
77 "<": Precedence.Relational,
78 ">": Precedence.Relational,
79 "<=": Precedence.Relational,
80 ">=": Precedence.Relational,
81 "in": Precedence.Relational,
82 "instanceof": Precedence.Relational,
83 "<<": Precedence.BitwiseSHIFT,
84 ">>": Precedence.BitwiseSHIFT,
85 ">>>": Precedence.BitwiseSHIFT,
86 "+": Precedence.Additive,
87 "-": Precedence.Additive,
88 "*": Precedence.Multiplicative,
89 "%": Precedence.Multiplicative,
90 "/": Precedence.Multiplicative
91};
92
93function copyLocation(from, to) {
94 if ("loc" in from) {
95 to.loc = from.loc;
96 }
97 return to;
98}
99
100function isValidSimpleAssignmentTarget(node) {
101 switch (node.type) {
102 case "IdentifierExpression":
103 case "ComputedMemberExpression":
104 case "StaticMemberExpression":
105 return true;
106 }
107 return false;
108}
109
110function isPrefixOperator(token) {
111 switch (token.type) {
112 case _tokenizer.TokenType.INC:
113 case _tokenizer.TokenType.DEC:
114 case _tokenizer.TokenType.ADD:
115 case _tokenizer.TokenType.SUB:
116 case _tokenizer.TokenType.BIT_NOT:
117 case _tokenizer.TokenType.NOT:
118 case _tokenizer.TokenType.DELETE:
119 case _tokenizer.TokenType.VOID:
120 case _tokenizer.TokenType.TYPEOF:
121 return true;
122 }
123 return false;
124}
125
126function isUpdateOperator(token) {
127 return token.type === _tokenizer.TokenType.INC || token.type === _tokenizer.TokenType.DEC;
128}
129
130var Parser = (function (_Tokenizer) {
131 _inherits(Parser, _Tokenizer);
132
133 function Parser(source) {
134 _classCallCheck(this, Parser);
135
136 _get(Object.getPrototypeOf(Parser.prototype), "constructor", this).call(this, source);
137 this.allowIn = true;
138 this.inFunctionBody = false;
139 this.inParameter = false;
140 this.allowYieldExpression = false;
141 this.module = false;
142 this.moduleIsTheGoalSymbol = false;
143 this.strict = false;
144
145 // Cover grammar
146 this.isBindingElement = true;
147 this.isAssignmentTarget = true;
148 this.firstExprError = null;
149 }
150
151 _createClass(Parser, [{
152 key: "match",
153 value: function match(subType) {
154 return this.lookahead.type === subType;
155 }
156 }, {
157 key: "eat",
158 value: function eat(tokenType) {
159 if (this.lookahead.type === tokenType) {
160 return this.lex();
161 }
162 }
163 }, {
164 key: "expect",
165 value: function expect(tokenType) {
166 if (this.lookahead.type === tokenType) {
167 return this.lex();
168 }
169 throw this.createUnexpected(this.lookahead);
170 }
171 }, {
172 key: "matchContextualKeyword",
173 value: function matchContextualKeyword(keyword) {
174 return this.lookahead.type === _tokenizer.TokenType.IDENTIFIER && this.lookahead.value === keyword;
175 }
176 }, {
177 key: "expectContextualKeyword",
178 value: function expectContextualKeyword(keyword) {
179 if (this.lookahead.type === _tokenizer.TokenType.IDENTIFIER && this.lookahead.value === keyword) {
180 return this.lex();
181 } else {
182 throw this.createUnexpected(this.lookahead);
183 }
184 }
185 }, {
186 key: "eatContextualKeyword",
187 value: function eatContextualKeyword(keyword) {
188 if (this.lookahead.type === _tokenizer.TokenType.IDENTIFIER && this.lookahead.value === keyword) {
189 return this.lex();
190 }
191 }
192 }, {
193 key: "consumeSemicolon",
194 value: function consumeSemicolon() {
195 if (this.hasLineTerminatorBeforeNext) return;
196 if (this.eat(_tokenizer.TokenType.SEMICOLON)) return;
197 if (!this.eof() && !this.match(_tokenizer.TokenType.RBRACE)) {
198 throw this.createUnexpected(this.lookahead);
199 }
200 }
201
202 // this is a no-op, reserved for future use
203 }, {
204 key: "markLocation",
205 value: function markLocation(node /*, startLocation*/) {
206 return node;
207 }
208 }, {
209 key: "parseModule",
210 value: function parseModule() {
211 this.moduleIsTheGoalSymbol = this.module = this.strict = true;
212 this.lookahead = this.advance();
213
214 var startLocation = this.getLocation();
215
216 var _parseBody = this.parseBody();
217
218 var directives = _parseBody.directives;
219 var statements = _parseBody.statements;
220
221 return this.markLocation({ type: "Module", directives: directives, items: statements }, startLocation);
222 }
223 }, {
224 key: "parseScript",
225 value: function parseScript() {
226 this.lookahead = this.advance();
227
228 var startLocation = this.getLocation();
229 var body = this.parseBody();
230 body.type = "Script";
231 if (!this.match(_tokenizer.TokenType.EOS)) {
232 throw this.createUnexpected(this.lookahead);
233 }
234 return this.markLocation(body, startLocation);
235 }
236 }, {
237 key: "parseFunctionBody",
238 value: function parseFunctionBody() {
239 var startLocation = this.getLocation();
240
241 var oldInFunctionBody = this.inFunctionBody;
242 var oldModule = this.module;
243 var oldStrict = this.strict;
244 this.inFunctionBody = true;
245 this.module = false;
246 this.strict = false;
247
248 this.expect(_tokenizer.TokenType.LBRACE);
249 var body = this.markLocation(this.parseBody(), startLocation);
250 this.expect(_tokenizer.TokenType.RBRACE);
251
252 this.inFunctionBody = oldInFunctionBody;
253 this.module = oldModule;
254 this.strict = oldStrict;
255
256 return body;
257 }
258 }, {
259 key: "parseBody",
260 value: function parseBody() {
261 var directives = [],
262 statements = [],
263 parsingDirectives = true;
264
265 while (true) {
266 if (this.eof() || this.match(_tokenizer.TokenType.RBRACE)) break;
267 var token = this.lookahead;
268 var text = token.slice.text;
269 var isStringLiteral = token.type === _tokenizer.TokenType.STRING;
270 var isModule = this.module;
271 var directiveLocation = this.getLocation();
272 var stmt = isModule ? this.parseModuleItem() : this.parseStatementListItem();
273 if (parsingDirectives) {
274 if (isStringLiteral && stmt.type === "ExpressionStatement" && stmt.expression.type === "LiteralStringExpression") {
275 var rawValue = text.slice(1, -1);
276 if (rawValue === "use strict") {
277 this.strict = true;
278 }
279 directives.push(this.markLocation({ type: "Directive", rawValue: rawValue }, directiveLocation));
280 } else {
281 parsingDirectives = false;
282 statements.push(stmt);
283 }
284 } else {
285 statements.push(stmt);
286 }
287 }
288
289 return { type: "FunctionBody", directives: directives, statements: statements };
290 }
291 }, {
292 key: "parseImportSpecifier",
293 value: function parseImportSpecifier() {
294 var startLocation = this.getLocation(),
295 name = undefined;
296 if (this.match(_tokenizer.TokenType.IDENTIFIER) || this.match(_tokenizer.TokenType.YIELD) || this.match(_tokenizer.TokenType.LET)) {
297 name = this.parseIdentifier();
298 if (!this.eatContextualKeyword("as")) {
299 return this.markLocation({
300 type: "ImportSpecifier",
301 name: null,
302 binding: this.markLocation({ type: "BindingIdentifier", name: name }, startLocation)
303 }, startLocation);
304 }
305 } else if (this.lookahead.type.klass.isIdentifierName) {
306 name = this.parseIdentifierName();
307 this.expectContextualKeyword("as");
308 }
309
310 return this.markLocation({ type: "ImportSpecifier", name: name, binding: this.parseBindingIdentifier() }, startLocation);
311 }
312 }, {
313 key: "parseNameSpaceBinding",
314 value: function parseNameSpaceBinding() {
315 this.expect(_tokenizer.TokenType.MUL);
316 this.expectContextualKeyword("as");
317 return this.parseBindingIdentifier();
318 }
319 }, {
320 key: "parseNamedImports",
321 value: function parseNamedImports() {
322 var result = [];
323 this.expect(_tokenizer.TokenType.LBRACE);
324 while (!this.eat(_tokenizer.TokenType.RBRACE)) {
325 result.push(this.parseImportSpecifier());
326 if (!this.eat(_tokenizer.TokenType.COMMA)) {
327 this.expect(_tokenizer.TokenType.RBRACE);
328 break;
329 }
330 }
331 return result;
332 }
333 }, {
334 key: "parseFromClause",
335 value: function parseFromClause() {
336 this.expectContextualKeyword("from");
337 var value = this.expect(_tokenizer.TokenType.STRING).str;
338 this.consumeSemicolon();
339 return value;
340 }
341 }, {
342 key: "parseImportDeclaration",
343 value: function parseImportDeclaration() {
344 var startLocation = this.getLocation(),
345 defaultBinding = null,
346 moduleSpecifier = undefined;
347 this.expect(_tokenizer.TokenType.IMPORT);
348 switch (this.lookahead.type) {
349 case _tokenizer.TokenType.STRING:
350 moduleSpecifier = this.lex().str;
351 this.consumeSemicolon();
352 return this.markLocation({ type: "Import", defaultBinding: null, namedImports: [], moduleSpecifier: moduleSpecifier }, startLocation);
353 case _tokenizer.TokenType.IDENTIFIER:
354 case _tokenizer.TokenType.YIELD:
355 case _tokenizer.TokenType.LET:
356 defaultBinding = this.parseBindingIdentifier();
357 if (!this.eat(_tokenizer.TokenType.COMMA)) {
358 return this.markLocation({ type: "Import", defaultBinding: defaultBinding, namedImports: [], moduleSpecifier: this.parseFromClause() }, startLocation);
359 }
360 break;
361 }
362 if (this.match(_tokenizer.TokenType.MUL)) {
363 return this.markLocation({
364 type: "ImportNamespace",
365 defaultBinding: defaultBinding,
366 namespaceBinding: this.parseNameSpaceBinding(),
367 moduleSpecifier: this.parseFromClause()
368 }, startLocation);
369 } else if (this.match(_tokenizer.TokenType.LBRACE)) {
370 return this.markLocation({
371 type: "Import",
372 defaultBinding: defaultBinding,
373 namedImports: this.parseNamedImports(),
374 moduleSpecifier: this.parseFromClause()
375 }, startLocation);
376 } else {
377 throw this.createUnexpected(this.lookahead);
378 }
379 }
380 }, {
381 key: "parseExportSpecifier",
382 value: function parseExportSpecifier() {
383 var startLocation = this.getLocation();
384 var name = this.parseIdentifierName();
385 if (this.eatContextualKeyword("as")) {
386 var exportedName = this.parseIdentifierName();
387 return this.markLocation({ type: "ExportSpecifier", name: name, exportedName: exportedName }, startLocation);
388 }
389 return this.markLocation({ type: "ExportSpecifier", name: null, exportedName: name }, startLocation);
390 }
391 }, {
392 key: "parseExportClause",
393 value: function parseExportClause() {
394 this.expect(_tokenizer.TokenType.LBRACE);
395 var result = [];
396 while (!this.eat(_tokenizer.TokenType.RBRACE)) {
397 result.push(this.parseExportSpecifier());
398 if (!this.eat(_tokenizer.TokenType.COMMA)) {
399 this.expect(_tokenizer.TokenType.RBRACE);
400 break;
401 }
402 }
403 return result;
404 }
405 }, {
406 key: "parseExportDeclaration",
407 value: function parseExportDeclaration() {
408 var startLocation = this.getLocation(),
409 decl = undefined;
410 this.expect(_tokenizer.TokenType.EXPORT);
411 switch (this.lookahead.type) {
412 case _tokenizer.TokenType.MUL:
413 this.lex();
414 // export * FromClause ;
415 decl = { type: "ExportAllFrom", moduleSpecifier: this.parseFromClause() };
416 break;
417 case _tokenizer.TokenType.LBRACE:
418 // export ExportClause FromClause ;
419 // export ExportClause ;
420 var namedExports = this.parseExportClause();
421 var moduleSpecifier = null;
422 if (this.matchContextualKeyword("from")) {
423 moduleSpecifier = this.parseFromClause();
424 }
425 decl = { type: "ExportFrom", namedExports: namedExports, moduleSpecifier: moduleSpecifier };
426 break;
427 case _tokenizer.TokenType.CLASS:
428 // export ClassDeclaration
429 decl = { type: "Export", declaration: this.parseClass({ isExpr: false, inDefault: false }) };
430 break;
431 case _tokenizer.TokenType.FUNCTION:
432 // export HoistableDeclaration
433 decl = { type: "Export", declaration: this.parseFunction({ isExpr: false, inDefault: false, allowGenerator: true }) };
434 break;
435 case _tokenizer.TokenType.DEFAULT:
436 this.lex();
437 switch (this.lookahead.type) {
438 case _tokenizer.TokenType.FUNCTION:
439 // export default HoistableDeclaration[Default]
440 decl = {
441 type: "ExportDefault",
442 body: this.parseFunction({ isExpr: false, inDefault: true, allowGenerator: true })
443 };
444 break;
445 case _tokenizer.TokenType.CLASS:
446 // export default ClassDeclaration[Default]
447 decl = { type: "ExportDefault", body: this.parseClass({ isExpr: false, inDefault: true }) };
448 break;
449 default:
450 // export default [lookahead ∉ {function, class}] AssignmentExpression[In] ;
451 decl = { type: "ExportDefault", body: this.parseAssignmentExpression() };
452 this.consumeSemicolon();
453 break;
454 }
455 break;
456 case _tokenizer.TokenType.VAR:
457 case _tokenizer.TokenType.LET:
458 case _tokenizer.TokenType.CONST:
459 // export LexicalDeclaration
460 decl = { type: "Export", declaration: this.parseVariableDeclaration(true) };
461 this.consumeSemicolon();
462 break;
463 default:
464 throw this.createUnexpected(this.lookahead);
465 }
466 return this.markLocation(decl, startLocation);
467 }
468 }, {
469 key: "parseModuleItem",
470 value: function parseModuleItem() {
471 switch (this.lookahead.type) {
472 case _tokenizer.TokenType.IMPORT:
473 return this.parseImportDeclaration();
474 case _tokenizer.TokenType.EXPORT:
475 return this.parseExportDeclaration();
476 default:
477 return this.parseStatementListItem();
478 }
479 }
480 }, {
481 key: "lookaheadLexicalDeclaration",
482 value: function lookaheadLexicalDeclaration() {
483 if (this.match(_tokenizer.TokenType.LET) || this.match(_tokenizer.TokenType.CONST)) {
484 var lexerState = this.saveLexerState();
485 this.lex();
486 if (this.match(_tokenizer.TokenType.IDENTIFIER) || this.match(_tokenizer.TokenType.YIELD) || this.match(_tokenizer.TokenType.LET) || this.match(_tokenizer.TokenType.LBRACE) || this.match(_tokenizer.TokenType.LBRACK)) {
487 this.restoreLexerState(lexerState);
488 return true;
489 } else {
490 this.restoreLexerState(lexerState);
491 }
492 }
493 return false;
494 }
495 }, {
496 key: "parseStatementListItem",
497 value: function parseStatementListItem() {
498 if (this.eof()) throw this.createUnexpected(this.lookahead);
499
500 switch (this.lookahead.type) {
501 case _tokenizer.TokenType.FUNCTION:
502 return this.parseFunction({ isExpr: false, inDefault: false, allowGenerator: true });
503 case _tokenizer.TokenType.CLASS:
504 return this.parseClass({ isExpr: false, inDefault: false });
505 default:
506 if (this.lookaheadLexicalDeclaration()) {
507 var startLocation = this.getLocation();
508 return this.markLocation(this.parseVariableDeclarationStatement(), startLocation);
509 } else {
510 return this.parseStatement();
511 }
512 }
513 }
514 }, {
515 key: "parseStatement",
516 value: function parseStatement() {
517 var startLocation = this.getLocation();
518 var stmt = this.isolateCoverGrammar(this.parseStatementHelper);
519 return this.markLocation(stmt, startLocation);
520 }
521 }, {
522 key: "parseStatementHelper",
523 value: function parseStatementHelper() {
524 if (this.eof()) {
525 throw this.createUnexpected(this.lookahead);
526 }
527
528 switch (this.lookahead.type) {
529 case _tokenizer.TokenType.SEMICOLON:
530 return this.parseEmptyStatement();
531 case _tokenizer.TokenType.LBRACE:
532 return this.parseBlockStatement();
533 case _tokenizer.TokenType.LPAREN:
534 return this.parseExpressionStatement();
535 case _tokenizer.TokenType.BREAK:
536 return this.parseBreakStatement();
537 case _tokenizer.TokenType.CONTINUE:
538 return this.parseContinueStatement();
539 case _tokenizer.TokenType.DEBUGGER:
540 return this.parseDebuggerStatement();
541 case _tokenizer.TokenType.DO:
542 return this.parseDoWhileStatement();
543 case _tokenizer.TokenType.FOR:
544 return this.parseForStatement();
545 case _tokenizer.TokenType.IF:
546 return this.parseIfStatement();
547 case _tokenizer.TokenType.RETURN:
548 return this.parseReturnStatement();
549 case _tokenizer.TokenType.SWITCH:
550 return this.parseSwitchStatement();
551 case _tokenizer.TokenType.THROW:
552 return this.parseThrowStatement();
553 case _tokenizer.TokenType.TRY:
554 return this.parseTryStatement();
555 case _tokenizer.TokenType.VAR:
556 return this.parseVariableDeclarationStatement();
557 case _tokenizer.TokenType.WHILE:
558 return this.parseWhileStatement();
559 case _tokenizer.TokenType.WITH:
560 return this.parseWithStatement();
561 case _tokenizer.TokenType.FUNCTION:
562 case _tokenizer.TokenType.CLASS:
563 throw this.createUnexpected(this.lookahead);
564
565 default:
566 {
567 if (this.lookaheadLexicalDeclaration()) {
568 throw this.createUnexpected(this.lookahead);
569 }
570 var expr = this.parseExpression();
571 // 12.12 Labelled Statements;
572 if (expr.type === "IdentifierExpression" && this.eat(_tokenizer.TokenType.COLON)) {
573 var labeledBody = this.match(_tokenizer.TokenType.FUNCTION) ? this.parseFunction({ isExpr: false, inDefault: false, allowGenerator: false }) : this.parseStatement();
574 return { type: "LabeledStatement", label: expr.name, body: labeledBody };
575 } else {
576 this.consumeSemicolon();
577 return { type: "ExpressionStatement", expression: expr };
578 }
579 }
580 }
581 }
582 }, {
583 key: "parseEmptyStatement",
584 value: function parseEmptyStatement() {
585 this.lex();
586 return { type: "EmptyStatement" };
587 }
588 }, {
589 key: "parseBlockStatement",
590 value: function parseBlockStatement() {
591 return { type: "BlockStatement", block: this.parseBlock() };
592 }
593 }, {
594 key: "parseExpressionStatement",
595 value: function parseExpressionStatement() {
596 var expr = this.parseExpression();
597 this.consumeSemicolon();
598 return { type: "ExpressionStatement", expression: expr };
599 }
600 }, {
601 key: "parseBreakStatement",
602 value: function parseBreakStatement() {
603 this.lex();
604
605 // Catch the very common case first: immediately a semicolon (U+003B).
606 if (this.eat(_tokenizer.TokenType.SEMICOLON) || this.hasLineTerminatorBeforeNext) {
607 return { type: "BreakStatement", label: null };
608 }
609
610 var label = null;
611 if (this.match(_tokenizer.TokenType.IDENTIFIER) || this.match(_tokenizer.TokenType.YIELD) || this.match(_tokenizer.TokenType.LET)) {
612 label = this.parseIdentifier();
613 }
614
615 this.consumeSemicolon();
616
617 return { type: "BreakStatement", label: label };
618 }
619 }, {
620 key: "parseContinueStatement",
621 value: function parseContinueStatement() {
622 this.lex();
623
624 // Catch the very common case first: immediately a semicolon (U+003B).
625 if (this.eat(_tokenizer.TokenType.SEMICOLON) || this.hasLineTerminatorBeforeNext) {
626 return { type: "ContinueStatement", label: null };
627 }
628
629 var label = null;
630 if (this.match(_tokenizer.TokenType.IDENTIFIER) || this.match(_tokenizer.TokenType.YIELD) || this.match(_tokenizer.TokenType.LET)) {
631 label = this.parseIdentifier();
632 }
633
634 this.consumeSemicolon();
635
636 return { type: "ContinueStatement", label: label };
637 }
638 }, {
639 key: "parseDebuggerStatement",
640 value: function parseDebuggerStatement() {
641 this.lex();
642 this.consumeSemicolon();
643 return { type: "DebuggerStatement" };
644 }
645 }, {
646 key: "parseDoWhileStatement",
647 value: function parseDoWhileStatement() {
648 this.lex();
649 var body = this.parseStatement();
650 this.expect(_tokenizer.TokenType.WHILE);
651 this.expect(_tokenizer.TokenType.LPAREN);
652 var test = this.parseExpression();
653 this.expect(_tokenizer.TokenType.RPAREN);
654 this.eat(_tokenizer.TokenType.SEMICOLON);
655 return { type: "DoWhileStatement", body: body, test: test };
656 }
657 }, {
658 key: "parseForStatement",
659 value: function parseForStatement() {
660 this.lex();
661 this.expect(_tokenizer.TokenType.LPAREN);
662 var test = null;
663 var right = null;
664 if (this.eat(_tokenizer.TokenType.SEMICOLON)) {
665 if (!this.match(_tokenizer.TokenType.SEMICOLON)) {
666 test = this.parseExpression();
667 }
668 this.expect(_tokenizer.TokenType.SEMICOLON);
669 if (!this.match(_tokenizer.TokenType.RPAREN)) {
670 right = this.parseExpression();
671 }
672 return { type: "ForStatement", init: null, test: test, update: right, body: this.getIteratorStatementEpilogue() };
673 } else {
674 var startsWithLet = this.match(_tokenizer.TokenType.LET);
675 var isForDecl = this.lookaheadLexicalDeclaration();
676 var leftLocation = this.getLocation();
677 if (this.match(_tokenizer.TokenType.VAR) || isForDecl) {
678 var previousAllowIn = this.allowIn;
679 this.allowIn = false;
680 var init = this.parseVariableDeclaration(false);
681 this.allowIn = previousAllowIn;
682
683 if (init.declarators.length === 1 && (this.match(_tokenizer.TokenType.IN) || this.matchContextualKeyword("of"))) {
684 var type = undefined;
685
686 if (this.match(_tokenizer.TokenType.IN)) {
687 if (init.declarators[0].init != null) {
688 throw this.createError(_errors.ErrorMessages.INVALID_VAR_INIT_FOR_IN);
689 }
690 type = "ForInStatement";
691 this.lex();
692 right = this.parseExpression();
693 } else {
694 if (init.declarators[0].init != null) {
695 throw this.createError(_errors.ErrorMessages.INVALID_VAR_INIT_FOR_OF);
696 }
697 type = "ForOfStatement";
698 this.lex();
699 right = this.parseAssignmentExpression();
700 }
701
702 var body = this.getIteratorStatementEpilogue();
703
704 return { type: type, left: init, right: right, body: body };
705 } else {
706 this.expect(_tokenizer.TokenType.SEMICOLON);
707 if (!this.match(_tokenizer.TokenType.SEMICOLON)) {
708 test = this.parseExpression();
709 }
710 this.expect(_tokenizer.TokenType.SEMICOLON);
711 if (!this.match(_tokenizer.TokenType.RPAREN)) {
712 right = this.parseExpression();
713 }
714 return { type: "ForStatement", init: init, test: test, update: right, body: this.getIteratorStatementEpilogue() };
715 }
716 } else {
717 var previousAllowIn = this.allowIn;
718 this.allowIn = false;
719 var expr = this.inheritCoverGrammar(this.parseAssignmentExpressionOrBindingElement);
720 this.allowIn = previousAllowIn;
721
722 if (this.isAssignmentTarget && expr.type !== "AssignmentExpression" && (this.match(_tokenizer.TokenType.IN) || this.matchContextualKeyword("of"))) {
723 if (startsWithLet && this.matchContextualKeyword("of")) {
724 throw this.createError(_errors.ErrorMessages.INVALID_LHS_IN_FOR_OF);
725 }
726 var type = this.match(_tokenizer.TokenType.IN) ? "ForInStatement" : "ForOfStatement";
727
728 this.lex();
729 right = this.parseExpression();
730
731 return { type: type, left: this.transformDestructuring(expr), right: right, body: this.getIteratorStatementEpilogue() };
732 } else {
733 if (this.firstExprError) {
734 throw this.firstExprError;
735 }
736 while (this.eat(_tokenizer.TokenType.COMMA)) {
737 var rhs = this.parseAssignmentExpression();
738 expr = this.markLocation({ type: "BinaryExpression", left: expr, operator: ",", right: rhs }, leftLocation);
739 }
740 if (this.match(_tokenizer.TokenType.IN)) {
741 throw this.createError(_errors.ErrorMessages.INVALID_LHS_IN_FOR_IN);
742 }
743 if (this.matchContextualKeyword("of")) {
744 throw this.createError(_errors.ErrorMessages.INVALID_LHS_IN_FOR_OF);
745 }
746 this.expect(_tokenizer.TokenType.SEMICOLON);
747 if (!this.match(_tokenizer.TokenType.SEMICOLON)) {
748 test = this.parseExpression();
749 }
750 this.expect(_tokenizer.TokenType.SEMICOLON);
751 if (!this.match(_tokenizer.TokenType.RPAREN)) {
752 right = this.parseExpression();
753 }
754 return { type: "ForStatement", init: expr, test: test, update: right, body: this.getIteratorStatementEpilogue() };
755 }
756 }
757 }
758 }
759 }, {
760 key: "getIteratorStatementEpilogue",
761 value: function getIteratorStatementEpilogue() {
762 this.expect(_tokenizer.TokenType.RPAREN);
763 var body = this.parseStatement();
764 return body;
765 }
766 }, {
767 key: "parseIfStatementChild",
768 value: function parseIfStatementChild() {
769 return this.match(_tokenizer.TokenType.FUNCTION) ? this.parseFunction({ isExpr: false, inDefault: false, allowGenerator: false }) : this.parseStatement();
770 }
771 }, {
772 key: "parseIfStatement",
773 value: function parseIfStatement() {
774 this.lex();
775 this.expect(_tokenizer.TokenType.LPAREN);
776 var test = this.parseExpression();
777 this.expect(_tokenizer.TokenType.RPAREN);
778 var consequent = this.parseIfStatementChild();
779 var alternate = null;
780 if (this.eat(_tokenizer.TokenType.ELSE)) {
781 alternate = this.parseIfStatementChild();
782 }
783 return { type: "IfStatement", test: test, consequent: consequent, alternate: alternate };
784 }
785 }, {
786 key: "parseReturnStatement",
787 value: function parseReturnStatement() {
788 if (!this.inFunctionBody) {
789 throw this.createError(_errors.ErrorMessages.ILLEGAL_RETURN);
790 }
791
792 this.lex();
793
794 if (this.hasLineTerminatorBeforeNext) {
795 return { type: "ReturnStatement", expression: null };
796 }
797
798 var expression = null;
799 if (!this.match(_tokenizer.TokenType.SEMICOLON)) {
800 if (!this.match(_tokenizer.TokenType.RBRACE) && !this.eof()) {
801 expression = this.parseExpression();
802 }
803 }
804
805 this.consumeSemicolon();
806 return { type: "ReturnStatement", expression: expression };
807 }
808 }, {
809 key: "parseSwitchStatement",
810 value: function parseSwitchStatement() {
811 this.lex();
812 this.expect(_tokenizer.TokenType.LPAREN);
813 var discriminant = this.parseExpression();
814 this.expect(_tokenizer.TokenType.RPAREN);
815 this.expect(_tokenizer.TokenType.LBRACE);
816
817 if (this.eat(_tokenizer.TokenType.RBRACE)) {
818 return { type: "SwitchStatement", discriminant: discriminant, cases: [] };
819 }
820
821 var cases = this.parseSwitchCases();
822 if (this.match(_tokenizer.TokenType.DEFAULT)) {
823 var defaultCase = this.parseSwitchDefault();
824 var postDefaultCases = this.parseSwitchCases();
825 if (this.match(_tokenizer.TokenType.DEFAULT)) {
826 throw this.createError(_errors.ErrorMessages.MULTIPLE_DEFAULTS_IN_SWITCH);
827 }
828 this.expect(_tokenizer.TokenType.RBRACE);
829 return {
830 type: "SwitchStatementWithDefault",
831 discriminant: discriminant,
832 preDefaultCases: cases,
833 defaultCase: defaultCase,
834 postDefaultCases: postDefaultCases
835 };
836 } else {
837 this.expect(_tokenizer.TokenType.RBRACE);
838 return { type: "SwitchStatement", discriminant: discriminant, cases: cases };
839 }
840 }
841 }, {
842 key: "parseSwitchCases",
843 value: function parseSwitchCases() {
844 var result = [];
845 while (!(this.eof() || this.match(_tokenizer.TokenType.RBRACE) || this.match(_tokenizer.TokenType.DEFAULT))) {
846 result.push(this.parseSwitchCase());
847 }
848 return result;
849 }
850 }, {
851 key: "parseSwitchCase",
852 value: function parseSwitchCase() {
853 var startLocation = this.getLocation();
854 this.expect(_tokenizer.TokenType.CASE);
855 return this.markLocation({
856 type: "SwitchCase",
857 test: this.parseExpression(),
858 consequent: this.parseSwitchCaseBody()
859 }, startLocation);
860 }
861 }, {
862 key: "parseSwitchDefault",
863 value: function parseSwitchDefault() {
864 var startLocation = this.getLocation();
865 this.expect(_tokenizer.TokenType.DEFAULT);
866 return this.markLocation({ type: "SwitchDefault", consequent: this.parseSwitchCaseBody() }, startLocation);
867 }
868 }, {
869 key: "parseSwitchCaseBody",
870 value: function parseSwitchCaseBody() {
871 this.expect(_tokenizer.TokenType.COLON);
872 return this.parseStatementListInSwitchCaseBody();
873 }
874 }, {
875 key: "parseStatementListInSwitchCaseBody",
876 value: function parseStatementListInSwitchCaseBody() {
877 var result = [];
878 while (!(this.eof() || this.match(_tokenizer.TokenType.RBRACE) || this.match(_tokenizer.TokenType.DEFAULT) || this.match(_tokenizer.TokenType.CASE))) {
879 result.push(this.parseStatementListItem());
880 }
881 return result;
882 }
883 }, {
884 key: "parseThrowStatement",
885 value: function parseThrowStatement() {
886 var token = this.lex();
887 if (this.hasLineTerminatorBeforeNext) {
888 throw this.createErrorWithLocation(token, _errors.ErrorMessages.NEWLINE_AFTER_THROW);
889 }
890 var expression = this.parseExpression();
891 this.consumeSemicolon();
892 return { type: "ThrowStatement", expression: expression };
893 }
894 }, {
895 key: "parseTryStatement",
896 value: function parseTryStatement() {
897 this.lex();
898 var body = this.parseBlock();
899
900 if (this.match(_tokenizer.TokenType.CATCH)) {
901 var catchClause = this.parseCatchClause();
902 if (this.eat(_tokenizer.TokenType.FINALLY)) {
903 var finalizer = this.parseBlock();
904 return { type: "TryFinallyStatement", body: body, catchClause: catchClause, finalizer: finalizer };
905 }
906 return { type: "TryCatchStatement", body: body, catchClause: catchClause };
907 }
908
909 if (this.eat(_tokenizer.TokenType.FINALLY)) {
910 var finalizer = this.parseBlock();
911 return { type: "TryFinallyStatement", body: body, catchClause: null, finalizer: finalizer };
912 } else {
913 throw this.createError(_errors.ErrorMessages.NO_CATCH_OR_FINALLY);
914 }
915 }
916 }, {
917 key: "parseVariableDeclarationStatement",
918 value: function parseVariableDeclarationStatement() {
919 var declaration = this.parseVariableDeclaration(true);
920 this.consumeSemicolon();
921 return { type: "VariableDeclarationStatement", declaration: declaration };
922 }
923 }, {
924 key: "parseWhileStatement",
925 value: function parseWhileStatement() {
926 this.lex();
927 this.expect(_tokenizer.TokenType.LPAREN);
928 var test = this.parseExpression();
929 var body = this.getIteratorStatementEpilogue();
930 return { type: "WhileStatement", test: test, body: body };
931 }
932 }, {
933 key: "parseWithStatement",
934 value: function parseWithStatement() {
935 this.lex();
936 this.expect(_tokenizer.TokenType.LPAREN);
937 var object = this.parseExpression();
938 this.expect(_tokenizer.TokenType.RPAREN);
939 var body = this.parseStatement();
940 return { type: "WithStatement", object: object, body: body };
941 }
942 }, {
943 key: "parseCatchClause",
944 value: function parseCatchClause() {
945 var startLocation = this.getLocation();
946
947 this.lex();
948 this.expect(_tokenizer.TokenType.LPAREN);
949 if (this.match(_tokenizer.TokenType.RPAREN) || this.match(_tokenizer.TokenType.LPAREN)) {
950 throw this.createUnexpected(this.lookahead);
951 }
952 var binding = this.parseBindingTarget();
953 this.expect(_tokenizer.TokenType.RPAREN);
954 var body = this.parseBlock();
955
956 return this.markLocation({ type: "CatchClause", binding: binding, body: body }, startLocation);
957 }
958 }, {
959 key: "parseBlock",
960 value: function parseBlock() {
961 var startLocation = this.getLocation();
962 this.expect(_tokenizer.TokenType.LBRACE);
963 var body = [];
964 while (!this.match(_tokenizer.TokenType.RBRACE)) {
965 body.push(this.parseStatementListItem());
966 }
967 this.expect(_tokenizer.TokenType.RBRACE);
968 return this.markLocation({ type: "Block", statements: body }, startLocation);
969 }
970 }, {
971 key: "parseVariableDeclaration",
972 value: function parseVariableDeclaration(bindingPatternsMustHaveInit) {
973 var startLocation = this.getLocation();
974 var token = this.lex();
975
976 // preceded by this.match(TokenSubType.VAR) || this.match(TokenSubType.LET);
977 var kind = token.type === _tokenizer.TokenType.VAR ? "var" : token.type === _tokenizer.TokenType.CONST ? "const" : "let";
978 var declarators = this.parseVariableDeclaratorList(bindingPatternsMustHaveInit);
979 return this.markLocation({ type: "VariableDeclaration", kind: kind, declarators: declarators }, startLocation);
980 }
981 }, {
982 key: "parseVariableDeclaratorList",
983 value: function parseVariableDeclaratorList(bindingPatternsMustHaveInit) {
984 var result = [];
985 do {
986 result.push(this.parseVariableDeclarator(bindingPatternsMustHaveInit));
987 } while (this.eat(_tokenizer.TokenType.COMMA));
988 return result;
989 }
990 }, {
991 key: "parseVariableDeclarator",
992 value: function parseVariableDeclarator(bindingPatternsMustHaveInit) {
993 var startLocation = this.getLocation();
994
995 if (this.match(_tokenizer.TokenType.LPAREN)) {
996 throw this.createUnexpected(this.lookahead);
997 }
998
999 var binding = this.parseBindingTarget();
1000 if (bindingPatternsMustHaveInit && binding.type !== "BindingIdentifier" && !this.match(_tokenizer.TokenType.ASSIGN)) {
1001 this.expect(_tokenizer.TokenType.ASSIGN);
1002 }
1003
1004 var init = null;
1005 if (this.eat(_tokenizer.TokenType.ASSIGN)) {
1006 init = this.parseAssignmentExpression();
1007 }
1008
1009 return this.markLocation({ type: "VariableDeclarator", binding: binding, init: init }, startLocation);
1010 }
1011 }, {
1012 key: "isolateCoverGrammar",
1013 value: function isolateCoverGrammar(parser) {
1014 var oldIsBindingElement = this.isBindingElement,
1015 oldIsAssignmentTarget = this.isAssignmentTarget,
1016 oldFirstExprError = this.firstExprError,
1017 result;
1018 this.isBindingElement = this.isAssignmentTarget = true;
1019 this.firstExprError = null;
1020 result = parser.call(this);
1021 if (this.firstExprError !== null) {
1022 throw this.firstExprError;
1023 }
1024 this.isBindingElement = oldIsBindingElement;
1025 this.isAssignmentTarget = oldIsAssignmentTarget;
1026 this.firstExprError = oldFirstExprError;
1027 return result;
1028 }
1029 }, {
1030 key: "inheritCoverGrammar",
1031 value: function inheritCoverGrammar(parser) {
1032 var oldIsBindingElement = this.isBindingElement,
1033 oldIsAssignmentTarget = this.isAssignmentTarget,
1034 oldFirstExprError = this.firstExprError,
1035 result;
1036 this.isBindingElement = this.isAssignmentTarget = true;
1037 this.firstExprError = null;
1038 result = parser.call(this);
1039 this.isBindingElement = this.isBindingElement && oldIsBindingElement;
1040 this.isAssignmentTarget = this.isAssignmentTarget && oldIsAssignmentTarget;
1041 this.firstExprError = oldFirstExprError || this.firstExprError;
1042 return result;
1043 }
1044 }, {
1045 key: "parseExpression",
1046 value: function parseExpression() {
1047 var startLocation = this.getLocation();
1048
1049 var left = this.parseAssignmentExpression();
1050 if (this.match(_tokenizer.TokenType.COMMA)) {
1051 while (!this.eof()) {
1052 if (!this.match(_tokenizer.TokenType.COMMA)) break;
1053 this.lex();
1054 var right = this.parseAssignmentExpression();
1055 left = this.markLocation({ type: "BinaryExpression", left: left, operator: ",", right: right }, startLocation);
1056 }
1057 }
1058 return left;
1059 }
1060 }, {
1061 key: "parseArrowExpressionTail",
1062 value: function parseArrowExpressionTail(head, startLocation) {
1063 var arrow = this.expect(_tokenizer.TokenType.ARROW);
1064
1065 // Convert param list.
1066 var _head$params = head.params;
1067 var params = _head$params === undefined ? null : _head$params;
1068 var _head$rest = head.rest;
1069 var rest = _head$rest === undefined ? null : _head$rest;
1070
1071 if (head.type !== ARROW_EXPRESSION_PARAMS) {
1072 if (head.type === "IdentifierExpression") {
1073 params = [this.transformDestructuring(head)];
1074 } else {
1075 throw this.createUnexpected(arrow);
1076 }
1077 }
1078
1079 var paramsNode = this.markLocation({ type: "FormalParameters", items: params, rest: rest }, startLocation);
1080
1081 if (this.match(_tokenizer.TokenType.LBRACE)) {
1082 var previousYield = this.allowYieldExpression;
1083 this.allowYieldExpression = false;
1084 var body = this.parseFunctionBody();
1085 this.allowYieldExpression = previousYield;
1086 return this.markLocation({ type: "ArrowExpression", params: paramsNode, body: body }, startLocation);
1087 } else {
1088 var body = this.parseAssignmentExpression();
1089 return this.markLocation({ type: "ArrowExpression", params: paramsNode, body: body }, startLocation);
1090 }
1091 }
1092 }, {
1093 key: "parseAssignmentExpression",
1094 value: function parseAssignmentExpression() {
1095 return this.isolateCoverGrammar(this.parseAssignmentExpressionOrBindingElement);
1096 }
1097 }, {
1098 key: "parseAssignmentExpressionOrBindingElement",
1099 value: function parseAssignmentExpressionOrBindingElement() {
1100 var startLocation = this.getLocation();
1101
1102 if (this.allowYieldExpression && this.match(_tokenizer.TokenType.YIELD)) {
1103 this.isBindingElement = this.isAssignmentTarget = false;
1104 return this.parseYieldExpression();
1105 }
1106
1107 var expr = this.parseConditionalExpression();
1108
1109 if (!this.hasLineTerminatorBeforeNext && this.match(_tokenizer.TokenType.ARROW)) {
1110 this.isBindingElement = this.isAssignmentTarget = false;
1111 this.firstExprError = null;
1112 return this.parseArrowExpressionTail(expr, startLocation);
1113 }
1114
1115 var isAssignmentOperator = false;
1116 var operator = this.lookahead;
1117 switch (operator.type) {
1118 case _tokenizer.TokenType.ASSIGN_BIT_OR:
1119 case _tokenizer.TokenType.ASSIGN_BIT_XOR:
1120 case _tokenizer.TokenType.ASSIGN_BIT_AND:
1121 case _tokenizer.TokenType.ASSIGN_SHL:
1122 case _tokenizer.TokenType.ASSIGN_SHR:
1123 case _tokenizer.TokenType.ASSIGN_SHR_UNSIGNED:
1124 case _tokenizer.TokenType.ASSIGN_ADD:
1125 case _tokenizer.TokenType.ASSIGN_SUB:
1126 case _tokenizer.TokenType.ASSIGN_MUL:
1127 case _tokenizer.TokenType.ASSIGN_DIV:
1128 case _tokenizer.TokenType.ASSIGN_MOD:
1129 isAssignmentOperator = true;
1130 break;
1131 }
1132 if (isAssignmentOperator) {
1133 if (!this.isAssignmentTarget || !isValidSimpleAssignmentTarget(expr)) {
1134 throw this.createError(_errors.ErrorMessages.INVALID_LHS_IN_ASSIGNMENT);
1135 }
1136 expr = this.transformDestructuring(expr);
1137 } else if (operator.type === _tokenizer.TokenType.ASSIGN) {
1138 if (!this.isAssignmentTarget) {
1139 throw this.createError(_errors.ErrorMessages.INVALID_LHS_IN_ASSIGNMENT);
1140 }
1141 expr = this.transformDestructuring(expr);
1142 } else {
1143 return expr;
1144 }
1145
1146 this.lex();
1147 var rhs = this.parseAssignmentExpression();
1148
1149 this.firstExprError = null;
1150 return this.markLocation(operator.type === _tokenizer.TokenType.ASSIGN ? { type: "AssignmentExpression", binding: expr, expression: rhs } : { type: "CompoundAssignmentExpression", binding: expr, operator: operator.type.name, expression: rhs }, startLocation);
1151 }
1152 }, {
1153 key: "transformDestructuring",
1154 value: function transformDestructuring(node) {
1155 // istanbul ignore next
1156
1157 var _this = this;
1158
1159 switch (node.type) {
1160
1161 case "DataProperty":
1162 return copyLocation(node, {
1163 type: "BindingPropertyProperty",
1164 name: node.name,
1165 binding: this.transformDestructuringWithDefault(node.expression)
1166 });
1167 case "ShorthandProperty":
1168 return copyLocation(node, {
1169 type: "BindingPropertyIdentifier",
1170 binding: copyLocation(node, { type: "BindingIdentifier", name: node.name }),
1171 init: null
1172 });
1173
1174 case "ObjectExpression":
1175 return copyLocation(node, {
1176 type: "ObjectBinding",
1177 properties: node.properties.map(function (x) {
1178 return _this.transformDestructuring(x);
1179 })
1180 });
1181 case "ArrayExpression":
1182 var last = node.elements[node.elements.length - 1];
1183 if (last != null && last.type === "SpreadElement") {
1184 return copyLocation(node, {
1185 type: "ArrayBinding",
1186 elements: node.elements.slice(0, -1).map(function (e) {
1187 return e && _this.transformDestructuringWithDefault(e);
1188 }),
1189 restElement: copyLocation(last.expression, this.transformDestructuring(last.expression))
1190 });
1191 } else {
1192 return copyLocation(node, {
1193 type: "ArrayBinding",
1194 elements: node.elements.map(function (e) {
1195 return e && _this.transformDestructuringWithDefault(e);
1196 }),
1197 restElement: null
1198 });
1199 }
1200 /* istanbul ignore next */
1201 break;
1202 case "IdentifierExpression":
1203 return copyLocation(node, { type: "BindingIdentifier", name: node.name });
1204 case "AssignmentExpression":
1205 throw this.createError(_errors.ErrorMessages.INVALID_LHS_IN_ASSIGNMENT);
1206
1207 case "StaticPropertyName":
1208 return copyLocation(node, { type: "BindingIdentifier", name: node.value });
1209
1210 case "ComputedMemberExpression":
1211 case "StaticMemberExpression":
1212 case "ArrayBinding":
1213 case "BindingIdentifier":
1214 case "BindingPropertyIdentifier":
1215 case "BindingPropertyProperty":
1216 case "BindingWithDefault":
1217 case "ObjectBinding":
1218 return node;
1219 }
1220
1221 // istanbul ignore next
1222 throw new Error("Not reached");
1223 }
1224 }, {
1225 key: "transformDestructuringWithDefault",
1226 value: function transformDestructuringWithDefault(node) {
1227 switch (node.type) {
1228 case "AssignmentExpression":
1229 return copyLocation(node, {
1230 type: "BindingWithDefault",
1231 binding: this.transformDestructuring(node.binding),
1232 init: node.expression
1233 });
1234 }
1235 return this.transformDestructuring(node);
1236 }
1237 }, {
1238 key: "lookaheadAssignmentExpression",
1239 value: function lookaheadAssignmentExpression() {
1240 switch (this.lookahead.type) {
1241 case _tokenizer.TokenType.ADD:
1242 case _tokenizer.TokenType.ASSIGN_DIV:
1243 case _tokenizer.TokenType.CLASS:
1244 case _tokenizer.TokenType.DEC:
1245 case _tokenizer.TokenType.DIV:
1246 case _tokenizer.TokenType.FALSE:
1247 case _tokenizer.TokenType.FUNCTION:
1248 case _tokenizer.TokenType.IDENTIFIER:
1249 case _tokenizer.TokenType.INC:
1250 case _tokenizer.TokenType.LET:
1251 case _tokenizer.TokenType.LBRACE:
1252 case _tokenizer.TokenType.LBRACK:
1253 case _tokenizer.TokenType.LPAREN:
1254 case _tokenizer.TokenType.NEW:
1255 case _tokenizer.TokenType.NOT:
1256 case _tokenizer.TokenType.NULL:
1257 case _tokenizer.TokenType.NUMBER:
1258 case _tokenizer.TokenType.STRING:
1259 case _tokenizer.TokenType.SUB:
1260 case _tokenizer.TokenType.SUPER:
1261 case _tokenizer.TokenType.THIS:
1262 case _tokenizer.TokenType.TRUE:
1263 case _tokenizer.TokenType.YIELD:
1264 case _tokenizer.TokenType.TEMPLATE:
1265 return true;
1266 }
1267 return false;
1268 }
1269 }, {
1270 key: "parseYieldExpression",
1271 value: function parseYieldExpression() {
1272 var startLocation = this.getLocation();
1273
1274 this.lex();
1275 if (this.hasLineTerminatorBeforeNext) {
1276 return this.markLocation({ type: "YieldExpression", expression: null }, startLocation);
1277 }
1278 var isGenerator = !!this.eat(_tokenizer.TokenType.MUL);
1279 var expr = null;
1280 if (isGenerator || this.lookaheadAssignmentExpression()) {
1281 expr = this.parseAssignmentExpression();
1282 }
1283 var type = isGenerator ? "YieldGeneratorExpression" : "YieldExpression";
1284 return this.markLocation({ type: type, expression: expr }, startLocation);
1285 }
1286 }, {
1287 key: "parseConditionalExpression",
1288 value: function parseConditionalExpression() {
1289 var startLocation = this.getLocation();
1290 var test = this.parseBinaryExpression();
1291 if (this.firstExprError) return test;
1292 if (this.eat(_tokenizer.TokenType.CONDITIONAL)) {
1293 this.isBindingElement = this.isAssignmentTarget = false;
1294 var previousAllowIn = this.allowIn;
1295 this.allowIn = true;
1296 var consequent = this.isolateCoverGrammar(this.parseAssignmentExpression);
1297 this.allowIn = previousAllowIn;
1298 this.expect(_tokenizer.TokenType.COLON);
1299 var alternate = this.isolateCoverGrammar(this.parseAssignmentExpression);
1300 return this.markLocation({ type: "ConditionalExpression", test: test, consequent: consequent, alternate: alternate }, startLocation);
1301 }
1302 return test;
1303 }
1304 }, {
1305 key: "isBinaryOperator",
1306 value: function isBinaryOperator(type) {
1307 switch (type) {
1308 case _tokenizer.TokenType.OR:
1309 case _tokenizer.TokenType.AND:
1310 case _tokenizer.TokenType.BIT_OR:
1311 case _tokenizer.TokenType.BIT_XOR:
1312 case _tokenizer.TokenType.BIT_AND:
1313 case _tokenizer.TokenType.EQ:
1314 case _tokenizer.TokenType.NE:
1315 case _tokenizer.TokenType.EQ_STRICT:
1316 case _tokenizer.TokenType.NE_STRICT:
1317 case _tokenizer.TokenType.LT:
1318 case _tokenizer.TokenType.GT:
1319 case _tokenizer.TokenType.LTE:
1320 case _tokenizer.TokenType.GTE:
1321 case _tokenizer.TokenType.INSTANCEOF:
1322 case _tokenizer.TokenType.SHL:
1323 case _tokenizer.TokenType.SHR:
1324 case _tokenizer.TokenType.SHR_UNSIGNED:
1325 case _tokenizer.TokenType.ADD:
1326 case _tokenizer.TokenType.SUB:
1327 case _tokenizer.TokenType.MUL:
1328 case _tokenizer.TokenType.DIV:
1329 case _tokenizer.TokenType.MOD:
1330 return true;
1331 case _tokenizer.TokenType.IN:
1332 return this.allowIn;
1333 default:
1334 return false;
1335 }
1336 }
1337 }, {
1338 key: "parseBinaryExpression",
1339 value: function parseBinaryExpression() {
1340 // istanbul ignore next
1341
1342 var _this2 = this;
1343
1344 var startLocation = this.getLocation();
1345 var left = this.parseUnaryExpression();
1346 if (this.firstExprError) {
1347 return left;
1348 }
1349
1350 var operator = this.lookahead.type;
1351
1352 if (!this.isBinaryOperator(operator)) return left;
1353
1354 this.isBindingElement = this.isAssignmentTarget = false;
1355
1356 this.lex();
1357 var stack = [];
1358 stack.push({ startLocation: startLocation, left: left, operator: operator, precedence: BinaryPrecedence[operator.name] });
1359 startLocation = this.getLocation();
1360 var right = this.isolateCoverGrammar(this.parseUnaryExpression);
1361 operator = this.lookahead.type;
1362 while (this.isBinaryOperator(operator)) {
1363 var precedence = BinaryPrecedence[operator.name];
1364 // Reduce: make a binary expression from the three topmost entries.
1365 while (stack.length && precedence <= stack[stack.length - 1].precedence) {
1366 var stackItem = stack[stack.length - 1];
1367 var stackOperator = stackItem.operator;
1368 left = stackItem.left;
1369 stack.pop();
1370 startLocation = stackItem.startLocation;
1371 right = this.markLocation({ type: "BinaryExpression", left: left, operator: stackOperator.name, right: right }, startLocation);
1372 }
1373
1374 this.lex();
1375 stack.push({ startLocation: startLocation, left: right, operator: operator, precedence: precedence });
1376
1377 startLocation = this.getLocation();
1378 right = this.isolateCoverGrammar(this.parseUnaryExpression);
1379 operator = this.lookahead.type;
1380 }
1381
1382 // Final reduce to clean-up the stack.
1383 return stack.reduceRight(function (expr, stackItem) {
1384 return _this2.markLocation({
1385 type: "BinaryExpression",
1386 left: stackItem.left,
1387 operator: stackItem.operator.name,
1388 right: expr
1389 }, stackItem.startLocation);
1390 }, right);
1391 }
1392 }, {
1393 key: "parseUnaryExpression",
1394 value: function parseUnaryExpression() {
1395 if (this.lookahead.type.klass !== _tokenizer.TokenClass.Punctuator && this.lookahead.type.klass !== _tokenizer.TokenClass.Keyword) {
1396 return this.parseUpdateExpression();
1397 }
1398 var startLocation = this.getLocation();
1399 var operator = this.lookahead;
1400 if (!isPrefixOperator(operator)) {
1401 return this.parseUpdateExpression();
1402 }
1403
1404 this.lex();
1405 this.isBindingElement = this.isAssignmentTarget = false;
1406
1407 var node = undefined;
1408 if (isUpdateOperator(operator)) {
1409 var operandStartLocation = this.getLocation();
1410 var operand = this.isolateCoverGrammar(this.parseUnaryExpression);
1411 if (operand.type === "IdentifierExpression") {
1412 operand.type = "BindingIdentifier";
1413 } else if (!isValidSimpleAssignmentTarget(operand)) {
1414 throw this.createErrorWithLocation(operandStartLocation, _errors.ErrorMessages.INVALID_UPDATE_OPERAND);
1415 }
1416 node = { type: "UpdateExpression", isPrefix: true, operator: operator.value, operand: operand };
1417 } else {
1418 var operand = this.isolateCoverGrammar(this.parseUnaryExpression);
1419 node = { type: "UnaryExpression", operator: operator.value, operand: operand };
1420 }
1421
1422 return this.markLocation(node, startLocation);
1423 }
1424 }, {
1425 key: "parseUpdateExpression",
1426 value: function parseUpdateExpression() {
1427 var startLocation = this.getLocation();
1428
1429 var operand = this.parseLeftHandSideExpression({ allowCall: true });
1430 if (this.firstExprError || this.hasLineTerminatorBeforeNext) return operand;
1431
1432 var operator = this.lookahead;
1433 if (!isUpdateOperator(operator)) return operand;
1434 this.lex();
1435 this.isBindingElement = this.isAssignmentTarget = false;
1436 if (operand.type === "IdentifierExpression") {
1437 operand.type = "BindingIdentifier";
1438 } else if (!isValidSimpleAssignmentTarget(operand)) {
1439 throw this.createErrorWithLocation(startLocation, _errors.ErrorMessages.INVALID_UPDATE_OPERAND);
1440 }
1441
1442 return this.markLocation({ type: "UpdateExpression", isPrefix: false, operator: operator.value, operand: operand }, startLocation);
1443 }
1444 }, {
1445 key: "parseLeftHandSideExpression",
1446 value: function parseLeftHandSideExpression(_ref) {
1447 var allowCall = _ref.allowCall;
1448
1449 var startLocation = this.getLocation();
1450 var previousAllowIn = this.allowIn;
1451 this.allowIn = allowCall;
1452
1453 var expr = undefined,
1454 token = this.lookahead;
1455
1456 if (this.eat(_tokenizer.TokenType.SUPER)) {
1457 this.isBindingElement = false;
1458 this.isAssignmentTarget = false;
1459 expr = this.markLocation({ type: "Super" }, startLocation);
1460 if (this.match(_tokenizer.TokenType.LPAREN)) {
1461 if (allowCall) {
1462 expr = this.markLocation({
1463 type: "CallExpression",
1464 callee: expr,
1465 arguments: this.parseArgumentList()
1466 }, startLocation);
1467 } else {
1468 throw this.createUnexpected(token);
1469 }
1470 } else if (this.match(_tokenizer.TokenType.LBRACK)) {
1471 expr = this.markLocation({
1472 type: "ComputedMemberExpression",
1473 object: expr,
1474 expression: this.parseComputedMember()
1475 }, startLocation);
1476 this.isAssignmentTarget = true;
1477 } else if (this.match(_tokenizer.TokenType.PERIOD)) {
1478 expr = this.markLocation({
1479 type: "StaticMemberExpression",
1480 object: expr,
1481 property: this.parseStaticMember()
1482 }, startLocation);
1483 this.isAssignmentTarget = true;
1484 } else {
1485 throw this.createUnexpected(token);
1486 }
1487 } else if (this.match(_tokenizer.TokenType.NEW)) {
1488 this.isBindingElement = this.isAssignmentTarget = false;
1489 expr = this.parseNewExpression();
1490 } else {
1491 expr = this.parsePrimaryExpression();
1492 if (this.firstExprError) {
1493 return expr;
1494 }
1495 }
1496
1497 while (true) {
1498 if (allowCall && this.match(_tokenizer.TokenType.LPAREN)) {
1499 this.isBindingElement = this.isAssignmentTarget = false;
1500 expr = this.markLocation({
1501 type: "CallExpression",
1502 callee: expr,
1503 arguments: this.parseArgumentList()
1504 }, startLocation);
1505 } else if (this.match(_tokenizer.TokenType.LBRACK)) {
1506 this.isBindingElement = false;
1507 this.isAssignmentTarget = true;
1508 expr = this.markLocation({
1509 type: "ComputedMemberExpression",
1510 object: expr,
1511 expression: this.parseComputedMember()
1512 }, startLocation);
1513 } else if (this.match(_tokenizer.TokenType.PERIOD)) {
1514 this.isBindingElement = false;
1515 this.isAssignmentTarget = true;
1516 expr = this.markLocation({
1517 type: "StaticMemberExpression",
1518 object: expr,
1519 property: this.parseStaticMember()
1520 }, startLocation);
1521 } else if (this.match(_tokenizer.TokenType.TEMPLATE)) {
1522 this.isBindingElement = this.isAssignmentTarget = false;
1523 expr = this.markLocation({
1524 type: "TemplateExpression",
1525 tag: expr,
1526 elements: this.parseTemplateElements()
1527 }, startLocation);
1528 } else {
1529 break;
1530 }
1531 }
1532
1533 this.allowIn = previousAllowIn;
1534
1535 return expr;
1536 }
1537 }, {
1538 key: "parseTemplateElements",
1539 value: function parseTemplateElements() {
1540 var startLocation = this.getLocation();
1541 var token = this.lookahead;
1542 if (token.tail) {
1543 this.lex();
1544 return [this.markLocation({ type: "TemplateElement", rawValue: token.slice.text.slice(1, -1) }, startLocation)];
1545 }
1546 var result = [this.markLocation({ type: "TemplateElement", rawValue: this.lex().slice.text.slice(1, -2) }, startLocation)];
1547 while (true) {
1548 result.push(this.parseExpression());
1549 if (!this.match(_tokenizer.TokenType.RBRACE)) {
1550 throw this.createILLEGAL();
1551 }
1552 this.index = this.startIndex;
1553 this.line = this.startLine;
1554 this.lineStart = this.startLineStart;
1555 this.lookahead = this.scanTemplateElement();
1556 startLocation = this.getLocation();
1557 token = this.lex();
1558 if (token.tail) {
1559 result.push(this.markLocation({ type: "TemplateElement", rawValue: token.slice.text.slice(1, -1) }, startLocation));
1560 return result;
1561 } else {
1562 result.push(this.markLocation({ type: "TemplateElement", rawValue: token.slice.text.slice(1, -2) }, startLocation));
1563 }
1564 }
1565 }
1566 }, {
1567 key: "parseStaticMember",
1568 value: function parseStaticMember() {
1569 this.lex();
1570 if (!this.lookahead.type.klass.isIdentifierName) {
1571 throw this.createUnexpected(this.lookahead);
1572 } else {
1573 return this.lex().value;
1574 }
1575 }
1576 }, {
1577 key: "parseComputedMember",
1578 value: function parseComputedMember() {
1579 this.lex();
1580 var expr = this.parseExpression();
1581 this.expect(_tokenizer.TokenType.RBRACK);
1582 return expr;
1583 }
1584 }, {
1585 key: "parseNewExpression",
1586 value: function parseNewExpression() {
1587 // istanbul ignore next
1588
1589 var _this3 = this;
1590
1591 var startLocation = this.getLocation();
1592 this.lex();
1593 if (this.eat(_tokenizer.TokenType.PERIOD)) {
1594 var ident = this.expect(_tokenizer.TokenType.IDENTIFIER);
1595 if (ident.value !== "target") {
1596 throw this.createUnexpected(ident);
1597 }
1598 return this.markLocation({ type: "NewTargetExpression" }, startLocation);
1599 }
1600 var callee = this.isolateCoverGrammar(function () {
1601 return _this3.parseLeftHandSideExpression({ allowCall: false });
1602 });
1603 return this.markLocation({
1604 type: "NewExpression",
1605 callee: callee,
1606 arguments: this.match(_tokenizer.TokenType.LPAREN) ? this.parseArgumentList() : []
1607 }, startLocation);
1608 }
1609 }, {
1610 key: "parsePrimaryExpression",
1611 value: function parsePrimaryExpression() {
1612 if (this.match(_tokenizer.TokenType.LPAREN)) {
1613 return this.parseGroupExpression();
1614 }
1615
1616 var startLocation = this.getLocation();
1617
1618 switch (this.lookahead.type) {
1619 case _tokenizer.TokenType.IDENTIFIER:
1620 case _tokenizer.TokenType.YIELD:
1621 case _tokenizer.TokenType.LET:
1622 return this.markLocation({ type: "IdentifierExpression", name: this.parseIdentifier() }, startLocation);
1623 case _tokenizer.TokenType.STRING:
1624 this.isBindingElement = this.isAssignmentTarget = false;
1625 return this.parseStringLiteral();
1626 case _tokenizer.TokenType.NUMBER:
1627 this.isBindingElement = this.isAssignmentTarget = false;
1628 return this.parseNumericLiteral();
1629 case _tokenizer.TokenType.THIS:
1630 this.lex();
1631 this.isBindingElement = this.isAssignmentTarget = false;
1632 return this.markLocation({ type: "ThisExpression" }, startLocation);
1633 case _tokenizer.TokenType.FUNCTION:
1634 this.isBindingElement = this.isAssignmentTarget = false;
1635 return this.markLocation(this.parseFunction({ isExpr: true, inDefault: false, allowGenerator: true }), startLocation);
1636 case _tokenizer.TokenType.TRUE:
1637 this.lex();
1638 this.isBindingElement = this.isAssignmentTarget = false;
1639 return this.markLocation({ type: "LiteralBooleanExpression", value: true }, startLocation);
1640 case _tokenizer.TokenType.FALSE:
1641 this.lex();
1642 this.isBindingElement = this.isAssignmentTarget = false;
1643 return this.markLocation({ type: "LiteralBooleanExpression", value: false }, startLocation);
1644 case _tokenizer.TokenType.NULL:
1645 this.lex();
1646 this.isBindingElement = this.isAssignmentTarget = false;
1647 return this.markLocation({ type: "LiteralNullExpression" }, startLocation);
1648 case _tokenizer.TokenType.LBRACK:
1649 return this.parseArrayExpression();
1650 case _tokenizer.TokenType.LBRACE:
1651 return this.parseObjectExpression();
1652 case _tokenizer.TokenType.TEMPLATE:
1653 this.isBindingElement = this.isAssignmentTarget = false;
1654 return this.markLocation({ type: "TemplateExpression", tag: null, elements: this.parseTemplateElements() }, startLocation);
1655 case _tokenizer.TokenType.DIV:
1656 case _tokenizer.TokenType.ASSIGN_DIV:
1657 this.isBindingElement = this.isAssignmentTarget = false;
1658 this.lookahead = this.scanRegExp(this.match(_tokenizer.TokenType.DIV) ? "/" : "/=");
1659 var token = this.lex();
1660 var lastSlash = token.value.lastIndexOf("/");
1661 var pattern = token.value.slice(1, lastSlash);
1662 var flags = token.value.slice(lastSlash + 1);
1663 return this.markLocation({ type: "LiteralRegExpExpression", pattern: pattern, flags: flags }, startLocation);
1664 case _tokenizer.TokenType.CLASS:
1665 this.isBindingElement = this.isAssignmentTarget = false;
1666 return this.parseClass({ isExpr: true, inDefault: false });
1667 default:
1668 throw this.createUnexpected(this.lookahead);
1669 }
1670 }
1671 }, {
1672 key: "parseNumericLiteral",
1673 value: function parseNumericLiteral() {
1674 var startLocation = this.getLocation();
1675 var token = this.lex();
1676 if (token.octal && this.strict) {
1677 if (token.noctal) {
1678 throw this.createErrorWithLocation(startLocation, "Unexpected noctal integer literal");
1679 } else {
1680 throw this.createErrorWithLocation(startLocation, "Unexpected legacy octal integer literal");
1681 }
1682 }
1683 var node = token.value === 1 / 0 ? { type: "LiteralInfinityExpression" } : { type: "LiteralNumericExpression", value: token.value };
1684 return this.markLocation(node, startLocation);
1685 }
1686 }, {
1687 key: "parseStringLiteral",
1688 value: function parseStringLiteral() {
1689 var startLocation = this.getLocation();
1690 var token = this.lex();
1691 if (token.octal != null && this.strict) {
1692 throw this.createErrorWithLocation(startLocation, "Unexpected legacy octal escape sequence: \\" + token.octal);
1693 }
1694 return this.markLocation({ type: "LiteralStringExpression", value: token.str }, startLocation);
1695 }
1696 }, {
1697 key: "parseIdentifierName",
1698 value: function parseIdentifierName() {
1699 if (this.lookahead.type.klass.isIdentifierName) {
1700 return this.lex().value;
1701 } else {
1702 throw this.createUnexpected(this.lookahead);
1703 }
1704 }
1705 }, {
1706 key: "parseBindingIdentifier",
1707 value: function parseBindingIdentifier() {
1708 var startLocation = this.getLocation();
1709 return this.markLocation({ type: "BindingIdentifier", name: this.parseIdentifier() }, startLocation);
1710 }
1711 }, {
1712 key: "parseIdentifier",
1713 value: function parseIdentifier() {
1714 var type = this.lookahead.type;
1715 if (type === _tokenizer.TokenType.IDENTIFIER || type === _tokenizer.TokenType.YIELD && !this.allowYieldExpression || type === _tokenizer.TokenType.LET) {
1716 return this.lex().value;
1717 }
1718 throw this.createUnexpected(this.lookahead);
1719 }
1720 }, {
1721 key: "parseArgumentList",
1722 value: function parseArgumentList() {
1723 this.lex();
1724 var args = this.parseArguments();
1725 this.expect(_tokenizer.TokenType.RPAREN);
1726 return args;
1727 }
1728 }, {
1729 key: "parseArguments",
1730 value: function parseArguments() {
1731 var result = [];
1732 while (true) {
1733 if (this.match(_tokenizer.TokenType.RPAREN) || this.eof()) {
1734 return result;
1735 }
1736 var arg = undefined;
1737 if (this.eat(_tokenizer.TokenType.ELLIPSIS)) {
1738 var startLocation = this.getLocation();
1739 arg = this.markLocation({ type: "SpreadElement", expression: this.parseAssignmentExpression() }, startLocation);
1740 } else {
1741 arg = this.parseAssignmentExpression();
1742 }
1743 result.push(arg);
1744 if (!this.eat(_tokenizer.TokenType.COMMA)) break;
1745 }
1746 return result;
1747 }
1748
1749 // 11.2 Left-Hand-Side Expressions;
1750
1751 }, {
1752 key: "ensureArrow",
1753 value: function ensureArrow() {
1754 if (this.hasLineTerminatorBeforeNext) {
1755 throw this.createError(_errors.ErrorMessages.UNEXPECTED_LINE_TERMINATOR);
1756 }
1757 if (!this.match(_tokenizer.TokenType.ARROW)) {
1758 this.expect(_tokenizer.TokenType.ARROW);
1759 }
1760 }
1761 }, {
1762 key: "parseGroupExpression",
1763 value: function parseGroupExpression() {
1764 // At this point, we need to parse 3 things:
1765 // 1. Group expression
1766 // 2. Assignment target of assignment expression
1767 // 3. Parameter list of arrow function
1768 var rest = null;
1769 var start = this.expect(_tokenizer.TokenType.LPAREN);
1770 if (this.eat(_tokenizer.TokenType.RPAREN)) {
1771 this.ensureArrow();
1772 this.isBindingElement = this.isAssignmentTarget = false;
1773 return {
1774 type: ARROW_EXPRESSION_PARAMS,
1775 params: [],
1776 rest: null
1777 };
1778 } else if (this.eat(_tokenizer.TokenType.ELLIPSIS)) {
1779 rest = this.parseBindingIdentifier();
1780 this.expect(_tokenizer.TokenType.RPAREN);
1781 this.ensureArrow();
1782 this.isBindingElement = this.isAssignmentTarget = false;
1783 return {
1784 type: ARROW_EXPRESSION_PARAMS,
1785 params: [],
1786 rest: rest
1787 };
1788 }
1789
1790 var startLocation = this.getLocation();
1791 var group = this.inheritCoverGrammar(this.parseAssignmentExpressionOrBindingElement);
1792
1793 var params = this.isBindingElement ? [this.transformDestructuringWithDefault(group)] : null;
1794
1795 while (this.eat(_tokenizer.TokenType.COMMA)) {
1796 this.isAssignmentTarget = false;
1797 if (this.match(_tokenizer.TokenType.ELLIPSIS)) {
1798 if (!this.isBindingElement) {
1799 throw this.createUnexpected(this.lookahead);
1800 }
1801 this.lex();
1802 rest = this.parseBindingIdentifier();
1803 break;
1804 }
1805
1806 if (!group) {
1807 // Can be only binding elements.
1808 var binding = this.parseBindingElement();
1809 params.push(binding);
1810 } else {
1811 // Can be either binding element or assignment target.
1812 var expr = this.inheritCoverGrammar(this.parseAssignmentExpressionOrBindingElement);
1813 if (!this.isBindingElement) {
1814 params = null;
1815 } else {
1816 params.push(this.transformDestructuringWithDefault(expr));
1817 }
1818
1819 if (this.firstExprError) {
1820 group = null;
1821 } else {
1822 group = this.markLocation({
1823 type: "BinaryExpression",
1824 left: group,
1825 operator: ",",
1826 right: expr
1827 }, startLocation);
1828 }
1829 }
1830 }
1831
1832 this.expect(_tokenizer.TokenType.RPAREN);
1833
1834 if (!this.hasLineTerminatorBeforeNext && this.match(_tokenizer.TokenType.ARROW)) {
1835 if (!this.isBindingElement) {
1836 throw this.createErrorWithLocation(start, _errors.ErrorMessages.ILLEGAL_ARROW_FUNCTION_PARAMS);
1837 }
1838
1839 this.isBindingElement = false;
1840 return { type: ARROW_EXPRESSION_PARAMS, params: params, rest: rest };
1841 } else {
1842 // Ensure assignment pattern:
1843 if (rest) {
1844 this.ensureArrow();
1845 }
1846 this.isBindingElement = false;
1847 return group;
1848 }
1849 }
1850 }, {
1851 key: "parseArrayExpression",
1852 value: function parseArrayExpression() {
1853 var startLocation = this.getLocation();
1854
1855 this.lex();
1856
1857 var exprs = [];
1858
1859 while (true) {
1860 if (this.match(_tokenizer.TokenType.RBRACK)) {
1861 break;
1862 }
1863 if (this.eat(_tokenizer.TokenType.COMMA)) {
1864 exprs.push(null);
1865 } else {
1866 var elementLocation = this.getLocation();
1867 var expr = undefined;
1868 if (this.eat(_tokenizer.TokenType.ELLIPSIS)) {
1869 // Spread/Rest element
1870 expr = this.inheritCoverGrammar(this.parseAssignmentExpressionOrBindingElement);
1871 if (!this.isAssignmentTarget && this.firstExprError) {
1872 throw this.firstExprError;
1873 }
1874 expr = this.markLocation({ type: "SpreadElement", expression: expr }, elementLocation);
1875 if (!this.match(_tokenizer.TokenType.RBRACK)) {
1876 this.isBindingElement = this.isAssignmentTarget = false;
1877 }
1878 } else {
1879 expr = this.inheritCoverGrammar(this.parseAssignmentExpressionOrBindingElement);
1880 if (!this.isAssignmentTarget && this.firstExprError) {
1881 throw this.firstExprError;
1882 }
1883 }
1884 exprs.push(expr);
1885
1886 if (!this.match(_tokenizer.TokenType.RBRACK)) {
1887 this.expect(_tokenizer.TokenType.COMMA);
1888 }
1889 }
1890 }
1891
1892 this.expect(_tokenizer.TokenType.RBRACK);
1893
1894 return this.markLocation({ type: "ArrayExpression", elements: exprs }, startLocation);
1895 }
1896 }, {
1897 key: "parseObjectExpression",
1898 value: function parseObjectExpression() {
1899 var startLocation = this.getLocation();
1900
1901 this.lex();
1902
1903 var properties = [];
1904 while (!this.match(_tokenizer.TokenType.RBRACE)) {
1905 var property = this.inheritCoverGrammar(this.parsePropertyDefinition);
1906 properties.push(property);
1907 if (!this.match(_tokenizer.TokenType.RBRACE)) {
1908 this.expect(_tokenizer.TokenType.COMMA);
1909 }
1910 }
1911 this.expect(_tokenizer.TokenType.RBRACE);
1912 return this.markLocation({ type: "ObjectExpression", properties: properties }, startLocation);
1913 }
1914 }, {
1915 key: "parsePropertyDefinition",
1916 value: function parsePropertyDefinition() {
1917 var startLocation = this.getLocation();
1918 var token = this.lookahead;
1919
1920 var _parseMethodDefinition = this.parseMethodDefinition();
1921
1922 var methodOrKey = _parseMethodDefinition.methodOrKey;
1923 var kind = _parseMethodDefinition.kind;
1924
1925 switch (kind) {
1926 case "method":
1927 this.isBindingElement = this.isAssignmentTarget = false;
1928 return methodOrKey;
1929 case "identifier":
1930 if (this.eat(_tokenizer.TokenType.ASSIGN)) {
1931 // CoverInitializedName
1932 var init = this.isolateCoverGrammar(this.parseAssignmentExpression);
1933 this.firstExprError = this.createErrorWithLocation(startLocation, _errors.ErrorMessages.ILLEGAL_PROPERTY);
1934 return this.markLocation({
1935 type: "BindingPropertyIdentifier",
1936 binding: this.transformDestructuring(methodOrKey),
1937 init: init
1938 }, startLocation);
1939 } else if (!this.match(_tokenizer.TokenType.COLON)) {
1940 if (token.type !== _tokenizer.TokenType.IDENTIFIER && token.type !== _tokenizer.TokenType.YIELD && token.type !== _tokenizer.TokenType.LET) {
1941 throw this.createUnexpected(token);
1942 }
1943 return this.markLocation({ type: "ShorthandProperty", name: methodOrKey.value }, startLocation);
1944 }
1945 }
1946
1947 // DataProperty
1948 this.expect(_tokenizer.TokenType.COLON);
1949
1950 var expr = this.inheritCoverGrammar(this.parseAssignmentExpressionOrBindingElement);
1951 return this.markLocation({ type: "DataProperty", name: methodOrKey, expression: expr }, startLocation);
1952 }
1953 }, {
1954 key: "parsePropertyName",
1955 value: function parsePropertyName() {
1956 // PropertyName[Yield,GeneratorParameter]:
1957 var token = this.lookahead;
1958 var startLocation = this.getLocation();
1959
1960 if (this.eof()) {
1961 throw this.createUnexpected(token);
1962 }
1963
1964 switch (token.type) {
1965 case _tokenizer.TokenType.STRING:
1966 return {
1967 name: this.markLocation({
1968 type: "StaticPropertyName",
1969 value: this.parseStringLiteral().value
1970 }, startLocation),
1971 binding: null
1972 };
1973 case _tokenizer.TokenType.NUMBER:
1974 var numLiteral = this.parseNumericLiteral();
1975 return {
1976 name: this.markLocation({
1977 type: "StaticPropertyName",
1978 value: "" + (numLiteral.type === "LiteralInfinityExpression" ? 1 / 0 : numLiteral.value)
1979 }, startLocation),
1980 binding: null
1981 };
1982 case _tokenizer.TokenType.LBRACK:
1983 var previousYield = this.allowYieldExpression;
1984 this.lex();
1985 var expr = this.parseAssignmentExpression();
1986 this.expect(_tokenizer.TokenType.RBRACK);
1987 this.allowYieldExpression = previousYield;
1988 return { name: this.markLocation({ type: "ComputedPropertyName", expression: expr }, startLocation), binding: null };
1989 }
1990
1991 var name = this.parseIdentifierName();
1992 return {
1993 name: this.markLocation({ type: "StaticPropertyName", value: name }, startLocation),
1994 binding: this.markLocation({ type: "BindingIdentifier", name: name }, startLocation)
1995 };
1996 }
1997
1998 /**
1999 * Test if lookahead can be the beginning of a `PropertyName`.
2000 * @returns {boolean}
2001 */
2002 }, {
2003 key: "lookaheadPropertyName",
2004 value: function lookaheadPropertyName() {
2005 switch (this.lookahead.type) {
2006 case _tokenizer.TokenType.NUMBER:
2007 case _tokenizer.TokenType.STRING:
2008 case _tokenizer.TokenType.LBRACK:
2009 return true;
2010 default:
2011 return this.lookahead.type.klass.isIdentifierName;
2012 }
2013 }
2014
2015 /**
2016 * Try to parse a method definition.
2017 *
2018 * If it turns out to be one of:
2019 * * `IdentifierReference`
2020 * * `CoverInitializedName` (`IdentifierReference "=" AssignmentExpression`)
2021 * * `PropertyName : AssignmentExpression`
2022 * The parser will stop at the end of the leading `Identifier` or `PropertyName` and return it.
2023 *
2024 * @returns {{methodOrKey: (Method|PropertyName), kind: string}}
2025 */
2026 }, {
2027 key: "parseMethodDefinition",
2028 value: function parseMethodDefinition() {
2029 var token = this.lookahead;
2030 var startLocation = this.getLocation();
2031
2032 var isGenerator = !!this.eat(_tokenizer.TokenType.MUL);
2033
2034 var _parsePropertyName = this.parsePropertyName();
2035
2036 var name = _parsePropertyName.name;
2037 var binding = _parsePropertyName.binding;
2038
2039 if (!isGenerator && token.type === _tokenizer.TokenType.IDENTIFIER) {
2040 var _name = token.value;
2041 if (_name.length === 3) {
2042 // Property Assignment: Getter and Setter.
2043 if (_name === "get" && this.lookaheadPropertyName()) {
2044 var _parsePropertyName2 = this.parsePropertyName();
2045
2046 _name = _parsePropertyName2.name;
2047
2048 this.expect(_tokenizer.TokenType.LPAREN);
2049 this.expect(_tokenizer.TokenType.RPAREN);
2050 var body = this.parseFunctionBody();
2051 return {
2052 methodOrKey: this.markLocation({ type: "Getter", name: _name, body: body }, startLocation),
2053 kind: "method"
2054 };
2055 } else if (_name === "set" && this.lookaheadPropertyName()) {
2056 var _parsePropertyName3 = this.parsePropertyName();
2057
2058 _name = _parsePropertyName3.name;
2059
2060 this.expect(_tokenizer.TokenType.LPAREN);
2061 var param = this.parseBindingElement();
2062 this.expect(_tokenizer.TokenType.RPAREN);
2063 var previousYield = this.allowYieldExpression;
2064 this.allowYieldExpression = false;
2065 var body = this.parseFunctionBody();
2066 this.allowYieldExpression = previousYield;
2067 return {
2068 methodOrKey: this.markLocation({ type: "Setter", name: _name, param: param, body: body }, startLocation),
2069 kind: "method"
2070 };
2071 }
2072 }
2073 }
2074
2075 if (this.match(_tokenizer.TokenType.LPAREN)) {
2076 var previousYield = this.allowYieldExpression;
2077 this.allowYieldExpression = isGenerator;
2078 var params = this.parseParams();
2079 this.allowYieldExpression = isGenerator;
2080 var body = this.parseFunctionBody();
2081 this.allowYieldExpression = previousYield;
2082
2083 return {
2084 methodOrKey: this.markLocation({ type: "Method", isGenerator: isGenerator, name: name, params: params, body: body }, startLocation),
2085 kind: "method"
2086 };
2087 }
2088
2089 if (isGenerator && this.match(_tokenizer.TokenType.COLON)) {
2090 throw this.createUnexpected(this.lookahead);
2091 }
2092
2093 return {
2094 methodOrKey: name,
2095 kind: token.type.klass.isIdentifierName ? "identifier" : "property",
2096 binding: binding
2097 };
2098 }
2099 }, {
2100 key: "parseClass",
2101 value: function parseClass(_ref2) {
2102 // istanbul ignore next
2103
2104 var _this4 = this;
2105
2106 var isExpr = _ref2.isExpr;
2107 var inDefault = _ref2.inDefault;
2108
2109 var startLocation = this.getLocation();
2110
2111 this.lex();
2112 var name = null;
2113 var heritage = null;
2114
2115 if (this.match(_tokenizer.TokenType.IDENTIFIER)) {
2116 name = this.parseBindingIdentifier();
2117 } else if (!isExpr) {
2118 if (inDefault) {
2119 name = this.markLocation({ type: "BindingIdentifier", name: "*default*" }, startLocation);
2120 } else {
2121 throw this.createUnexpected(this.lookahead);
2122 }
2123 }
2124
2125 var previousParamYield = this.allowYieldExpression;
2126
2127 if (isExpr) {
2128 this.allowYieldExpression = false;
2129 }
2130
2131 if (this.eat(_tokenizer.TokenType.EXTENDS)) {
2132 heritage = this.isolateCoverGrammar(function () {
2133 return _this4.parseLeftHandSideExpression({ allowCall: true });
2134 });
2135 }
2136
2137 this.expect(_tokenizer.TokenType.LBRACE);
2138 var elements = [];
2139 while (!this.eat(_tokenizer.TokenType.RBRACE)) {
2140 if (this.eat(_tokenizer.TokenType.SEMICOLON)) {
2141 continue;
2142 }
2143 var isStatic = false;
2144
2145 var _parseMethodDefinition2 = this.parseMethodDefinition();
2146
2147 var methodOrKey = _parseMethodDefinition2.methodOrKey;
2148 var kind = _parseMethodDefinition2.kind;
2149
2150 if (kind === "identifier" && methodOrKey.value === "static") {
2151 isStatic = true;
2152
2153 var _parseMethodDefinition3 = this.parseMethodDefinition();
2154
2155 methodOrKey = _parseMethodDefinition3.methodOrKey;
2156 kind = _parseMethodDefinition3.kind;
2157 }
2158 if (kind === "method") {
2159 elements.push(copyLocation(methodOrKey, { type: "ClassElement", isStatic: isStatic, method: methodOrKey }));
2160 } else {
2161 throw this.createError("Only methods are allowed in classes");
2162 }
2163 }
2164 this.allowYieldExpression = previousParamYield;
2165 return this.markLocation({ type: isExpr ? "ClassExpression" : "ClassDeclaration", name: name, "super": heritage, elements: elements }, startLocation);
2166 }
2167 }, {
2168 key: "parseFunction",
2169 value: function parseFunction(_ref3) {
2170 var isExpr = _ref3.isExpr;
2171 var inDefault = _ref3.inDefault;
2172 var allowGenerator = _ref3.allowGenerator;
2173
2174 var startLocation = this.getLocation();
2175
2176 this.lex();
2177
2178 var name = null;
2179 var isGenerator = allowGenerator && !!this.eat(_tokenizer.TokenType.MUL);
2180
2181 var previousYield = this.allowYieldExpression;
2182
2183 if (isExpr) {
2184 this.allowYieldExpression = isGenerator;
2185 }
2186
2187 if (!this.match(_tokenizer.TokenType.LPAREN)) {
2188 name = this.parseBindingIdentifier();
2189 } else if (!isExpr) {
2190 if (inDefault) {
2191 name = this.markLocation({ type: "BindingIdentifier", name: "*default*" }, startLocation);
2192 } else {
2193 throw this.createUnexpected(this.lookahead);
2194 }
2195 }
2196
2197 this.allowYieldExpression = isGenerator;
2198 var params = this.parseParams();
2199 this.allowYieldExpression = isGenerator;
2200 var body = this.parseFunctionBody();
2201 this.allowYieldExpression = previousYield;
2202
2203 var type = isExpr ? "FunctionExpression" : "FunctionDeclaration";
2204 return this.markLocation({ type: type, isGenerator: isGenerator, name: name, params: params, body: body }, startLocation);
2205 }
2206 }, {
2207 key: "parseArrayBinding",
2208 value: function parseArrayBinding() {
2209 var startLocation = this.getLocation();
2210
2211 this.expect(_tokenizer.TokenType.LBRACK);
2212
2213 var elements = [],
2214 restElement = null;
2215
2216 while (true) {
2217 if (this.match(_tokenizer.TokenType.RBRACK)) {
2218 break;
2219 }
2220 var el = undefined;
2221
2222 if (this.eat(_tokenizer.TokenType.COMMA)) {
2223 el = null;
2224 } else {
2225 if (this.eat(_tokenizer.TokenType.ELLIPSIS)) {
2226 restElement = this.parseBindingTarget();
2227 break;
2228 } else {
2229 el = this.parseBindingElement();
2230 }
2231 if (!this.match(_tokenizer.TokenType.RBRACK)) {
2232 this.expect(_tokenizer.TokenType.COMMA);
2233 }
2234 }
2235 elements.push(el);
2236 }
2237
2238 this.expect(_tokenizer.TokenType.RBRACK);
2239
2240 return this.markLocation({ type: "ArrayBinding", elements: elements, restElement: restElement }, startLocation);
2241 }
2242 }, {
2243 key: "parseBindingProperty",
2244 value: function parseBindingProperty() {
2245 var startLocation = this.getLocation();
2246 var token = this.lookahead;
2247
2248 var _parsePropertyName4 = this.parsePropertyName();
2249
2250 var name = _parsePropertyName4.name;
2251 var binding = _parsePropertyName4.binding;
2252
2253 if ((token.type === _tokenizer.TokenType.IDENTIFIER || token.type === _tokenizer.TokenType.LET || token.type === _tokenizer.TokenType.YIELD) && name.type === "StaticPropertyName") {
2254 if (!this.match(_tokenizer.TokenType.COLON)) {
2255 var defaultValue = null;
2256 if (this.eat(_tokenizer.TokenType.ASSIGN)) {
2257 var previousAllowYieldExpression = this.allowYieldExpression;
2258 var expr = this.parseAssignmentExpression();
2259 defaultValue = expr;
2260 this.allowYieldExpression = previousAllowYieldExpression;
2261 }
2262 return this.markLocation({
2263 type: "BindingPropertyIdentifier",
2264 binding: binding,
2265 init: defaultValue
2266 }, startLocation);
2267 }
2268 }
2269 this.expect(_tokenizer.TokenType.COLON);
2270 binding = this.parseBindingElement();
2271 return this.markLocation({ type: "BindingPropertyProperty", name: name, binding: binding }, startLocation);
2272 }
2273 }, {
2274 key: "parseObjectBinding",
2275 value: function parseObjectBinding() {
2276 var startLocation = this.getLocation();
2277
2278 this.expect(_tokenizer.TokenType.LBRACE);
2279
2280 var properties = [];
2281 while (!this.match(_tokenizer.TokenType.RBRACE)) {
2282 properties.push(this.parseBindingProperty());
2283 if (!this.match(_tokenizer.TokenType.RBRACE)) {
2284 this.expect(_tokenizer.TokenType.COMMA);
2285 }
2286 }
2287
2288 this.expect(_tokenizer.TokenType.RBRACE);
2289
2290 return this.markLocation({ type: "ObjectBinding", properties: properties }, startLocation);
2291 }
2292 }, {
2293 key: "parseBindingTarget",
2294 value: function parseBindingTarget() {
2295 switch (this.lookahead.type) {
2296 case _tokenizer.TokenType.IDENTIFIER:
2297 case _tokenizer.TokenType.LET:
2298 case _tokenizer.TokenType.YIELD:
2299 return this.parseBindingIdentifier();
2300 case _tokenizer.TokenType.LBRACK:
2301 return this.parseArrayBinding();
2302 case _tokenizer.TokenType.LBRACE:
2303 return this.parseObjectBinding();
2304 }
2305 throw this.createUnexpected(this.lookahead);
2306 }
2307 }, {
2308 key: "parseBindingElement",
2309 value: function parseBindingElement() {
2310 var startLocation = this.getLocation();
2311 var binding = this.parseBindingTarget();
2312
2313 if (this.eat(_tokenizer.TokenType.ASSIGN)) {
2314 var previousYieldExpression = this.allowYieldExpression;
2315 var init = this.parseAssignmentExpression();
2316 binding = this.markLocation({ type: "BindingWithDefault", binding: binding, init: init }, startLocation);
2317 this.allowYieldExpression = previousYieldExpression;
2318 }
2319 return binding;
2320 }
2321 }, {
2322 key: "parseParam",
2323 value: function parseParam() {
2324 var previousInParameter = this.inParameter;
2325 this.inParameter = true;
2326 var param = this.parseBindingElement();
2327 this.inParameter = previousInParameter;
2328 return param;
2329 }
2330 }, {
2331 key: "parseParams",
2332 value: function parseParams() {
2333 var paramsLocation = this.getLocation();
2334
2335 this.expect(_tokenizer.TokenType.LPAREN);
2336
2337 var items = [],
2338 rest = null;
2339 if (!this.match(_tokenizer.TokenType.RPAREN)) {
2340 while (!this.eof()) {
2341 if (this.eat(_tokenizer.TokenType.ELLIPSIS)) {
2342 rest = this.parseBindingIdentifier();
2343 break;
2344 }
2345 items.push(this.parseParam());
2346 if (this.match(_tokenizer.TokenType.RPAREN)) break;
2347 this.expect(_tokenizer.TokenType.COMMA);
2348 }
2349 }
2350
2351 this.expect(_tokenizer.TokenType.RPAREN);
2352
2353 return this.markLocation({ type: "FormalParameters", items: items, rest: rest }, paramsLocation);
2354 }
2355 }]);
2356
2357 return Parser;
2358})(_tokenizer["default"]);
2359
2360exports.Parser = Parser;
\No newline at end of file