1 /*
   2  * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.parser;
  27 
  28 import static jdk.nashorn.internal.codegen.CompilerConstants.ANON_FUNCTION_PREFIX;
  29 import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
  30 import static jdk.nashorn.internal.codegen.CompilerConstants.PROGRAM;
  31 import static jdk.nashorn.internal.parser.TokenType.ARROW;
  32 import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
  33 import static jdk.nashorn.internal.parser.TokenType.CASE;
  34 import static jdk.nashorn.internal.parser.TokenType.CATCH;
  35 import static jdk.nashorn.internal.parser.TokenType.CLASS;
  36 import static jdk.nashorn.internal.parser.TokenType.COLON;
  37 import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
  38 import static jdk.nashorn.internal.parser.TokenType.COMMENT;
  39 import static jdk.nashorn.internal.parser.TokenType.CONST;
  40 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
  41 import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
  42 import static jdk.nashorn.internal.parser.TokenType.ELLIPSIS;
  43 import static jdk.nashorn.internal.parser.TokenType.ELSE;
  44 import static jdk.nashorn.internal.parser.TokenType.EOF;
  45 import static jdk.nashorn.internal.parser.TokenType.EOL;
  46 import static jdk.nashorn.internal.parser.TokenType.EQ_STRICT;
  47 import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
  48 import static jdk.nashorn.internal.parser.TokenType.EXPORT;
  49 import static jdk.nashorn.internal.parser.TokenType.EXTENDS;
  50 import static jdk.nashorn.internal.parser.TokenType.FINALLY;
  51 import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
  52 import static jdk.nashorn.internal.parser.TokenType.IDENT;
  53 import static jdk.nashorn.internal.parser.TokenType.IF;
  54 import static jdk.nashorn.internal.parser.TokenType.IMPORT;
  55 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
  56 import static jdk.nashorn.internal.parser.TokenType.LBRACE;
  57 import static jdk.nashorn.internal.parser.TokenType.LBRACKET;
  58 import static jdk.nashorn.internal.parser.TokenType.LET;
  59 import static jdk.nashorn.internal.parser.TokenType.LPAREN;
  60 import static jdk.nashorn.internal.parser.TokenType.MUL;
  61 import static jdk.nashorn.internal.parser.TokenType.PERIOD;
  62 import static jdk.nashorn.internal.parser.TokenType.RBRACE;
  63 import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
  64 import static jdk.nashorn.internal.parser.TokenType.RPAREN;
  65 import static jdk.nashorn.internal.parser.TokenType.SEMICOLON;
  66 import static jdk.nashorn.internal.parser.TokenType.SPREAD_ARRAY;
  67 import static jdk.nashorn.internal.parser.TokenType.STATIC;
  68 import static jdk.nashorn.internal.parser.TokenType.STRING;
  69 import static jdk.nashorn.internal.parser.TokenType.SUPER;
  70 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE;
  71 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_HEAD;
  72 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_MIDDLE;
  73 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_TAIL;
  74 import static jdk.nashorn.internal.parser.TokenType.TERNARY;
  75 import static jdk.nashorn.internal.parser.TokenType.VAR;
  76 import static jdk.nashorn.internal.parser.TokenType.VOID;
  77 import static jdk.nashorn.internal.parser.TokenType.WHILE;
  78 import static jdk.nashorn.internal.parser.TokenType.YIELD;
  79 import static jdk.nashorn.internal.parser.TokenType.YIELD_STAR;
  80 
  81 import java.io.Serializable;
  82 import java.util.ArrayDeque;
  83 import java.util.ArrayList;
  84 import java.util.Collections;
  85 import java.util.Deque;
  86 import java.util.HashMap;
  87 import java.util.HashSet;
  88 import java.util.Iterator;
  89 import java.util.List;
  90 import java.util.Map;
  91 import java.util.Objects;
  92 import java.util.function.Consumer;
  93 import jdk.nashorn.internal.codegen.CompilerConstants;
  94 import jdk.nashorn.internal.codegen.Namespace;
  95 import jdk.nashorn.internal.ir.AccessNode;
  96 import jdk.nashorn.internal.ir.BaseNode;
  97 import jdk.nashorn.internal.ir.BinaryNode;
  98 import jdk.nashorn.internal.ir.Block;
  99 import jdk.nashorn.internal.ir.BlockStatement;
 100 import jdk.nashorn.internal.ir.BreakNode;
 101 import jdk.nashorn.internal.ir.CallNode;
 102 import jdk.nashorn.internal.ir.CaseNode;
 103 import jdk.nashorn.internal.ir.CatchNode;
 104 import jdk.nashorn.internal.ir.ClassNode;
 105 import jdk.nashorn.internal.ir.ContinueNode;
 106 import jdk.nashorn.internal.ir.DebuggerNode;
 107 import jdk.nashorn.internal.ir.EmptyNode;
 108 import jdk.nashorn.internal.ir.ErrorNode;
 109 import jdk.nashorn.internal.ir.Expression;
 110 import jdk.nashorn.internal.ir.ExpressionList;
 111 import jdk.nashorn.internal.ir.ExpressionStatement;
 112 import jdk.nashorn.internal.ir.ForNode;
 113 import jdk.nashorn.internal.ir.FunctionNode;
 114 import jdk.nashorn.internal.ir.IdentNode;
 115 import jdk.nashorn.internal.ir.IfNode;
 116 import jdk.nashorn.internal.ir.IndexNode;
 117 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
 118 import jdk.nashorn.internal.ir.LabelNode;
 119 import jdk.nashorn.internal.ir.LexicalContext;
 120 import jdk.nashorn.internal.ir.LiteralNode;
 121 import jdk.nashorn.internal.ir.Module;
 122 import jdk.nashorn.internal.ir.Node;
 123 import jdk.nashorn.internal.ir.ObjectNode;
 124 import jdk.nashorn.internal.ir.PropertyKey;
 125 import jdk.nashorn.internal.ir.PropertyNode;
 126 import jdk.nashorn.internal.ir.ReturnNode;
 127 import jdk.nashorn.internal.ir.RuntimeNode;
 128 import jdk.nashorn.internal.ir.Statement;
 129 import jdk.nashorn.internal.ir.SwitchNode;
 130 import jdk.nashorn.internal.ir.TernaryNode;
 131 import jdk.nashorn.internal.ir.ThrowNode;
 132 import jdk.nashorn.internal.ir.TryNode;
 133 import jdk.nashorn.internal.ir.UnaryNode;
 134 import jdk.nashorn.internal.ir.VarNode;
 135 import jdk.nashorn.internal.ir.WhileNode;
 136 import jdk.nashorn.internal.ir.WithNode;
 137 import jdk.nashorn.internal.ir.debug.ASTWriter;
 138 import jdk.nashorn.internal.ir.debug.PrintVisitor;
 139 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 140 import jdk.nashorn.internal.runtime.Context;
 141 import jdk.nashorn.internal.runtime.ErrorManager;
 142 import jdk.nashorn.internal.runtime.JSErrorType;
 143 import jdk.nashorn.internal.runtime.ParserException;
 144 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 145 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 146 import jdk.nashorn.internal.runtime.ScriptingFunctions;
 147 import jdk.nashorn.internal.runtime.Source;
 148 import jdk.nashorn.internal.runtime.Timing;
 149 import jdk.nashorn.internal.runtime.linker.NameCodec;
 150 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 151 import jdk.nashorn.internal.runtime.logging.Loggable;
 152 import jdk.nashorn.internal.runtime.logging.Logger;
 153 
 154 /**
 155  * Builds the IR.
 156  */
 157 @Logger(name="parser")
 158 public class Parser extends AbstractParser implements Loggable {
 159     private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName();
 160 
 161     /** Current env. */
 162     private final ScriptEnvironment env;
 163 
 164     /** Is scripting mode. */
 165     private final boolean scripting;
 166 
 167     private List<Statement> functionDeclarations;
 168 
 169     private final ParserContext lc;
 170     private final Deque<Object> defaultNames;
 171 
 172     /** Namespace for function names where not explicitly given */
 173     private final Namespace namespace;
 174 
 175     private final DebugLogger log;
 176 
 177     /** to receive line information from Lexer when scanning multine literals. */
 178     protected final Lexer.LineInfoReceiver lineInfoReceiver;
 179 
 180     private RecompilableScriptFunctionData reparsedFunction;
 181 
 182     /**
 183      * Constructor
 184      *
 185      * @param env     script environment
 186      * @param source  source to parse
 187      * @param errors  error manager
 188      */
 189     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors) {
 190         this(env, source, errors, env._strict, null);
 191     }
 192 
 193     /**
 194      * Constructor
 195      *
 196      * @param env     script environment
 197      * @param source  source to parse
 198      * @param errors  error manager
 199      * @param strict  strict
 200      * @param log debug logger if one is needed
 201      */
 202     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) {
 203         this(env, source, errors, strict, 0, log);
 204     }
 205 
 206     /**
 207      * Construct a parser.
 208      *
 209      * @param env     script environment
 210      * @param source  source to parse
 211      * @param errors  error manager
 212      * @param strict  parser created with strict mode enabled.
 213      * @param lineOffset line offset to start counting lines from
 214      * @param log debug logger if one is needed
 215      */
 216     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) {
 217         super(source, errors, strict, lineOffset);
 218         this.lc = new ParserContext();
 219         this.defaultNames = new ArrayDeque<>();
 220         this.env = env;
 221         this.namespace = new Namespace(env.getNamespace());
 222         this.scripting = env._scripting;
 223         if (this.scripting) {
 224             this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
 225                 @Override
 226                 public void lineInfo(final int receiverLine, final int receiverLinePosition) {
 227                     // update the parser maintained line information
 228                     Parser.this.line = receiverLine;
 229                     Parser.this.linePosition = receiverLinePosition;
 230                 }
 231             };
 232         } else {
 233             // non-scripting mode script can't have multi-line literals
 234             this.lineInfoReceiver = null;
 235         }
 236 
 237         this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
 238     }
 239 
 240     @Override
 241     public DebugLogger getLogger() {
 242         return log;
 243     }
 244 
 245     @Override
 246     public DebugLogger initLogger(final Context context) {
 247         return context.getLogger(this.getClass());
 248     }
 249 
 250     /**
 251      * Sets the name for the first function. This is only used when reparsing anonymous functions to ensure they can
 252      * preserve their already assigned name, as that name doesn't appear in their source text.
 253      * @param name the name for the first parsed function.
 254      */
 255     public void setFunctionName(final String name) {
 256         defaultNames.push(createIdentNode(0, 0, name));
 257     }
 258 
 259     /**
 260      * Sets the {@link RecompilableScriptFunctionData} representing the function being reparsed (when this
 261      * parser instance is used to reparse a previously parsed function, as part of its on-demand compilation).
 262      * This will trigger various special behaviors, such as skipping nested function bodies.
 263      * @param reparsedFunction the function being reparsed.
 264      */
 265     public void setReparsedFunction(final RecompilableScriptFunctionData reparsedFunction) {
 266         this.reparsedFunction = reparsedFunction;
 267     }
 268 
 269     /**
 270      * Execute parse and return the resulting function node.
 271      * Errors will be thrown and the error manager will contain information
 272      * if parsing should fail
 273      *
 274      * This is the default parse call, which will name the function node
 275      * {code :program} {@link CompilerConstants#PROGRAM}
 276      *
 277      * @return function node resulting from successful parse
 278      */
 279     public FunctionNode parse() {
 280         return parse(PROGRAM.symbolName(), 0, source.getLength(), false);
 281     }
 282 
 283     /**
 284      * Set up first token. Skips opening EOL.
 285      */
 286     private void scanFirstToken() {
 287         k = -1;
 288         next();
 289     }
 290 
 291     /**
 292      * Execute parse and return the resulting function node.
 293      * Errors will be thrown and the error manager will contain information
 294      * if parsing should fail
 295      *
 296      * This should be used to create one and only one function node
 297      *
 298      * @param scriptName name for the script, given to the parsed FunctionNode
 299      * @param startPos start position in source
 300      * @param len length of parse
 301      * @param allowPropertyFunction if true, "get" and "set" are allowed as first tokens of the program, followed by
 302      * a property getter or setter function. This is used when reparsing a function that can potentially be defined as a
 303      * property getter or setter in an object literal.
 304      *
 305      * @return function node resulting from successful parse
 306      */
 307     public FunctionNode parse(final String scriptName, final int startPos, final int len, final boolean allowPropertyFunction) {
 308         final boolean isTimingEnabled = env.isTimingEnabled();
 309         final long t0 = isTimingEnabled ? System.nanoTime() : 0L;
 310         log.info(this, " begin for '", scriptName, "'");
 311 
 312         try {
 313             stream = new TokenStream();
 314             lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
 315             lexer.line = lexer.pendingLine = lineOffset + 1;
 316             line = lineOffset;
 317 
 318             scanFirstToken();
 319             // Begin parse.
 320             return program(scriptName, allowPropertyFunction);
 321         } catch (final Exception e) {
 322             handleParseException(e);
 323 
 324             return null;
 325         } finally {
 326             final String end = this + " end '" + scriptName + "'";
 327             if (isTimingEnabled) {
 328                 env._timing.accumulateTime(toString(), System.nanoTime() - t0);
 329                 log.info(end, "' in ", Timing.toMillisPrint(System.nanoTime() - t0), " ms");
 330             } else {
 331                 log.info(end);
 332             }
 333         }
 334     }
 335 
 336     /**
 337      * Parse and return the resulting module.
 338      * Errors will be thrown and the error manager will contain information
 339      * if parsing should fail
 340      *
 341      * @param moduleName name for the module, given to the parsed FunctionNode
 342      * @param startPos start position in source
 343      * @param len length of parse
 344      *
 345      * @return function node resulting from successful parse
 346      */
 347     public FunctionNode parseModule(final String moduleName, final int startPos, final int len) {
 348         try {
 349             stream = new TokenStream();
 350             lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
 351             lexer.line = lexer.pendingLine = lineOffset + 1;
 352             line = lineOffset;
 353 
 354             scanFirstToken();
 355             // Begin parse.
 356             return module(moduleName);
 357         } catch (final Exception e) {
 358             handleParseException(e);
 359 
 360             return null;
 361         }
 362     }
 363 
 364     /**
 365      * Entry point for parsing a module.
 366      *
 367      * @param moduleName the module name
 368      * @return the parsed module
 369      */
 370     public FunctionNode parseModule(final String moduleName) {
 371         return parseModule(moduleName, 0, source.getLength());
 372     }
 373 
 374     /**
 375      * Parse and return the list of function parameter list. A comma
 376      * separated list of function parameter identifiers is expected to be parsed.
 377      * Errors will be thrown and the error manager will contain information
 378      * if parsing should fail. This method is used to check if parameter Strings
 379      * passed to "Function" constructor is a valid or not.
 380      *
 381      * @return the list of IdentNodes representing the formal parameter list
 382      */
 383     public List<IdentNode> parseFormalParameterList() {
 384         try {
 385             stream = new TokenStream();
 386             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
 387 
 388             scanFirstToken();
 389 
 390             return formalParameterList(TokenType.EOF, false);
 391         } catch (final Exception e) {
 392             handleParseException(e);
 393             return null;
 394         }
 395     }
 396 
 397     /**
 398      * Execute parse and return the resulting function node.
 399      * Errors will be thrown and the error manager will contain information
 400      * if parsing should fail. This method is used to check if code String
 401      * passed to "Function" constructor is a valid function body or not.
 402      *
 403      * @return function node resulting from successful parse
 404      */
 405     public FunctionNode parseFunctionBody() {
 406         try {
 407             stream = new TokenStream();
 408             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
 409             final int functionLine = line;
 410 
 411             scanFirstToken();
 412 
 413             // Make a fake token for the function.
 414             final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
 415             // Set up the function to append elements.
 416 
 417             final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName());
 418             final ParserContextFunctionNode function = createParserContextFunctionNode(ident, functionToken, FunctionNode.Kind.NORMAL, functionLine, Collections.<IdentNode>emptyList());
 419             lc.push(function);
 420 
 421             final ParserContextBlockNode body = newBlock();
 422 
 423             functionDeclarations = new ArrayList<>();
 424             sourceElements(false);
 425             addFunctionDeclarations(function);
 426             functionDeclarations = null;
 427 
 428             restoreBlock(body);
 429             body.setFlag(Block.NEEDS_SCOPE);
 430 
 431             final Block functionBody = new Block(functionToken, source.getLength() - 1,
 432                 body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
 433             lc.pop(function);
 434 
 435             expect(EOF);
 436 
 437             final FunctionNode functionNode = createFunctionNode(
 438                     function,
 439                     functionToken,
 440                     ident,
 441                     Collections.<IdentNode>emptyList(),
 442                     FunctionNode.Kind.NORMAL,
 443                     functionLine,
 444                     functionBody);
 445             printAST(functionNode);
 446             return functionNode;
 447         } catch (final Exception e) {
 448             handleParseException(e);
 449             return null;
 450         }
 451     }
 452 
 453     private void handleParseException(final Exception e) {
 454         // Extract message from exception.  The message will be in error
 455         // message format.
 456         String message = e.getMessage();
 457 
 458         // If empty message.
 459         if (message == null) {
 460             message = e.toString();
 461         }
 462 
 463         // Issue message.
 464         if (e instanceof ParserException) {
 465             errors.error((ParserException)e);
 466         } else {
 467             errors.error(message);
 468         }
 469 
 470         if (env._dump_on_error) {
 471             e.printStackTrace(env.getErr());
 472         }
 473     }
 474 
 475     /**
 476      * Skip to a good parsing recovery point.
 477      */
 478     private void recover(final Exception e) {
 479         if (e != null) {
 480             // Extract message from exception.  The message will be in error
 481             // message format.
 482             String message = e.getMessage();
 483 
 484             // If empty message.
 485             if (message == null) {
 486                 message = e.toString();
 487             }
 488 
 489             // Issue message.
 490             if (e instanceof ParserException) {
 491                 errors.error((ParserException)e);
 492             } else {
 493                 errors.error(message);
 494             }
 495 
 496             if (env._dump_on_error) {
 497                 e.printStackTrace(env.getErr());
 498             }
 499         }
 500 
 501         // Skip to a recovery point.
 502         loop:
 503         while (true) {
 504             switch (type) {
 505             case EOF:
 506                 // Can not go any further.
 507                 break loop;
 508             case EOL:
 509             case SEMICOLON:
 510             case RBRACE:
 511                 // Good recovery points.
 512                 next();
 513                 break loop;
 514             default:
 515                 // So we can recover after EOL.
 516                 nextOrEOL();
 517                 break;
 518             }
 519         }
 520     }
 521 
 522     /**
 523      * Set up a new block.
 524      *
 525      * @return New block.
 526      */
 527     private ParserContextBlockNode newBlock() {
 528         return lc.push(new ParserContextBlockNode(token));
 529     }
 530 
 531     private ParserContextFunctionNode createParserContextFunctionNode(final IdentNode ident, final long functionToken, final FunctionNode.Kind kind, final int functionLine, final List<IdentNode> parameters) {
 532         // Build function name.
 533         final StringBuilder sb = new StringBuilder();
 534 
 535         final ParserContextFunctionNode parentFunction = lc.getCurrentFunction();
 536         if (parentFunction != null && !parentFunction.isProgram()) {
 537             sb.append(parentFunction.getName()).append('$');
 538         }
 539 
 540         assert ident.getName() != null;
 541         sb.append(ident.getName());
 542 
 543         final String name = namespace.uniqueName(sb.toString());
 544         assert parentFunction != null || name.equals(PROGRAM.symbolName()) : "name = " + name;
 545 
 546         int flags = 0;
 547         if (isStrictMode) {
 548             flags |= FunctionNode.IS_STRICT;
 549         }
 550         if (parentFunction == null) {
 551             flags |= FunctionNode.IS_PROGRAM;
 552         }
 553 
 554         final ParserContextFunctionNode functionNode = new ParserContextFunctionNode(functionToken, ident, name, namespace, functionLine, kind, parameters);
 555         functionNode.setFlag(flags);
 556         return functionNode;
 557     }
 558 
 559     private FunctionNode createFunctionNode(final ParserContextFunctionNode function, final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine, final Block body) {
 560         // assert body.isFunctionBody() || body.getFlag(Block.IS_PARAMETER_BLOCK) && ((BlockStatement) body.getLastStatement()).getBlock().isFunctionBody();
 561         // Start new block.
 562         final FunctionNode functionNode =
 563             new FunctionNode(
 564                 source,
 565                 functionLine,
 566                 body.getToken(),
 567                 Token.descPosition(body.getToken()),
 568                 startToken,
 569                 function.getLastToken(),
 570                 namespace,
 571                 ident,
 572                 function.getName(),
 573                 parameters,
 574                 kind,
 575                 function.getFlags(),
 576                 body,
 577                 function.getEndParserState(),
 578                 function.getModule(),
 579                 function.getDebugFlags());
 580 
 581         printAST(functionNode);
 582 
 583         return functionNode;
 584     }
 585 
 586     /**
 587      * Restore the current block.
 588      */
 589     private ParserContextBlockNode restoreBlock(final ParserContextBlockNode block) {
 590         return lc.pop(block);
 591     }
 592 
 593     /**
 594      * Get the statements in a block.
 595      * @return Block statements.
 596      */
 597     private Block getBlock(final boolean needsBraces) {
 598         final long blockToken = token;
 599         final ParserContextBlockNode newBlock = newBlock();
 600         try {
 601             // Block opening brace.
 602             if (needsBraces) {
 603                 expect(LBRACE);
 604             }
 605             // Accumulate block statements.
 606             statementList();
 607 
 608         } finally {
 609             restoreBlock(newBlock);
 610         }
 611 
 612         // Block closing brace.
 613         if (needsBraces) {
 614             expect(RBRACE);
 615         }
 616 
 617         final int flags = newBlock.getFlags() | (needsBraces ? 0 : Block.IS_SYNTHETIC);
 618         return new Block(blockToken, finish, flags, newBlock.getStatements());
 619     }
 620 
 621     /**
 622      * Get the statements in a case clause.
 623      */
 624     private List<Statement> caseStatementList() {
 625         final ParserContextBlockNode newBlock = newBlock();
 626         try {
 627             statementList();
 628         } finally {
 629             restoreBlock(newBlock);
 630         }
 631         return newBlock.getStatements();
 632     }
 633 
 634     /**
 635      * Get all the statements generated by a single statement.
 636      * @return Statements.
 637      */
 638     private Block getStatement() {
 639         return getStatement(false);
 640     }
 641 
 642     private Block getStatement(boolean labelledStatement) {
 643         if (type == LBRACE) {
 644             return getBlock(true);
 645         }
 646         // Set up new block. Captures first token.
 647         final ParserContextBlockNode newBlock = newBlock();
 648         try {
 649             statement(false, false, true, labelledStatement);
 650         } finally {
 651             restoreBlock(newBlock);
 652         }
 653         return new Block(newBlock.getToken(), finish, newBlock.getFlags() | Block.IS_SYNTHETIC, newBlock.getStatements());
 654     }
 655 
 656     /**
 657      * Detect calls to special functions.
 658      * @param ident Called function.
 659      */
 660     private void detectSpecialFunction(final IdentNode ident) {
 661         final String name = ident.getName();
 662 
 663         if (EVAL.symbolName().equals(name)) {
 664             markEval(lc);
 665         } else if (SUPER.getName().equals(name)) {
 666             assert ident.isDirectSuper();
 667             markSuperCall(lc);
 668         }
 669     }
 670 
 671     /**
 672      * Detect use of special properties.
 673      * @param ident Referenced property.
 674      */
 675     private void detectSpecialProperty(final IdentNode ident) {
 676         if (isArguments(ident)) {
 677             // skip over arrow functions, e.g. function f() { return (() => arguments.length)(); }
 678             getCurrentNonArrowFunction().setFlag(FunctionNode.USES_ARGUMENTS);
 679         }
 680     }
 681 
 682     private boolean useBlockScope() {
 683         return env._es6;
 684     }
 685 
 686     private boolean isES6() {
 687         return env._es6;
 688     }
 689 
 690     private static boolean isArguments(final String name) {
 691         return ARGUMENTS_NAME.equals(name);
 692     }
 693 
 694     static boolean isArguments(final IdentNode ident) {
 695         return isArguments(ident.getName());
 696     }
 697 
 698     /**
 699      * Tells whether a IdentNode can be used as L-value of an assignment
 700      *
 701      * @param ident IdentNode to be checked
 702      * @return whether the ident can be used as L-value
 703      */
 704     private static boolean checkIdentLValue(final IdentNode ident) {
 705         return ident.tokenType().getKind() != TokenKind.KEYWORD;
 706     }
 707 
 708     /**
 709      * Verify an assignment expression.
 710      * @param op  Operation token.
 711      * @param lhs Left hand side expression.
 712      * @param rhs Right hand side expression.
 713      * @return Verified expression.
 714      */
 715     private Expression verifyAssignment(final long op, final Expression lhs, final Expression rhs) {
 716         final TokenType opType = Token.descType(op);
 717 
 718         switch (opType) {
 719         case ASSIGN:
 720         case ASSIGN_ADD:
 721         case ASSIGN_BIT_AND:
 722         case ASSIGN_BIT_OR:
 723         case ASSIGN_BIT_XOR:
 724         case ASSIGN_DIV:
 725         case ASSIGN_MOD:
 726         case ASSIGN_MUL:
 727         case ASSIGN_SAR:
 728         case ASSIGN_SHL:
 729         case ASSIGN_SHR:
 730         case ASSIGN_SUB:
 731             if (lhs instanceof IdentNode) {
 732                 if (!checkIdentLValue((IdentNode)lhs)) {
 733                     return referenceError(lhs, rhs, false);
 734                 }
 735                 verifyIdent((IdentNode)lhs, "assignment");
 736                 break;
 737             } else if (lhs instanceof AccessNode || lhs instanceof IndexNode) {
 738                 break;
 739             } else if (opType == ASSIGN && isDestructuringLhs(lhs)) {
 740                 verifyDestructuringAssignmentPattern(lhs, "assignment");
 741                 break;
 742             } else {
 743                 return referenceError(lhs, rhs, env._early_lvalue_error);
 744             }
 745         default:
 746             break;
 747         }
 748 
 749         // Build up node.
 750         if(BinaryNode.isLogical(opType)) {
 751             return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs));
 752         }
 753         return new BinaryNode(op, lhs, rhs);
 754     }
 755 
 756     private boolean isDestructuringLhs(Expression lhs) {
 757         if (lhs instanceof ObjectNode || lhs instanceof LiteralNode.ArrayLiteralNode) {
 758             return isES6();
 759         }
 760         return false;
 761     }
 762 
 763     private void verifyDestructuringAssignmentPattern(Expression pattern, String contextString) {
 764         assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
 765         pattern.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
 766             @Override
 767             public boolean enterLiteralNode(LiteralNode<?> literalNode) {
 768                 if (literalNode.isArray()) {
 769                     boolean restElement = false;
 770                     for (Expression element : literalNode.getElementExpressions()) {
 771                         if (element != null) {
 772                             if (restElement) {
 773                                 throw error(String.format("Unexpected element after rest element"), element.getToken());
 774                             }
 775                             if (element.isTokenType(SPREAD_ARRAY)) {
 776                                 restElement = true;
 777                                 Expression lvalue = ((UnaryNode) element).getExpression();
 778                                 if (!checkValidLValue(lvalue, contextString)) {
 779                                     throw error(AbstractParser.message("invalid.lvalue"), lvalue.getToken());
 780                                 }
 781                             }
 782                             element.accept(this);
 783                         }
 784                     }
 785                     return false;
 786                 } else {
 787                     return enterDefault(literalNode);
 788                 }
 789             }
 790 
 791             @Override
 792             public boolean enterObjectNode(ObjectNode objectNode) {
 793                 return true;
 794             }
 795 
 796             @Override
 797             public boolean enterPropertyNode(PropertyNode propertyNode) {
 798                 if (propertyNode.getValue() != null) {
 799                     propertyNode.getValue().accept(this);
 800                     return false;
 801                 } else {
 802                     return enterDefault(propertyNode);
 803                 }
 804             }
 805 
 806             @Override
 807             public boolean enterIdentNode(IdentNode identNode) {
 808                 verifyIdent(identNode, contextString);
 809                 if (!checkIdentLValue(identNode)) {
 810                     referenceError(identNode, null, true);
 811                     return false;
 812                 }
 813                 return false;
 814             }
 815 
 816             @Override
 817             public boolean enterAccessNode(AccessNode accessNode) {
 818                 return false;
 819             }
 820 
 821             @Override
 822             public boolean enterIndexNode(IndexNode indexNode) {
 823                 return false;
 824             }
 825 
 826             @Override
 827             public boolean enterBinaryNode(BinaryNode binaryNode) {
 828                 if (binaryNode.isTokenType(ASSIGN)) {
 829                     binaryNode.lhs().accept(this);
 830                     // Initializer(rhs) can be any AssignmentExpression
 831                     return false;
 832                 } else {
 833                     return enterDefault(binaryNode);
 834                 }
 835             }
 836 
 837             @Override
 838             public boolean enterUnaryNode(UnaryNode unaryNode) {
 839                 if (unaryNode.isTokenType(SPREAD_ARRAY)) {
 840                     // rest element
 841                     return true;
 842                 } else {
 843                     return enterDefault(unaryNode);
 844                 }
 845             }
 846 
 847             @Override
 848             protected boolean enterDefault(Node node) {
 849                 throw error(String.format("unexpected node in AssignmentPattern: %s", node));
 850             }
 851         });
 852     }
 853 
 854     private static Expression newBinaryExpression(final long op, final Expression lhs, final Expression rhs) {
 855         final TokenType opType = Token.descType(op);
 856 
 857         // Build up node.
 858         if (BinaryNode.isLogical(opType)) {
 859             return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs));
 860         }
 861         return new BinaryNode(op, lhs, rhs);
 862     }
 863 
 864 
 865     /**
 866      * Reduce increment/decrement to simpler operations.
 867      * @param firstToken First token.
 868      * @param tokenType  Operation token (INCPREFIX/DEC.)
 869      * @param expression Left hand side expression.
 870      * @param isPostfix  Prefix or postfix.
 871      * @return           Reduced expression.
 872      */
 873     private static UnaryNode incDecExpression(final long firstToken, final TokenType tokenType, final Expression expression, final boolean isPostfix) {
 874         if (isPostfix) {
 875             return new UnaryNode(Token.recast(firstToken, tokenType == DECPREFIX ? DECPOSTFIX : INCPOSTFIX), expression.getStart(), Token.descPosition(firstToken) + Token.descLength(firstToken), expression);
 876         }
 877 
 878         return new UnaryNode(firstToken, expression);
 879     }
 880 
 881     /**
 882      * -----------------------------------------------------------------------
 883      *
 884      * Grammar based on
 885      *
 886      *      ECMAScript Language Specification
 887      *      ECMA-262 5th Edition / December 2009
 888      *
 889      * -----------------------------------------------------------------------
 890      */
 891 
 892     /**
 893      * Program :
 894      *      SourceElements?
 895      *
 896      * See 14
 897      *
 898      * Parse the top level script.
 899      */
 900     private FunctionNode program(final String scriptName, final boolean allowPropertyFunction) {
 901         // Make a pseudo-token for the script holding its start and length.
 902         final long functionToken = Token.toDesc(FUNCTION, Token.descPosition(Token.withDelimiter(token)), source.getLength());
 903         final int  functionLine  = line;
 904 
 905         final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), scriptName);
 906         final ParserContextFunctionNode script = createParserContextFunctionNode(
 907                 ident,
 908                 functionToken,
 909                 FunctionNode.Kind.SCRIPT,
 910                 functionLine,
 911                 Collections.<IdentNode>emptyList());
 912         lc.push(script);
 913         final ParserContextBlockNode body = newBlock();
 914 
 915         functionDeclarations = new ArrayList<>();
 916         sourceElements(allowPropertyFunction);
 917         addFunctionDeclarations(script);
 918         functionDeclarations = null;
 919 
 920         restoreBlock(body);
 921         body.setFlag(Block.NEEDS_SCOPE);
 922         final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
 923         lc.pop(script);
 924         script.setLastToken(token);
 925 
 926         expect(EOF);
 927 
 928         return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.SCRIPT, functionLine, programBody);
 929     }
 930 
 931     /**
 932      * Directive value or null if statement is not a directive.
 933      *
 934      * @param stmt Statement to be checked
 935      * @return Directive value if the given statement is a directive
 936      */
 937     private String getDirective(final Node stmt) {
 938         if (stmt instanceof ExpressionStatement) {
 939             final Node expr = ((ExpressionStatement)stmt).getExpression();
 940             if (expr instanceof LiteralNode) {
 941                 final LiteralNode<?> lit = (LiteralNode<?>)expr;
 942                 final long litToken = lit.getToken();
 943                 final TokenType tt = Token.descType(litToken);
 944                 // A directive is either a string or an escape string
 945                 if (tt == TokenType.STRING || tt == TokenType.ESCSTRING) {
 946                     // Make sure that we don't unescape anything. Return as seen in source!
 947                     return source.getString(lit.getStart(), Token.descLength(litToken));
 948                 }
 949             }
 950         }
 951 
 952         return null;
 953     }
 954 
 955     /**
 956      * SourceElements :
 957      *      SourceElement
 958      *      SourceElements SourceElement
 959      *
 960      * See 14
 961      *
 962      * Parse the elements of the script or function.
 963      */
 964     private void sourceElements(final boolean shouldAllowPropertyFunction) {
 965         List<Node>    directiveStmts        = null;
 966         boolean       checkDirective        = true;
 967         boolean       allowPropertyFunction = shouldAllowPropertyFunction;
 968         final boolean oldStrictMode         = isStrictMode;
 969 
 970 
 971         try {
 972             // If is a script, then process until the end of the script.
 973             while (type != EOF) {
 974                 // Break if the end of a code block.
 975                 if (type == RBRACE) {
 976                     break;
 977                 }
 978 
 979                 try {
 980                     // Get the next element.
 981                     statement(true, allowPropertyFunction, false, false);
 982                     allowPropertyFunction = false;
 983 
 984                     // check for directive prologues
 985                     if (checkDirective) {
 986                         // skip any debug statement like line number to get actual first line
 987                         final Statement lastStatement = lc.getLastStatement();
 988 
 989                         // get directive prologue, if any
 990                         final String directive = getDirective(lastStatement);
 991 
 992                         // If we have seen first non-directive statement,
 993                         // no more directive statements!!
 994                         checkDirective = directive != null;
 995 
 996                         if (checkDirective) {
 997                             if (!oldStrictMode) {
 998                                 if (directiveStmts == null) {
 999                                     directiveStmts = new ArrayList<>();
1000                                 }
1001                                 directiveStmts.add(lastStatement);
1002                             }
1003 
1004                             // handle use strict directive
1005                             if ("use strict".equals(directive)) {
1006                                 isStrictMode = true;
1007                                 final ParserContextFunctionNode function = lc.getCurrentFunction();
1008                                 function.setFlag(FunctionNode.IS_STRICT);
1009 
1010                                 // We don't need to check these, if lexical environment is already strict
1011                                 if (!oldStrictMode && directiveStmts != null) {
1012                                     // check that directives preceding this one do not violate strictness
1013                                     for (final Node statement : directiveStmts) {
1014                                         // the get value will force unescape of preceding
1015                                         // escaped string directives
1016                                         getValue(statement.getToken());
1017                                     }
1018 
1019                                     // verify that function name as well as parameter names
1020                                     // satisfy strict mode restrictions.
1021                                     verifyIdent(function.getIdent(), "function name");
1022                                     for (final IdentNode param : function.getParameters()) {
1023                                         verifyIdent(param, "function parameter");
1024                                     }
1025                                 }
1026                             } else if (Context.DEBUG) {
1027                                 final int debugFlag = FunctionNode.getDirectiveFlag(directive);
1028                                 if (debugFlag != 0) {
1029                                     final ParserContextFunctionNode function = lc.getCurrentFunction();
1030                                     function.setDebugFlag(debugFlag);
1031                                 }
1032                             }
1033                         }
1034                     }
1035                 } catch (final Exception e) {
1036                     final int errorLine = line;
1037                     final long errorToken = token;
1038                     //recover parsing
1039                     recover(e);
1040                     final ErrorNode errorExpr = new ErrorNode(errorToken, finish);
1041                     final ExpressionStatement expressionStatement = new ExpressionStatement(errorLine, errorToken, finish, errorExpr);
1042                     appendStatement(expressionStatement);
1043                 }
1044 
1045                 // No backtracking from here on.
1046                 stream.commit(k);
1047             }
1048         } finally {
1049             isStrictMode = oldStrictMode;
1050         }
1051     }
1052 
1053     /**
1054      * Parse any of the basic statement types.
1055      *
1056      * Statement :
1057      *      BlockStatement
1058      *      VariableStatement
1059      *      EmptyStatement
1060      *      ExpressionStatement
1061      *      IfStatement
1062      *      BreakableStatement
1063      *      ContinueStatement
1064      *      BreakStatement
1065      *      ReturnStatement
1066      *      WithStatement
1067      *      LabelledStatement
1068      *      ThrowStatement
1069      *      TryStatement
1070      *      DebuggerStatement
1071      *
1072      * BreakableStatement :
1073      *      IterationStatement
1074      *      SwitchStatement
1075      *
1076      * BlockStatement :
1077      *      Block
1078      *
1079      * Block :
1080      *      { StatementList opt }
1081      *
1082      * StatementList :
1083      *      StatementListItem
1084      *      StatementList StatementListItem
1085      *
1086      * StatementItem :
1087      *      Statement
1088      *      Declaration
1089      *
1090      * Declaration :
1091      *     HoistableDeclaration
1092      *     ClassDeclaration
1093      *     LexicalDeclaration
1094      *
1095      * HoistableDeclaration :
1096      *     FunctionDeclaration
1097      *     GeneratorDeclaration
1098      */
1099     private void statement() {
1100         statement(false, false, false, false);
1101     }
1102 
1103     /**
1104      * @param topLevel does this statement occur at the "top level" of a script or a function?
1105      * @param allowPropertyFunction allow property "get" and "set" functions?
1106      * @param singleStatement are we in a single statement context?
1107      */
1108     private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement, final boolean labelledStatement) {
1109         switch (type) {
1110         case LBRACE:
1111             block();
1112             break;
1113         case VAR:
1114             variableStatement(type);
1115             break;
1116         case SEMICOLON:
1117             emptyStatement();
1118             break;
1119         case IF:
1120             ifStatement();
1121             break;
1122         case FOR:
1123             forStatement();
1124             break;
1125         case WHILE:
1126             whileStatement();
1127             break;
1128         case DO:
1129             doStatement();
1130             break;
1131         case CONTINUE:
1132             continueStatement();
1133             break;
1134         case BREAK:
1135             breakStatement();
1136             break;
1137         case RETURN:
1138             returnStatement();
1139             break;
1140         case WITH:
1141             withStatement();
1142             break;
1143         case SWITCH:
1144             switchStatement();
1145             break;
1146         case THROW:
1147             throwStatement();
1148             break;
1149         case TRY:
1150             tryStatement();
1151             break;
1152         case DEBUGGER:
1153             debuggerStatement();
1154             break;
1155         case RPAREN:
1156         case RBRACKET:
1157         case EOF:
1158             expect(SEMICOLON);
1159             break;
1160         case FUNCTION:
1161             // As per spec (ECMA section 12), function declarations as arbitrary statement
1162             // is not "portable". Implementation can issue a warning or disallow the same.
1163             if (singleStatement) {
1164                 // ES6 B.3.2 Labelled Function Declarations
1165                 // It is a Syntax Error if any strict mode source code matches this rule:
1166                 // LabelledItem : FunctionDeclaration.
1167                 if (!labelledStatement || isStrictMode) {
1168                     throw error(AbstractParser.message("expected.stmt", "function declaration"), token);
1169                 }
1170             }
1171             functionExpression(true, topLevel || labelledStatement);
1172             return;
1173         default:
1174             if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(false) || type == CONST)) {
1175                 if (singleStatement) {
1176                     throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
1177                 }
1178                 variableStatement(type);
1179                 break;
1180             } else if (type == CLASS && isES6()) {
1181                 if (singleStatement) {
1182                     throw error(AbstractParser.message("expected.stmt", "class declaration"), token);
1183                 }
1184                 classDeclaration(false);
1185                 break;
1186             }
1187             if (env._const_as_var && type == CONST) {
1188                 variableStatement(TokenType.VAR);
1189                 break;
1190             }
1191 
1192             if (type == IDENT || isNonStrictModeIdent()) {
1193                 if (T(k + 1) == COLON) {
1194                     labelStatement();
1195                     return;
1196                 }
1197                 if(allowPropertyFunction) {
1198                     final String ident = (String)getValue();
1199                     final long propertyToken = token;
1200                     final int propertyLine = line;
1201                     if ("get".equals(ident)) {
1202                         next();
1203                         addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
1204                         return;
1205                     } else if ("set".equals(ident)) {
1206                         next();
1207                         addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
1208                         return;
1209                     }
1210                 }
1211             }
1212 
1213             expressionStatement();
1214             break;
1215         }
1216     }
1217 
1218     private void addPropertyFunctionStatement(final PropertyFunction propertyFunction) {
1219         final FunctionNode fn = propertyFunction.functionNode;
1220         functionDeclarations.add(new ExpressionStatement(fn.getLineNumber(), fn.getToken(), finish, fn));
1221     }
1222 
1223     /**
1224      * ClassDeclaration[Yield, Default] :
1225      *   class BindingIdentifier[?Yield] ClassTail[?Yield]
1226      *   [+Default] class ClassTail[?Yield]
1227      */
1228     private ClassNode classDeclaration(boolean isDefault) {
1229         int classLineNumber = line;
1230 
1231         ClassNode classExpression = classExpression(!isDefault);
1232 
1233         if (!isDefault) {
1234             VarNode classVar = new VarNode(classLineNumber, classExpression.getToken(), classExpression.getIdent().getFinish(), classExpression.getIdent(), classExpression, VarNode.IS_CONST);
1235             appendStatement(classVar);
1236         }
1237         return classExpression;
1238     }
1239 
1240     /**
1241      * ClassExpression[Yield] :
1242      *   class BindingIdentifier[?Yield]opt ClassTail[?Yield]
1243      */
1244     private ClassNode classExpression(boolean isStatement) {
1245         assert type == CLASS;
1246         int classLineNumber = line;
1247         long classToken = token;
1248         next();
1249 
1250         IdentNode className = null;
1251         if (isStatement || type == IDENT) {
1252             className = getIdent();
1253         }
1254 
1255         return classTail(classLineNumber, classToken, className);
1256     }
1257 
1258     private static final class ClassElementKey {
1259         private final boolean isStatic;
1260         private final String propertyName;
1261 
1262         private ClassElementKey(boolean isStatic, String propertyName) {
1263             this.isStatic = isStatic;
1264             this.propertyName = propertyName;
1265         }
1266 
1267         @Override
1268         public int hashCode() {
1269             final int prime = 31;
1270             int result = 1;
1271             result = prime * result + (isStatic ? 1231 : 1237);
1272             result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode());
1273             return result;
1274         }
1275 
1276         @Override
1277         public boolean equals(Object obj) {
1278             if (obj instanceof ClassElementKey) {
1279                 ClassElementKey other = (ClassElementKey) obj;
1280                 return this.isStatic == other.isStatic && Objects.equals(this.propertyName, other.propertyName);
1281             }
1282             return false;
1283         }
1284     }
1285 
1286     /**
1287      * Parse ClassTail and ClassBody.
1288      *
1289      * ClassTail[Yield] :
1290      *   ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
1291      * ClassHeritage[Yield] :
1292      *   extends LeftHandSideExpression[?Yield]
1293      *
1294      * ClassBody[Yield] :
1295      *   ClassElementList[?Yield]
1296      * ClassElementList[Yield] :
1297      *   ClassElement[?Yield]
1298      *   ClassElementList[?Yield] ClassElement[?Yield]
1299      * ClassElement[Yield] :
1300      *   MethodDefinition[?Yield]
1301      *   static MethodDefinition[?Yield]
1302      *   ;
1303      */
1304     private ClassNode classTail(final int classLineNumber, final long classToken, final IdentNode className) {
1305         final boolean oldStrictMode = isStrictMode;
1306         isStrictMode = true;
1307         try {
1308             Expression classHeritage = null;
1309             if (type == EXTENDS) {
1310                 next();
1311                 classHeritage = leftHandSideExpression();
1312             }
1313 
1314             expect(LBRACE);
1315 
1316             PropertyNode constructor = null;
1317             final ArrayList<PropertyNode> classElements = new ArrayList<>();
1318             final Map<ClassElementKey, Integer> keyToIndexMap = new HashMap<>();
1319             for (;;) {
1320                 if (type == SEMICOLON) {
1321                     next();
1322                     continue;
1323                 }
1324                 if (type == RBRACE) {
1325                     break;
1326                 }
1327                 final long classElementToken = token;
1328                 boolean isStatic = false;
1329                 if (type == STATIC) {
1330                     isStatic = true;
1331                     next();
1332                 }
1333                 boolean generator = false;
1334                 if (isES6() && type == MUL) {
1335                     generator = true;
1336                     next();
1337                 }
1338                 final PropertyNode classElement = methodDefinition(isStatic, classHeritage != null, generator);
1339                 if (classElement.isComputed()) {
1340                     classElements.add(classElement);
1341                 } else if (!classElement.isStatic() && classElement.getKeyName().equals("constructor")) {
1342                     if (constructor == null) {
1343                         constructor = classElement;
1344                     } else {
1345                         throw error(AbstractParser.message("multiple.constructors"), classElementToken);
1346                     }
1347                 } else {
1348                     // Check for duplicate method definitions and combine accessor methods.
1349                     // In ES6, a duplicate is never an error regardless of strict mode (in consequence of computed property names).
1350 
1351                     final ClassElementKey key = new ClassElementKey(classElement.isStatic(), classElement.getKeyName());
1352                     final Integer existing = keyToIndexMap.get(key);
1353 
1354                     if (existing == null) {
1355                         keyToIndexMap.put(key, classElements.size());
1356                         classElements.add(classElement);
1357                     } else {
1358                         final PropertyNode existingProperty = classElements.get(existing);
1359 
1360                         final Expression   value  = classElement.getValue();
1361                         final FunctionNode getter = classElement.getGetter();
1362                         final FunctionNode setter = classElement.getSetter();
1363 
1364                         if (value != null || existingProperty.getValue() != null) {
1365                             keyToIndexMap.put(key, classElements.size());
1366                             classElements.add(classElement);
1367                         } else if (getter != null) {
1368                             assert existingProperty.getGetter() != null || existingProperty.getSetter() != null;
1369                             classElements.set(existing, existingProperty.setGetter(getter));
1370                         } else if (setter != null) {
1371                             assert existingProperty.getGetter() != null || existingProperty.getSetter() != null;
1372                             classElements.set(existing, existingProperty.setSetter(setter));
1373                         }
1374                     }
1375                 }
1376             }
1377 
1378             final long lastToken = token;
1379             expect(RBRACE);
1380 
1381             if (constructor == null) {
1382                 constructor = createDefaultClassConstructor(classLineNumber, classToken, lastToken, className, classHeritage != null);
1383             }
1384 
1385             classElements.trimToSize();
1386             return new ClassNode(classLineNumber, classToken, finish, className, classHeritage, constructor, classElements);
1387         } finally {
1388             isStrictMode = oldStrictMode;
1389         }
1390     }
1391 
1392     private PropertyNode createDefaultClassConstructor(int classLineNumber, long classToken, long lastToken, IdentNode className, boolean subclass) {
1393         final int ctorFinish = finish;
1394         final List<Statement> statements;
1395         final List<IdentNode> parameters;
1396         final long identToken = Token.recast(classToken, TokenType.IDENT);
1397         if (subclass) {
1398             final IdentNode superIdent = createIdentNode(identToken, ctorFinish, SUPER.getName()).setIsDirectSuper();
1399             final IdentNode argsIdent = createIdentNode(identToken, ctorFinish, "args").setIsRestParameter();
1400             final Expression spreadArgs = new UnaryNode(Token.recast(classToken, TokenType.SPREAD_ARGUMENT), argsIdent);
1401             final CallNode superCall = new CallNode(classLineNumber, classToken, ctorFinish, superIdent, Collections.singletonList(spreadArgs), false);
1402             statements = Collections.singletonList(new ExpressionStatement(classLineNumber, classToken, ctorFinish, superCall));
1403             parameters = Collections.singletonList(argsIdent);
1404         } else {
1405             statements = Collections.emptyList();
1406             parameters = Collections.emptyList();
1407         }
1408 
1409         final Block body = new Block(classToken, ctorFinish, Block.IS_BODY, statements);
1410         final IdentNode ctorName = className != null ? className : createIdentNode(identToken, ctorFinish, "constructor");
1411         final ParserContextFunctionNode function = createParserContextFunctionNode(ctorName, classToken, FunctionNode.Kind.NORMAL, classLineNumber, parameters);
1412         function.setLastToken(lastToken);
1413 
1414         function.setFlag(FunctionNode.ES6_IS_METHOD);
1415         function.setFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR);
1416         if (subclass) {
1417             function.setFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR);
1418             function.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
1419         }
1420         if (className == null) {
1421             function.setFlag(FunctionNode.IS_ANONYMOUS);
1422         }
1423 
1424         final PropertyNode constructor = new PropertyNode(classToken, ctorFinish, ctorName, createFunctionNode(
1425                         function,
1426                         classToken,
1427                         ctorName,
1428                         parameters,
1429                         FunctionNode.Kind.NORMAL,
1430                         classLineNumber,
1431                         body
1432                         ), null, null, false, false);
1433         return constructor;
1434     }
1435 
1436     private PropertyNode methodDefinition(final boolean isStatic, final boolean subclass, final boolean generator) {
1437         final long methodToken = token;
1438         final int methodLine = line;
1439         final boolean computed = type == LBRACKET;
1440         final boolean isIdent = type == IDENT;
1441         final Expression propertyName = propertyName();
1442         int flags = FunctionNode.ES6_IS_METHOD;
1443         if (!computed) {
1444             final String name = ((PropertyKey)propertyName).getPropertyName();
1445             if (!generator && isIdent && type != LPAREN && name.equals("get")) {
1446                 final PropertyFunction methodDefinition = propertyGetterFunction(methodToken, methodLine, flags);
1447                 verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true);
1448                 return new PropertyNode(methodToken, finish, methodDefinition.key, null, methodDefinition.functionNode, null, isStatic, methodDefinition.computed);
1449             } else if (!generator && isIdent && type != LPAREN && name.equals("set")) {
1450                 final PropertyFunction methodDefinition = propertySetterFunction(methodToken, methodLine, flags);
1451                 verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true);
1452                 return new PropertyNode(methodToken, finish, methodDefinition.key, null, null, methodDefinition.functionNode, isStatic, methodDefinition.computed);
1453             } else {
1454                 if (!isStatic && !generator && name.equals("constructor")) {
1455                     flags |= FunctionNode.ES6_IS_CLASS_CONSTRUCTOR;
1456                     if (subclass) {
1457                         flags |= FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR;
1458                     }
1459                 }
1460                 verifyAllowedMethodName(propertyName, isStatic, computed, generator, false);
1461             }
1462         }
1463         final PropertyFunction methodDefinition = propertyMethodFunction(propertyName, methodToken, methodLine, generator, flags, computed);
1464         return new PropertyNode(methodToken, finish, methodDefinition.key, methodDefinition.functionNode, null, null, isStatic, computed);
1465     }
1466 
1467     /**
1468      * ES6 14.5.1 Static Semantics: Early Errors.
1469      */
1470     private void verifyAllowedMethodName(final Expression key, final boolean isStatic, final boolean computed, final boolean generator, final boolean accessor) {
1471         if (!computed) {
1472             if (!isStatic && generator && ((PropertyKey) key).getPropertyName().equals("constructor")) {
1473                 throw error(AbstractParser.message("generator.constructor"), key.getToken());
1474             }
1475             if (!isStatic && accessor && ((PropertyKey) key).getPropertyName().equals("constructor")) {
1476                 throw error(AbstractParser.message("accessor.constructor"), key.getToken());
1477             }
1478             if (isStatic && ((PropertyKey) key).getPropertyName().equals("prototype")) {
1479                 throw error(AbstractParser.message("static.prototype.method"), key.getToken());
1480             }
1481         }
1482     }
1483 
1484     /**
1485      * block :
1486      *      { StatementList? }
1487      *
1488      * see 12.1
1489      *
1490      * Parse a statement block.
1491      */
1492     private void block() {
1493         appendStatement(new BlockStatement(line, getBlock(true)));
1494     }
1495 
1496     /**
1497      * StatementList :
1498      *      Statement
1499      *      StatementList Statement
1500      *
1501      * See 12.1
1502      *
1503      * Parse a list of statements.
1504      */
1505     private void statementList() {
1506         // Accumulate statements until end of list. */
1507         loop:
1508         while (type != EOF) {
1509             switch (type) {
1510             case EOF:
1511             case CASE:
1512             case DEFAULT:
1513             case RBRACE:
1514                 break loop;
1515             default:
1516                 break;
1517             }
1518 
1519             // Get next statement.
1520             statement();
1521         }
1522     }
1523 
1524     /**
1525      * Make sure that the identifier name used is allowed.
1526      *
1527      * @param ident         Identifier that is verified
1528      * @param contextString String used in error message to give context to the user
1529      */
1530     private void verifyIdent(final IdentNode ident, final String contextString) {
1531         verifyStrictIdent(ident, contextString);
1532         if (isES6()) {
1533             final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length());
1534             if (tokenType != IDENT && tokenType.getKind() != TokenKind.FUTURESTRICT) {
1535                 throw error(expectMessage(IDENT));
1536             }
1537         }
1538     }
1539 
1540     /**
1541      * Make sure that in strict mode, the identifier name used is allowed.
1542      *
1543      * @param ident         Identifier that is verified
1544      * @param contextString String used in error message to give context to the user
1545      */
1546     private void verifyStrictIdent(final IdentNode ident, final String contextString) {
1547         if (isStrictMode) {
1548             switch (ident.getName()) {
1549             case "eval":
1550             case "arguments":
1551                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1552             default:
1553                 break;
1554             }
1555 
1556             if (ident.isFutureStrictName()) {
1557                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1558             }
1559         }
1560     }
1561 
1562     /*
1563      * VariableStatement :
1564      *      var VariableDeclarationList ;
1565      *
1566      * VariableDeclarationList :
1567      *      VariableDeclaration
1568      *      VariableDeclarationList , VariableDeclaration
1569      *
1570      * VariableDeclaration :
1571      *      Identifier Initializer?
1572      *
1573      * Initializer :
1574      *      = AssignmentExpression
1575      *
1576      * See 12.2
1577      *
1578      * Parse a VAR statement.
1579      * @param isStatement True if a statement (not used in a FOR.)
1580      */
1581     private void variableStatement(final TokenType varType) {
1582         variableDeclarationList(varType, true, -1);
1583     }
1584 
1585     private List<Expression> variableDeclarationList(final TokenType varType, final boolean isStatement, final int sourceOrder) {
1586         // VAR tested in caller.
1587         assert varType == VAR || varType == LET || varType == CONST;
1588         next();
1589 
1590         final List<Expression> bindings = new ArrayList<>();
1591         int varFlags = 0;
1592         if (varType == LET) {
1593             varFlags |= VarNode.IS_LET;
1594         } else if (varType == CONST) {
1595             varFlags |= VarNode.IS_CONST;
1596         }
1597 
1598         Expression missingAssignment = null;
1599         while (true) {
1600             // Get starting token.
1601             final int  varLine  = line;
1602             final long varToken = token;
1603             // Get name of var.
1604             if (type == YIELD && inGeneratorFunction()) {
1605                 expect(IDENT);
1606             }
1607 
1608             final String contextString = "variable name";
1609             Expression binding = bindingIdentifierOrPattern(contextString);
1610             final boolean isDestructuring = !(binding instanceof IdentNode);
1611             if (isDestructuring) {
1612                 final int finalVarFlags = varFlags;
1613                 verifyDestructuringBindingPattern(binding, new Consumer<IdentNode>() {
1614                     public void accept(final IdentNode identNode) {
1615                         verifyIdent(identNode, contextString);
1616                         final VarNode var = new VarNode(varLine, varToken, sourceOrder, identNode.getFinish(), identNode.setIsDeclaredHere(), null, finalVarFlags);
1617                         appendStatement(var);
1618                     }
1619                 });
1620             }
1621 
1622             // Assume no init.
1623             Expression init = null;
1624 
1625             // Look for initializer assignment.
1626             if (type == ASSIGN) {
1627                 next();
1628 
1629                 // Get initializer expression. Suppress IN if not statement.
1630                 if (!isDestructuring) {
1631                     defaultNames.push(binding);
1632                 }
1633                 try {
1634                     init = assignmentExpression(!isStatement);
1635                 } finally {
1636                     if (!isDestructuring) {
1637                         defaultNames.pop();
1638                     }
1639                 }
1640             } else if (isStatement) {
1641                 if (isDestructuring) {
1642                     throw error(AbstractParser.message("missing.destructuring.assignment"), token);
1643                 } else if (varType == CONST) {
1644                     throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)binding).getName()));
1645                 }
1646                 // else, if we are in a for loop, delay checking until we know the kind of loop
1647             }
1648 
1649             if (!isDestructuring) {
1650                 assert init != null || varType != CONST || !isStatement;
1651                 final IdentNode ident = (IdentNode)binding;
1652                 if (!isStatement && ident.getName().equals("let")) {
1653                     throw error(AbstractParser.message("let.binding.for")); //ES6 13.7.5.1
1654                 }
1655                 // Only set declaration flag on lexically scoped let/const as it adds runtime overhead.
1656                 final IdentNode name = varType == LET || varType == CONST ? ident.setIsDeclaredHere() : ident;
1657                 binding = name;
1658                 final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name, init, varFlags);
1659                 appendStatement(var);
1660                 if (init == null && varType == CONST) {
1661                     if (missingAssignment == null) {
1662                         missingAssignment = binding;
1663                     }
1664                 }
1665             } else {
1666                 assert init != null || !isStatement;
1667                 binding = init == null ? binding : verifyAssignment(Token.recast(varToken, ASSIGN), binding, init);
1668                 if (isStatement) {
1669                     appendStatement(new ExpressionStatement(varLine, binding.getToken(), finish, binding));
1670                 } else if (init == null) {
1671                     if (missingAssignment == null) {
1672                         missingAssignment = binding;
1673                     }
1674                 }
1675             }
1676             bindings.add(binding);
1677 
1678             if (type != COMMARIGHT) {
1679                 break;
1680             }
1681             next();
1682         }
1683 
1684         // If is a statement then handle end of line.
1685         if (isStatement) {
1686             endOfLine();
1687         } else {
1688             if (type == SEMICOLON) {
1689                 // late check for missing assignment, now we know it's a for (init; test; modify) loop
1690                 if (missingAssignment != null) {
1691                     if (missingAssignment instanceof IdentNode) {
1692                         throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)missingAssignment).getName()));
1693                     } else {
1694                         throw error(AbstractParser.message("missing.destructuring.assignment"), missingAssignment.getToken());
1695                     }
1696                 }
1697             }
1698         }
1699 
1700         return bindings;
1701     }
1702 
1703     private boolean isBindingIdentifier() {
1704         return type == IDENT || isNonStrictModeIdent();
1705     }
1706 
1707     private IdentNode bindingIdentifier(final String contextString) {
1708         final IdentNode name = getIdent();
1709         verifyIdent(name, contextString);
1710         return name;
1711     }
1712 
1713     private Expression bindingPattern() {
1714         if (type == LBRACKET) {
1715             return arrayLiteral();
1716         } else if (type == LBRACE) {
1717             return objectLiteral();
1718         } else {
1719             throw error(AbstractParser.message("expected.binding"));
1720         }
1721     }
1722 
1723     private Expression bindingIdentifierOrPattern(final String contextString) {
1724         if (isBindingIdentifier() || !isES6()) {
1725             return bindingIdentifier(contextString);
1726         } else {
1727             return bindingPattern();
1728         }
1729     }
1730 
1731     /**
1732      * Verify destructuring variable declaration binding pattern and extract bound variable declarations.
1733      */
1734     private void verifyDestructuringBindingPattern(final Expression pattern, final Consumer<IdentNode> identifierCallback) {
1735         assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
1736         pattern.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
1737             @Override
1738             public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
1739                 if (literalNode.isArray()) {
1740                     boolean restElement = false;
1741                     for (final Expression element : literalNode.getElementExpressions()) {
1742                         if (restElement) {
1743                             throw error(String.format("Unexpected element after rest element"), element.getToken());
1744                         }
1745                         if (element != null) {
1746                             if (element.isTokenType(SPREAD_ARRAY)) {
1747                                 restElement = true;
1748                                 if (!(((UnaryNode) element).getExpression() instanceof IdentNode)) {
1749                                     throw error(String.format("Expected a valid binding identifier"), element.getToken());
1750 
1751                                 }
1752                             }
1753                             element.accept(this);
1754                         }
1755                     }
1756                     return false;
1757                 } else {
1758                     return enterDefault(literalNode);
1759                 }
1760             }
1761 
1762             @Override
1763             public boolean enterObjectNode(final ObjectNode objectNode) {
1764                 return true;
1765             }
1766 
1767             @Override
1768             public boolean enterPropertyNode(final PropertyNode propertyNode) {
1769                 if (propertyNode.getValue() != null) {
1770                     propertyNode.getValue().accept(this);
1771                     return false;
1772                 } else {
1773                     return enterDefault(propertyNode);
1774                 }
1775             }
1776 
1777             @Override
1778             public boolean enterIdentNode(final IdentNode identNode) {
1779                 identifierCallback.accept(identNode);
1780                 return false;
1781             }
1782 
1783             @Override
1784             public boolean enterBinaryNode(final BinaryNode binaryNode) {
1785                 if (binaryNode.isTokenType(ASSIGN)) {
1786                     binaryNode.lhs().accept(this);
1787                     // Initializer(rhs) can be any AssignmentExpression
1788                     return false;
1789                 } else {
1790                     return enterDefault(binaryNode);
1791                 }
1792             }
1793 
1794             @Override
1795             public boolean enterUnaryNode(final UnaryNode unaryNode) {
1796                 if (unaryNode.isTokenType(SPREAD_ARRAY)) {
1797                     // rest element
1798                     return true;
1799                 } else {
1800                     return enterDefault(unaryNode);
1801                 }
1802             }
1803 
1804             @Override
1805             protected boolean enterDefault(final Node node) {
1806                 throw error(String.format("unexpected node in BindingPattern: %s", node));
1807             }
1808         });
1809     }
1810 
1811     /**
1812      * EmptyStatement :
1813      *      ;
1814      *
1815      * See 12.3
1816      *
1817      * Parse an empty statement.
1818      */
1819     private void emptyStatement() {
1820         if (env._empty_statements) {
1821             appendStatement(new EmptyNode(line, token, Token.descPosition(token) + Token.descLength(token)));
1822         }
1823 
1824         // SEMICOLON checked in caller.
1825         next();
1826     }
1827 
1828     /**
1829      * ExpressionStatement :
1830      *      Expression ; // [lookahead ~( or  function )]
1831      *
1832      * See 12.4
1833      *
1834      * Parse an expression used in a statement block.
1835      */
1836     private void expressionStatement() {
1837         // Lookahead checked in caller.
1838         final int  expressionLine  = line;
1839         final long expressionToken = token;
1840 
1841         // Get expression and add as statement.
1842         final Expression expression = expression();
1843 
1844         ExpressionStatement expressionStatement = null;
1845         if (expression != null) {
1846             expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
1847             appendStatement(expressionStatement);
1848         } else {
1849             expect(null);
1850         }
1851 
1852         endOfLine();
1853     }
1854 
1855     /**
1856      * IfStatement :
1857      *      if ( Expression ) Statement else Statement
1858      *      if ( Expression ) Statement
1859      *
1860      * See 12.5
1861      *
1862      * Parse an IF statement.
1863      */
1864     private void ifStatement() {
1865         // Capture IF token.
1866         final int  ifLine  = line;
1867         final long ifToken = token;
1868          // IF tested in caller.
1869         next();
1870 
1871         expect(LPAREN);
1872         final Expression test = expression();
1873         expect(RPAREN);
1874         final Block pass = getStatement();
1875 
1876         Block fail = null;
1877         if (type == ELSE) {
1878             next();
1879             fail = getStatement();
1880         }
1881 
1882         appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1883     }
1884 
1885     /**
1886      * ... IterationStatement:
1887      *           ...
1888      *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1889      *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1890      *           for ( LeftHandSideExpression in Expression ) Statement
1891      *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1892      *
1893      * See 12.6
1894      *
1895      * Parse a FOR statement.
1896      */
1897     @SuppressWarnings("fallthrough")
1898     private void forStatement() {
1899         final long forToken = token;
1900         final int forLine = line;
1901         // start position of this for statement. This is used
1902         // for sort order for variables declared in the initializer
1903         // part of this 'for' statement (if any).
1904         final int forStart = Token.descPosition(forToken);
1905         // When ES6 for-let is enabled we create a container block to capture the LET.
1906         final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1907 
1908         // Create FOR node, capturing FOR token.
1909         final ParserContextLoopNode forNode = new ParserContextLoopNode();
1910         lc.push(forNode);
1911         Block body = null;
1912         List<Expression> vars = null;
1913         Expression init = null;
1914         JoinPredecessorExpression test = null;
1915         JoinPredecessorExpression modify = null;
1916 
1917         int flags = 0;
1918         boolean isForOf = false;
1919 
1920         try {
1921             // FOR tested in caller.
1922             next();
1923 
1924             // Nashorn extension: for each expression.
1925             // iterate property values rather than property names.
1926             if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1927                 flags |= ForNode.IS_FOR_EACH;
1928                 next();
1929             }
1930 
1931             expect(LPAREN);
1932 
1933             switch (type) {
1934             case VAR:
1935                 // Var declaration captured in for outer block.
1936                 vars = variableDeclarationList(type, false, forStart);
1937                 break;
1938             case SEMICOLON:
1939                 break;
1940             default:
1941                 if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(true) || type == CONST)) {
1942                     flags |= ForNode.PER_ITERATION_SCOPE;
1943                     // LET/CONST declaration captured in container block created above.
1944                     vars = variableDeclarationList(type, false, forStart);
1945                     break;
1946                 }
1947                 if (env._const_as_var && type == CONST) {
1948                     // Var declaration captured in for outer block.
1949                     vars = variableDeclarationList(TokenType.VAR, false, forStart);
1950                     break;
1951                 }
1952 
1953                 init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1954                 break;
1955             }
1956 
1957             switch (type) {
1958             case SEMICOLON:
1959                 // for (init; test; modify)
1960 
1961                 // for each (init; test; modify) is invalid
1962                 if ((flags & ForNode.IS_FOR_EACH) != 0) {
1963                     throw error(AbstractParser.message("for.each.without.in"), token);
1964                 }
1965 
1966                 expect(SEMICOLON);
1967                 if (type != SEMICOLON) {
1968                     test = joinPredecessorExpression();
1969                 }
1970                 expect(SEMICOLON);
1971                 if (type != RPAREN) {
1972                     modify = joinPredecessorExpression();
1973                 }
1974                 break;
1975 
1976             case IDENT:
1977                 if (env._es6 && "of".equals(getValue())) {
1978                     isForOf = true;
1979                     // fall through
1980                 } else {
1981                     expect(SEMICOLON); // fail with expected message
1982                     break;
1983                 }
1984             case IN:
1985 
1986                 flags |= isForOf ? ForNode.IS_FOR_OF : ForNode.IS_FOR_IN;
1987                 test = new JoinPredecessorExpression();
1988                 if (vars != null) {
1989                     // for (var i in obj)
1990                     if (vars.size() == 1) {
1991                         init = new IdentNode((IdentNode)vars.get(0));
1992                         if (init.isTokenType(ASSIGN)) {
1993                             throw error(AbstractParser.message("for.in.loop.initializer"), init.getToken());
1994                         }
1995                         assert init instanceof IdentNode || isDestructuringLhs(init);
1996                     } else {
1997                         // for (var i, j in obj) is invalid
1998                         throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), vars.get(1).getToken());
1999                     }
2000                 } else {
2001                     // for (expr in obj)
2002                     assert init != null : "for..in/of init expression can not be null here";
2003 
2004                     // check if initial expression is a valid L-value
2005                     if (!(init instanceof AccessNode ||
2006                           init instanceof IndexNode ||
2007                           init instanceof IdentNode)) {
2008                         throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
2009                     }
2010 
2011                     if (init instanceof IdentNode) {
2012                         if (!checkIdentLValue((IdentNode)init)) {
2013                             throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
2014                         }
2015                         verifyStrictIdent((IdentNode)init, isForOf ? "for-of iterator" : "for-in iterator");
2016                     }
2017                 }
2018 
2019                 next();
2020 
2021                 // For-of only allows AssignmentExpression.
2022                 modify = isForOf ? new JoinPredecessorExpression(assignmentExpression(false)) : joinPredecessorExpression();
2023                 break;
2024 
2025             default:
2026                 expect(SEMICOLON);
2027                 break;
2028             }
2029 
2030             expect(RPAREN);
2031 
2032             // Set the for body.
2033             body = getStatement();
2034         } finally {
2035             lc.pop(forNode);
2036 
2037             for (final Statement var : forNode.getStatements()) {
2038                 assert var instanceof VarNode;
2039                 appendStatement(var);
2040             }
2041             if (body != null) {
2042                 appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
2043             }
2044             if (outer != null) {
2045                 restoreBlock(outer);
2046                 if (body != null) {
2047                     appendStatement(new BlockStatement(forLine, new Block(
2048                                     outer.getToken(),
2049                                     body.getFinish(),
2050                                     outer.getStatements())));
2051                 }
2052             }
2053         }
2054     }
2055 
2056     private boolean checkValidLValue(final Expression init, final String contextString) {
2057         if (init instanceof IdentNode) {
2058             if (!checkIdentLValue((IdentNode)init)) {
2059                 return false;
2060             }
2061             verifyIdent((IdentNode)init, contextString);
2062             return true;
2063         } else if (init instanceof AccessNode || init instanceof IndexNode) {
2064             return true;
2065         } else if (isDestructuringLhs(init)) {
2066             verifyDestructuringAssignmentPattern(init, contextString);
2067             return true;
2068         } else {
2069             return false;
2070         }
2071     }
2072 
2073     private boolean lookaheadIsLetDeclaration(final boolean ofContextualKeyword) {
2074         assert type == LET;
2075         for (int i = 1;; i++) {
2076             TokenType t = T(k + i);
2077             switch (t) {
2078             case EOL:
2079             case COMMENT:
2080                 continue;
2081             case IDENT:
2082                 if (ofContextualKeyword && isES6() && "of".equals(getValue(getToken(k + i)))) {
2083                     return false;
2084                 }
2085                 // fall through
2086             case LBRACKET:
2087             case LBRACE:
2088                 return true;
2089             default:
2090                 // accept future strict tokens in non-strict mode (including LET)
2091                 if (!isStrictMode && t.getKind() == TokenKind.FUTURESTRICT) {
2092                     return true;
2093                 }
2094                 return false;
2095             }
2096         }
2097     }
2098 
2099     /**
2100      * ...IterationStatement :
2101      *           ...
2102      *           while ( Expression ) Statement
2103      *           ...
2104      *
2105      * See 12.6
2106      *
2107      * Parse while statement.
2108      */
2109     private void whileStatement() {
2110         // Capture WHILE token.
2111         final long whileToken = token;
2112         final int whileLine = line;
2113         // WHILE tested in caller.
2114         next();
2115 
2116         final ParserContextLoopNode whileNode = new ParserContextLoopNode();
2117         lc.push(whileNode);
2118 
2119         JoinPredecessorExpression test = null;
2120         Block body = null;
2121 
2122         try {
2123             expect(LPAREN);
2124             test = joinPredecessorExpression();
2125             expect(RPAREN);
2126             body = getStatement();
2127         } finally {
2128             lc.pop(whileNode);
2129         }
2130 
2131         if (body != null) {
2132             appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
2133         }
2134     }
2135 
2136     /**
2137      * ...IterationStatement :
2138      *           ...
2139      *           do Statement while( Expression ) ;
2140      *           ...
2141      *
2142      * See 12.6
2143      *
2144      * Parse DO WHILE statement.
2145      */
2146     private void doStatement() {
2147         // Capture DO token.
2148         final long doToken = token;
2149         int doLine = 0;
2150         // DO tested in the caller.
2151         next();
2152 
2153         final ParserContextLoopNode doWhileNode = new ParserContextLoopNode();
2154         lc.push(doWhileNode);
2155 
2156         Block body = null;
2157         JoinPredecessorExpression test = null;
2158 
2159         try {
2160            // Get DO body.
2161             body = getStatement();
2162 
2163             expect(WHILE);
2164             expect(LPAREN);
2165             doLine = line;
2166             test = joinPredecessorExpression();
2167             expect(RPAREN);
2168 
2169             if (type == SEMICOLON) {
2170                 endOfLine();
2171             }
2172         } finally {
2173             lc.pop(doWhileNode);
2174         }
2175 
2176         appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
2177     }
2178 
2179     /**
2180      * ContinueStatement :
2181      *      continue Identifier? ; // [no LineTerminator here]
2182      *
2183      * See 12.7
2184      *
2185      * Parse CONTINUE statement.
2186      */
2187     private void continueStatement() {
2188         // Capture CONTINUE token.
2189         final int  continueLine  = line;
2190         final long continueToken = token;
2191         // CONTINUE tested in caller.
2192         nextOrEOL();
2193 
2194         ParserContextLabelNode labelNode = null;
2195 
2196         // SEMICOLON or label.
2197         switch (type) {
2198         case RBRACE:
2199         case SEMICOLON:
2200         case EOL:
2201         case EOF:
2202             break;
2203 
2204         default:
2205             final IdentNode ident = getIdent();
2206             labelNode = lc.findLabel(ident.getName());
2207 
2208             if (labelNode == null) {
2209                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
2210             }
2211 
2212             break;
2213         }
2214 
2215         final String labelName = labelNode == null ? null : labelNode.getLabelName();
2216         final ParserContextLoopNode targetNode = lc.getContinueTo(labelName);
2217 
2218         if (targetNode == null) {
2219             throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
2220         }
2221 
2222         endOfLine();
2223 
2224         // Construct and add CONTINUE node.
2225         appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
2226     }
2227 
2228     /**
2229      * BreakStatement :
2230      *      break Identifier? ; // [no LineTerminator here]
2231      *
2232      * See 12.8
2233      *
2234      */
2235     private void breakStatement() {
2236         // Capture BREAK token.
2237         final int  breakLine  = line;
2238         final long breakToken = token;
2239         // BREAK tested in caller.
2240         nextOrEOL();
2241 
2242         ParserContextLabelNode labelNode = null;
2243 
2244         // SEMICOLON or label.
2245         switch (type) {
2246         case RBRACE:
2247         case SEMICOLON:
2248         case EOL:
2249         case EOF:
2250             break;
2251 
2252         default:
2253             final IdentNode ident = getIdent();
2254             labelNode = lc.findLabel(ident.getName());
2255 
2256             if (labelNode == null) {
2257                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
2258             }
2259 
2260             break;
2261         }
2262 
2263         //either an explicit label - then get its node or just a "break" - get first breakable
2264         //targetNode is what we are breaking out from.
2265         final String labelName = labelNode == null ? null : labelNode.getLabelName();
2266         final ParserContextBreakableNode targetNode = lc.getBreakable(labelName);
2267         if (targetNode == null) {
2268             throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
2269         }
2270 
2271         endOfLine();
2272 
2273         // Construct and add BREAK node.
2274         appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
2275     }
2276 
2277     /**
2278      * ReturnStatement :
2279      *      return Expression? ; // [no LineTerminator here]
2280      *
2281      * See 12.9
2282      *
2283      * Parse RETURN statement.
2284      */
2285     private void returnStatement() {
2286         // check for return outside function
2287         if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT || lc.getCurrentFunction().getKind() == FunctionNode.Kind.MODULE) {
2288             throw error(AbstractParser.message("invalid.return"));
2289         }
2290 
2291         // Capture RETURN token.
2292         final int  returnLine  = line;
2293         final long returnToken = token;
2294         // RETURN tested in caller.
2295         nextOrEOL();
2296 
2297         Expression expression = null;
2298 
2299         // SEMICOLON or expression.
2300         switch (type) {
2301         case RBRACE:
2302         case SEMICOLON:
2303         case EOL:
2304         case EOF:
2305             break;
2306 
2307         default:
2308             expression = expression();
2309             break;
2310         }
2311 
2312         endOfLine();
2313 
2314         // Construct and add RETURN node.
2315         appendStatement(new ReturnNode(returnLine, returnToken, finish, expression));
2316     }
2317 
2318     /**
2319      * Parse YieldExpression.
2320      *
2321      * YieldExpression[In] :
2322      *   yield
2323      *   yield [no LineTerminator here] AssignmentExpression[?In, Yield]
2324      *   yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
2325      */
2326     private Expression yieldExpression(final boolean noIn) {
2327         assert inGeneratorFunction();
2328         // Capture YIELD token.
2329         long yieldToken = token;
2330         // YIELD tested in caller.
2331         assert type == YIELD;
2332         nextOrEOL();
2333 
2334         Expression expression = null;
2335 
2336         boolean yieldAsterisk = false;
2337         if (type == MUL) {
2338             yieldAsterisk = true;
2339             yieldToken = Token.recast(yieldToken, YIELD_STAR);
2340             next();
2341         }
2342 
2343         switch (type) {
2344         case RBRACE:
2345         case SEMICOLON:
2346         case EOL:
2347         case EOF:
2348         case COMMARIGHT:
2349         case RPAREN:
2350         case RBRACKET:
2351         case COLON:
2352             if (!yieldAsterisk) {
2353                 // treat (yield) as (yield void 0)
2354                 expression = newUndefinedLiteral(yieldToken, finish);
2355                 if (type == EOL) {
2356                     next();
2357                 }
2358                 break;
2359             } else {
2360                 // AssignmentExpression required, fall through
2361             }
2362 
2363         default:
2364             expression = assignmentExpression(noIn);
2365             break;
2366         }
2367 
2368         // Construct and add YIELD node.
2369         return new UnaryNode(yieldToken, expression);
2370     }
2371 
2372     private static UnaryNode newUndefinedLiteral(final long token, final int finish) {
2373         return new UnaryNode(Token.recast(token, VOID), LiteralNode.newInstance(token, finish, 0));
2374     }
2375 
2376     /**
2377      * WithStatement :
2378      *      with ( Expression ) Statement
2379      *
2380      * See 12.10
2381      *
2382      * Parse WITH statement.
2383      */
2384     private void withStatement() {
2385         // Capture WITH token.
2386         final int  withLine  = line;
2387         final long withToken = token;
2388         // WITH tested in caller.
2389         next();
2390 
2391         // ECMA 12.10.1 strict mode restrictions
2392         if (isStrictMode) {
2393             throw error(AbstractParser.message("strict.no.with"), withToken);
2394         }
2395 
2396         expect(LPAREN);
2397         final Expression expression = expression();
2398         expect(RPAREN);
2399         final Block body = getStatement();
2400 
2401         appendStatement(new WithNode(withLine, withToken, finish, expression, body));
2402     }
2403 
2404     /**
2405      * SwitchStatement :
2406      *      switch ( Expression ) CaseBlock
2407      *
2408      * CaseBlock :
2409      *      { CaseClauses? }
2410      *      { CaseClauses? DefaultClause CaseClauses }
2411      *
2412      * CaseClauses :
2413      *      CaseClause
2414      *      CaseClauses CaseClause
2415      *
2416      * CaseClause :
2417      *      case Expression : StatementList?
2418      *
2419      * DefaultClause :
2420      *      default : StatementList?
2421      *
2422      * See 12.11
2423      *
2424      * Parse SWITCH statement.
2425      */
2426     private void switchStatement() {
2427         final int  switchLine  = line;
2428         final long switchToken = token;
2429 
2430         // Block to capture variables declared inside the switch statement.
2431         final ParserContextBlockNode switchBlock = newBlock();
2432 
2433         // SWITCH tested in caller.
2434         next();
2435 
2436         // Create and add switch statement.
2437         final ParserContextSwitchNode switchNode = new ParserContextSwitchNode();
2438         lc.push(switchNode);
2439 
2440         CaseNode defaultCase = null;
2441         // Prepare to accumulate cases.
2442         final List<CaseNode> cases = new ArrayList<>();
2443 
2444         Expression expression = null;
2445 
2446         try {
2447             expect(LPAREN);
2448             expression = expression();
2449             expect(RPAREN);
2450 
2451             expect(LBRACE);
2452 
2453 
2454             while (type != RBRACE) {
2455                 // Prepare for next case.
2456                 Expression caseExpression = null;
2457                 final long caseToken = token;
2458 
2459                 switch (type) {
2460                 case CASE:
2461                     next();
2462                     caseExpression = expression();
2463                     break;
2464 
2465                 case DEFAULT:
2466                     if (defaultCase != null) {
2467                         throw error(AbstractParser.message("duplicate.default.in.switch"));
2468                     }
2469                     next();
2470                     break;
2471 
2472                 default:
2473                     // Force an error.
2474                     expect(CASE);
2475                     break;
2476                 }
2477 
2478                 expect(COLON);
2479 
2480                 // Get CASE body.
2481                 final Block statements = getBlock(false); // TODO: List<Statement> statements = caseStatementList();
2482                 final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
2483 
2484                 if (caseExpression == null) {
2485                     defaultCase = caseNode;
2486                 }
2487 
2488                 cases.add(caseNode);
2489             }
2490 
2491             next();
2492         } finally {
2493             lc.pop(switchNode);
2494             restoreBlock(switchBlock);
2495         }
2496 
2497         final SwitchNode switchStatement = new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase);
2498         appendStatement(new BlockStatement(switchLine, new Block(switchToken, finish, switchBlock.getFlags() | Block.IS_SYNTHETIC | Block.IS_SWITCH_BLOCK, switchStatement)));
2499     }
2500 
2501     /**
2502      * LabelledStatement :
2503      *      Identifier : Statement
2504      *
2505      * See 12.12
2506      *
2507      * Parse label statement.
2508      */
2509     private void labelStatement() {
2510         // Capture label token.
2511         final long labelToken = token;
2512         // Get label ident.
2513         final IdentNode ident = getIdent();
2514 
2515         expect(COLON);
2516 
2517         if (lc.findLabel(ident.getName()) != null) {
2518             throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
2519         }
2520 
2521         final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName());
2522         Block body = null;
2523         try {
2524             lc.push(labelNode);
2525             body = getStatement(true);
2526         } finally {
2527             assert lc.peek() instanceof ParserContextLabelNode;
2528             lc.pop(labelNode);
2529         }
2530 
2531         appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
2532     }
2533 
2534     /**
2535      * ThrowStatement :
2536      *      throw Expression ; // [no LineTerminator here]
2537      *
2538      * See 12.13
2539      *
2540      * Parse throw statement.
2541      */
2542     private void throwStatement() {
2543         // Capture THROW token.
2544         final int  throwLine  = line;
2545         final long throwToken = token;
2546         // THROW tested in caller.
2547         nextOrEOL();
2548 
2549         Expression expression = null;
2550 
2551         // SEMICOLON or expression.
2552         switch (type) {
2553         case RBRACE:
2554         case SEMICOLON:
2555         case EOL:
2556             break;
2557 
2558         default:
2559             expression = expression();
2560             break;
2561         }
2562 
2563         if (expression == null) {
2564             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2565         }
2566 
2567         endOfLine();
2568 
2569         appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
2570     }
2571 
2572     /**
2573      * TryStatement :
2574      *      try Block Catch
2575      *      try Block Finally
2576      *      try Block Catch Finally
2577      *
2578      * Catch :
2579      *      catch( Identifier if Expression ) Block
2580      *      catch( Identifier ) Block
2581      *
2582      * Finally :
2583      *      finally Block
2584      *
2585      * See 12.14
2586      *
2587      * Parse TRY statement.
2588      */
2589     private void tryStatement() {
2590         // Capture TRY token.
2591         final int  tryLine  = line;
2592         final long tryToken = token;
2593         // TRY tested in caller.
2594         next();
2595 
2596         // Container block needed to act as target for labeled break statements
2597         final int startLine = line;
2598         final ParserContextBlockNode outer = newBlock();
2599         // Create try.
2600 
2601         try {
2602             final Block       tryBody     = getBlock(true);
2603             final List<Block> catchBlocks = new ArrayList<>();
2604 
2605             while (type == CATCH) {
2606                 final int  catchLine  = line;
2607                 final long catchToken = token;
2608                 next();
2609                 expect(LPAREN);
2610                 final IdentNode exception = getIdent();
2611 
2612                 // ECMA 12.4.1 strict mode restrictions
2613                 verifyStrictIdent(exception, "catch argument");
2614 
2615                 // Nashorn extension: catch clause can have optional
2616                 // condition. So, a single try can have more than one
2617                 // catch clause each with it's own condition.
2618                 final Expression ifExpression;
2619                 if (!env._no_syntax_extensions && type == IF) {
2620                     next();
2621                     // Get the exception condition.
2622                     ifExpression = expression();
2623                 } else {
2624                     ifExpression = null;
2625                 }
2626 
2627                 expect(RPAREN);
2628 
2629                 final ParserContextBlockNode catchBlock = newBlock();
2630                 try {
2631                     // Get CATCH body.
2632                     final Block catchBody = getBlock(true);
2633                     final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
2634                     appendStatement(catchNode);
2635                 } finally {
2636                     restoreBlock(catchBlock);
2637                     catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements()));
2638                 }
2639 
2640                 // If unconditional catch then should to be the end.
2641                 if (ifExpression == null) {
2642                     break;
2643                 }
2644             }
2645 
2646             // Prepare to capture finally statement.
2647             Block finallyStatements = null;
2648 
2649             if (type == FINALLY) {
2650                 next();
2651                 finallyStatements = getBlock(true);
2652             }
2653 
2654             // Need at least one catch or a finally.
2655             if (catchBlocks.isEmpty() && finallyStatements == null) {
2656                 throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
2657             }
2658 
2659             final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
2660             // Add try.
2661             assert lc.peek() == outer;
2662             appendStatement(tryNode);
2663         } finally {
2664             restoreBlock(outer);
2665         }
2666 
2667         appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements())));
2668     }
2669 
2670     /**
2671      * DebuggerStatement :
2672      *      debugger ;
2673      *
2674      * See 12.15
2675      *
2676      * Parse debugger statement.
2677      */
2678     private void  debuggerStatement() {
2679         // Capture DEBUGGER token.
2680         final int  debuggerLine  = line;
2681         final long debuggerToken = token;
2682         // DEBUGGER tested in caller.
2683         next();
2684         endOfLine();
2685         appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish));
2686     }
2687 
2688     /**
2689      * PrimaryExpression :
2690      *      this
2691      *      IdentifierReference
2692      *      Literal
2693      *      ArrayLiteral
2694      *      ObjectLiteral
2695      *      RegularExpressionLiteral
2696      *      TemplateLiteral
2697      *      CoverParenthesizedExpressionAndArrowParameterList
2698      *
2699      * CoverParenthesizedExpressionAndArrowParameterList :
2700      *      ( Expression )
2701      *      ( )
2702      *      ( ... BindingIdentifier )
2703      *      ( Expression , ... BindingIdentifier )
2704      *
2705      * Parse primary expression.
2706      * @return Expression node.
2707      */
2708     @SuppressWarnings("fallthrough")
2709     private Expression primaryExpression() {
2710         // Capture first token.
2711         final int  primaryLine  = line;
2712         final long primaryToken = token;
2713 
2714         switch (type) {
2715         case THIS:
2716             final String name = type.getName();
2717             next();
2718             markThis(lc);
2719             return new IdentNode(primaryToken, finish, name);
2720         case IDENT:
2721             final IdentNode ident = getIdent();
2722             if (ident == null) {
2723                 break;
2724             }
2725             detectSpecialProperty(ident);
2726             return ident;
2727         case OCTAL_LEGACY:
2728             if (isStrictMode) {
2729                throw error(AbstractParser.message("strict.no.octal"), token);
2730             }
2731         case STRING:
2732         case ESCSTRING:
2733         case DECIMAL:
2734         case HEXADECIMAL:
2735         case OCTAL:
2736         case BINARY_NUMBER:
2737         case FLOATING:
2738         case REGEX:
2739         case XML:
2740             return getLiteral();
2741         case EXECSTRING:
2742             return execString(primaryLine, primaryToken);
2743         case FALSE:
2744             next();
2745             return LiteralNode.newInstance(primaryToken, finish, false);
2746         case TRUE:
2747             next();
2748             return LiteralNode.newInstance(primaryToken, finish, true);
2749         case NULL:
2750             next();
2751             return LiteralNode.newInstance(primaryToken, finish);
2752         case LBRACKET:
2753             return arrayLiteral();
2754         case LBRACE:
2755             return objectLiteral();
2756         case LPAREN:
2757             next();
2758 
2759             if (isES6()) {
2760                 if (type == RPAREN) {
2761                     // ()
2762                     nextOrEOL();
2763                     expectDontAdvance(ARROW);
2764                     return new ExpressionList(primaryToken, finish, Collections.emptyList());
2765                 } else if (type == ELLIPSIS) {
2766                     // (...rest)
2767                     final IdentNode restParam = formalParameterList(false).get(0);
2768                     expectDontAdvance(RPAREN);
2769                     nextOrEOL();
2770                     expectDontAdvance(ARROW);
2771                     return new ExpressionList(primaryToken, finish, Collections.singletonList(restParam));
2772                 }
2773             }
2774 
2775             final Expression expression = expression();
2776 
2777             expect(RPAREN);
2778 
2779             return expression;
2780         case TEMPLATE:
2781         case TEMPLATE_HEAD:
2782             return templateLiteral();
2783 
2784         default:
2785             // In this context some operator tokens mark the start of a literal.
2786             if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
2787                 next();
2788                 return getLiteral();
2789             }
2790             if (isNonStrictModeIdent()) {
2791                 return getIdent();
2792             }
2793             break;
2794         }
2795 
2796         return null;
2797     }
2798 
2799     /**
2800      * Convert execString to a call to $EXEC.
2801      *
2802      * @param primaryToken Original string token.
2803      * @return callNode to $EXEC.
2804      */
2805     CallNode execString(final int primaryLine, final long primaryToken) {
2806         // Synthesize an ident to call $EXEC.
2807         final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
2808         // Skip over EXECSTRING.
2809         next();
2810         // Set up argument list for call.
2811         // Skip beginning of edit string expression.
2812         expect(LBRACE);
2813         // Add the following expression to arguments.
2814         final List<Expression> arguments = Collections.singletonList(expression());
2815         // Skip ending of edit string expression.
2816         expect(RBRACE);
2817 
2818         return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
2819     }
2820 
2821     /**
2822      * ArrayLiteral :
2823      *      [ Elision? ]
2824      *      [ ElementList ]
2825      *      [ ElementList , Elision? ]
2826      *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
2827      *
2828      * ElementList : Elision? AssignmentExpression
2829      *      ElementList , Elision? AssignmentExpression
2830      *
2831      * Elision :
2832      *      ,
2833      *      Elision ,
2834      *
2835      * See 12.1.4
2836      * JavaScript 1.8
2837      *
2838      * Parse array literal.
2839      * @return Expression node.
2840      */
2841     private LiteralNode<Expression[]> arrayLiteral() {
2842         // Capture LBRACKET token.
2843         final long arrayToken = token;
2844         // LBRACKET tested in caller.
2845         next();
2846 
2847         // Prepare to accumulate elements.
2848         final List<Expression> elements = new ArrayList<>();
2849         // Track elisions.
2850         boolean elision = true;
2851         loop:
2852         while (true) {
2853             long spreadToken = 0;
2854             switch (type) {
2855             case RBRACKET:
2856                 next();
2857 
2858                 break loop;
2859 
2860             case COMMARIGHT:
2861                 next();
2862 
2863                 // If no prior expression
2864                 if (elision) {
2865                     elements.add(null);
2866                 }
2867 
2868                 elision = true;
2869 
2870                 break;
2871 
2872             case ELLIPSIS:
2873                 if (isES6()) {
2874                     spreadToken = token;
2875                     next();
2876                 }
2877                 // fall through
2878 
2879             default:
2880                 if (!elision) {
2881                     throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2882                 }
2883 
2884                 // Add expression element.
2885                 Expression expression = assignmentExpression(false);
2886                 if (expression != null) {
2887                     if (spreadToken != 0) {
2888                         expression = new UnaryNode(Token.recast(spreadToken, SPREAD_ARRAY), expression);
2889                     }
2890                     elements.add(expression);
2891                 } else {
2892                     expect(RBRACKET);
2893                 }
2894 
2895                 elision = false;
2896                 break;
2897             }
2898         }
2899 
2900         return LiteralNode.newInstance(arrayToken, finish, elements);
2901     }
2902 
2903     /**
2904      * ObjectLiteral :
2905      *      { }
2906      *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2907      *
2908      * PropertyNameAndValueList :
2909      *      PropertyAssignment
2910      *      PropertyNameAndValueList , PropertyAssignment
2911      *
2912      * See 11.1.5
2913      *
2914      * Parse an object literal.
2915      * @return Expression node.
2916      */
2917     private ObjectNode objectLiteral() {
2918         // Capture LBRACE token.
2919         final long objectToken = token;
2920         // LBRACE tested in caller.
2921         next();
2922 
2923         // Object context.
2924         // Prepare to accumulate elements.
2925         final List<PropertyNode> elements = new ArrayList<>();
2926         final Map<String, Integer> map = new HashMap<>();
2927 
2928         // Create a block for the object literal.
2929         boolean commaSeen = true;
2930         loop:
2931         while (true) {
2932             switch (type) {
2933                 case RBRACE:
2934                     next();
2935                     break loop;
2936 
2937                 case COMMARIGHT:
2938                     if (commaSeen) {
2939                         throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2940                     }
2941                     next();
2942                     commaSeen = true;
2943                     break;
2944 
2945                 default:
2946                     if (!commaSeen) {
2947                         throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2948                     }
2949 
2950                     commaSeen = false;
2951                     // Get and add the next property.
2952                     final PropertyNode property = propertyAssignment();
2953 
2954                     if (property.isComputed()) {
2955                         elements.add(property);
2956                         break;
2957                     }
2958 
2959                     final String key = property.getKeyName();
2960                     final Integer existing = map.get(key);
2961 
2962                     if (existing == null) {
2963                         map.put(key, elements.size());
2964                         elements.add(property);
2965                         break;
2966                     }
2967 
2968                     final PropertyNode existingProperty = elements.get(existing);
2969 
2970                     // ECMA section 11.1.5 Object Initialiser
2971                     // point # 4 on property assignment production
2972                     final Expression   value  = property.getValue();
2973                     final FunctionNode getter = property.getGetter();
2974                     final FunctionNode setter = property.getSetter();
2975 
2976                     final Expression   prevValue  = existingProperty.getValue();
2977                     final FunctionNode prevGetter = existingProperty.getGetter();
2978                     final FunctionNode prevSetter = existingProperty.getSetter();
2979 
2980                     if (!isES6()) {
2981                         checkPropertyRedefinition(property, value, getter, setter, prevValue, prevGetter, prevSetter);
2982                     } else {
2983                         if (property.getKey() instanceof IdentNode && ((IdentNode)property.getKey()).isProtoPropertyName() &&
2984                                         existingProperty.getKey() instanceof IdentNode && ((IdentNode)existingProperty.getKey()).isProtoPropertyName()) {
2985                             throw error(AbstractParser.message("multiple.proto.key"), property.getToken());
2986                         }
2987                     }
2988 
2989                     if (value != null || prevValue != null) {
2990                         map.put(key, elements.size());
2991                         elements.add(property);
2992                     } else if (getter != null) {
2993                         assert prevGetter != null || prevSetter != null;
2994                         elements.set(existing, existingProperty.setGetter(getter));
2995                     } else if (setter != null) {
2996                         assert prevGetter != null || prevSetter != null;
2997                         elements.set(existing, existingProperty.setSetter(setter));
2998                     }
2999                     break;
3000             }
3001         }
3002 
3003         return new ObjectNode(objectToken, finish, elements);
3004     }
3005 
3006     private void checkPropertyRedefinition(final PropertyNode property, final Expression value, final FunctionNode getter, final FunctionNode setter, final Expression prevValue, final FunctionNode prevGetter, final FunctionNode prevSetter) {
3007         // ECMA 11.1.5 strict mode restrictions
3008         if (isStrictMode && value != null && prevValue != null) {
3009             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3010         }
3011 
3012         final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
3013         final boolean isAccessor     = getter != null     || setter != null;
3014 
3015         // data property redefined as accessor property
3016         if (prevValue != null && isAccessor) {
3017             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3018         }
3019 
3020         // accessor property redefined as data
3021         if (isPrevAccessor && value != null) {
3022             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3023         }
3024 
3025         if (isAccessor && isPrevAccessor) {
3026             if (getter != null && prevGetter != null ||
3027                     setter != null && prevSetter != null) {
3028                 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3029             }
3030         }
3031     }
3032 
3033     /**
3034      * LiteralPropertyName :
3035      *      IdentifierName
3036      *      StringLiteral
3037      *      NumericLiteral
3038      *
3039      * @return PropertyName node
3040      */
3041     @SuppressWarnings("fallthrough")
3042     private PropertyKey literalPropertyName() {
3043         switch (type) {
3044         case IDENT:
3045             return getIdent().setIsPropertyName();
3046         case OCTAL_LEGACY:
3047             if (isStrictMode) {
3048                 throw error(AbstractParser.message("strict.no.octal"), token);
3049             }
3050         case STRING:
3051         case ESCSTRING:
3052         case DECIMAL:
3053         case HEXADECIMAL:
3054         case OCTAL:
3055         case BINARY_NUMBER:
3056         case FLOATING:
3057             return getLiteral();
3058         default:
3059             return getIdentifierName().setIsPropertyName();
3060         }
3061     }
3062 
3063     /**
3064      * ComputedPropertyName :
3065      *      AssignmentExpression
3066      *
3067      * @return PropertyName node
3068      */
3069     private Expression computedPropertyName() {
3070         expect(LBRACKET);
3071         Expression expression = assignmentExpression(false);
3072         expect(RBRACKET);
3073         return expression;
3074     }
3075 
3076     /**
3077      * PropertyName :
3078      *      LiteralPropertyName
3079      *      ComputedPropertyName
3080      *
3081      * @return PropertyName node
3082      */
3083     private Expression propertyName() {
3084         if (type == LBRACKET && isES6()) {
3085             return computedPropertyName();
3086         } else {
3087             return (Expression)literalPropertyName();
3088         }
3089     }
3090 
3091     /**
3092      * PropertyAssignment :
3093      *      PropertyName : AssignmentExpression
3094      *      get PropertyName ( ) { FunctionBody }
3095      *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
3096      *
3097      * PropertySetParameterList :
3098      *      Identifier
3099      *
3100      * PropertyName :
3101      *      IdentifierName
3102      *      StringLiteral
3103      *      NumericLiteral
3104      *
3105      * See 11.1.5
3106      *
3107      * Parse an object literal property.
3108      * @return Property or reference node.
3109      */
3110     private PropertyNode propertyAssignment() {
3111         // Capture firstToken.
3112         final long propertyToken = token;
3113         final int  functionLine  = line;
3114 
3115         final Expression propertyName;
3116         final boolean isIdentifier;
3117 
3118         boolean generator = false;
3119         if (type == MUL && isES6()) {
3120             generator = true;
3121             next();
3122         }
3123 
3124         final boolean computed = type == LBRACKET;
3125         if (type == IDENT) {
3126             // Get IDENT.
3127             final String ident = (String)expectValue(IDENT);
3128 
3129             if (type != COLON && (type != LPAREN || !isES6())) {
3130                 final long getSetToken = propertyToken;
3131 
3132                 switch (ident) {
3133                 case "get":
3134                     final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
3135                     return new PropertyNode(propertyToken, finish, getter.key, null, getter.functionNode, null, false, getter.computed);
3136 
3137                 case "set":
3138                     final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
3139                     return new PropertyNode(propertyToken, finish, setter.key, null, null, setter.functionNode, false, setter.computed);
3140                 default:
3141                     break;
3142                 }
3143             }
3144 
3145             isIdentifier = true;
3146             IdentNode identNode = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
3147             if (type == COLON && ident.equals("__proto__")) {
3148                 identNode = identNode.setIsProtoPropertyName();
3149             }
3150             propertyName = identNode;
3151         } else {
3152             isIdentifier = isNonStrictModeIdent();
3153             propertyName = propertyName();
3154         }
3155 
3156         Expression propertyValue;
3157 
3158         if (generator) {
3159             expectDontAdvance(LPAREN);
3160         }
3161 
3162         if (type == LPAREN && isES6()) {
3163             propertyValue = propertyMethodFunction(propertyName, propertyToken, functionLine, generator, FunctionNode.ES6_IS_METHOD, computed).functionNode;
3164         } else if (isIdentifier && (type == COMMARIGHT || type == RBRACE || type == ASSIGN) && isES6()) {
3165             propertyValue = createIdentNode(propertyToken, finish, ((IdentNode) propertyName).getPropertyName());
3166             if (type == ASSIGN && isES6()) {
3167                 // TODO if not destructuring, this is a SyntaxError
3168                 final long assignToken = token;
3169                 next();
3170                 final Expression rhs = assignmentExpression(false);
3171                 propertyValue = verifyAssignment(assignToken, propertyValue, rhs);
3172             }
3173         } else {
3174             expect(COLON);
3175 
3176             defaultNames.push(propertyName);
3177             try {
3178                 propertyValue = assignmentExpression(false);
3179             } finally {
3180                 defaultNames.pop();
3181             }
3182         }
3183 
3184         return new PropertyNode(propertyToken, finish, propertyName, propertyValue, null, null, false, computed);
3185     }
3186 
3187     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
3188         return propertyGetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
3189     }
3190 
3191     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine, final int flags) {
3192         final boolean computed = type == LBRACKET;
3193         final Expression propertyName = propertyName();
3194         final String getterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
3195         final IdentNode getNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("get " + getterName));
3196         expect(LPAREN);
3197         expect(RPAREN);
3198 
3199         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
3200         functionNode.setFlag(flags);
3201         if (computed) {
3202             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3203         }
3204         lc.push(functionNode);
3205 
3206         Block functionBody;
3207 
3208 
3209         try {
3210             functionBody = functionBody(functionNode);
3211         } finally {
3212             lc.pop(functionNode);
3213         }
3214 
3215         final FunctionNode  function = createFunctionNode(
3216                 functionNode,
3217                 getSetToken,
3218                 getNameNode,
3219                 Collections.<IdentNode>emptyList(),
3220                 FunctionNode.Kind.GETTER,
3221                 functionLine,
3222                 functionBody);
3223 
3224         return new PropertyFunction(propertyName, function, computed);
3225     }
3226 
3227     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
3228         return propertySetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
3229     }
3230 
3231     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine, final int flags) {
3232         final boolean computed = type == LBRACKET;
3233         final Expression propertyName = propertyName();
3234         final String setterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
3235         final IdentNode setNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("set " + setterName));
3236         expect(LPAREN);
3237         // be sloppy and allow missing setter parameter even though
3238         // spec does not permit it!
3239         final IdentNode argIdent;
3240         if (isBindingIdentifier()) {
3241             argIdent = getIdent();
3242             verifyIdent(argIdent, "setter argument");
3243         } else {
3244             argIdent = null;
3245         }
3246         expect(RPAREN);
3247         final List<IdentNode> parameters = new ArrayList<>();
3248         if (argIdent != null) {
3249             parameters.add(argIdent);
3250         }
3251 
3252 
3253         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
3254         functionNode.setFlag(flags);
3255         if (computed) {
3256             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3257         }
3258         lc.push(functionNode);
3259 
3260         Block functionBody;
3261         try {
3262             functionBody = functionBody(functionNode);
3263         } finally {
3264             lc.pop(functionNode);
3265         }
3266 
3267 
3268         final FunctionNode  function = createFunctionNode(
3269                 functionNode,
3270                 getSetToken,
3271                 setNameNode,
3272                 parameters,
3273                 FunctionNode.Kind.SETTER,
3274                 functionLine,
3275                 functionBody);
3276 
3277         return new PropertyFunction(propertyName, function, computed);
3278     }
3279 
3280     private PropertyFunction propertyMethodFunction(Expression key, final long methodToken, final int methodLine, final boolean generator, final int flags, boolean computed) {
3281         final String methodName = key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : getDefaultValidFunctionName(methodLine, false);
3282         final IdentNode methodNameNode = createIdentNode(((Node)key).getToken(), finish, methodName);
3283 
3284         FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
3285         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(methodNameNode, methodToken, functionKind, methodLine, null);
3286         functionNode.setFlag(flags);
3287         if (computed) {
3288             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3289         }
3290         lc.push(functionNode);
3291 
3292         try {
3293             final ParserContextBlockNode parameterBlock = newBlock();
3294             final List<IdentNode> parameters;
3295             try {
3296                 expect(LPAREN);
3297                 parameters = formalParameterList(generator);
3298                 functionNode.setParameters(parameters);
3299                 expect(RPAREN);
3300             } finally {
3301                 restoreBlock(parameterBlock);
3302             }
3303 
3304             Block functionBody = functionBody(functionNode);
3305 
3306             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
3307 
3308             final FunctionNode  function = createFunctionNode(
3309                             functionNode,
3310                             methodToken,
3311                             methodNameNode,
3312                             parameters,
3313                             functionKind,
3314                             methodLine,
3315                             functionBody);
3316             return new PropertyFunction(key, function, computed);
3317         } finally {
3318             lc.pop(functionNode);
3319         }
3320     }
3321 
3322     private static class PropertyFunction {
3323         final Expression key;
3324         final FunctionNode functionNode;
3325         final boolean computed;
3326 
3327         PropertyFunction(final Expression key, final FunctionNode function, final boolean computed) {
3328             this.key = key;
3329             this.functionNode = function;
3330             this.computed = computed;
3331         }
3332     }
3333 
3334     /**
3335      * LeftHandSideExpression :
3336      *      NewExpression
3337      *      CallExpression
3338      *
3339      * CallExpression :
3340      *      MemberExpression Arguments
3341      *      SuperCall
3342      *      CallExpression Arguments
3343      *      CallExpression [ Expression ]
3344      *      CallExpression . IdentifierName
3345      *
3346      * SuperCall :
3347      *      super Arguments
3348      *
3349      * See 11.2
3350      *
3351      * Parse left hand side expression.
3352      * @return Expression node.
3353      */
3354     private Expression leftHandSideExpression() {
3355         int  callLine  = line;
3356         long callToken = token;
3357 
3358         Expression lhs = memberExpression();
3359 
3360         if (type == LPAREN) {
3361             final List<Expression> arguments = optimizeList(argumentList());
3362 
3363             // Catch special functions.
3364             if (lhs instanceof IdentNode) {
3365                 detectSpecialFunction((IdentNode)lhs);
3366             }
3367 
3368             lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3369         }
3370 
3371         loop:
3372         while (true) {
3373             // Capture token.
3374             callLine  = line;
3375             callToken = token;
3376 
3377             switch (type) {
3378             case LPAREN: {
3379                 // Get NEW or FUNCTION arguments.
3380                 final List<Expression> arguments = optimizeList(argumentList());
3381 
3382                 // Create call node.
3383                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3384 
3385                 break;
3386             }
3387             case LBRACKET: {
3388                 next();
3389 
3390                 // Get array index.
3391                 final Expression rhs = expression();
3392 
3393                 expect(RBRACKET);
3394 
3395                 // Create indexing node.
3396                 lhs = new IndexNode(callToken, finish, lhs, rhs);
3397 
3398                 break;
3399             }
3400             case PERIOD: {
3401                 next();
3402 
3403                 final IdentNode property = getIdentifierName();
3404 
3405                 // Create property access node.
3406                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
3407 
3408                 break;
3409             }
3410             case TEMPLATE:
3411             case TEMPLATE_HEAD: {
3412                 // tagged template literal
3413                 final List<Expression> arguments = templateLiteralArgumentList();
3414 
3415                 // Create call node.
3416                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3417 
3418                 break;
3419             }
3420             default:
3421                 break loop;
3422             }
3423         }
3424 
3425         return lhs;
3426     }
3427 
3428     /**
3429      * NewExpression :
3430      *      MemberExpression
3431      *      new NewExpression
3432      *
3433      * See 11.2
3434      *
3435      * Parse new expression.
3436      * @return Expression node.
3437      */
3438     private Expression newExpression() {
3439         final long newToken = token;
3440         // NEW is tested in caller.
3441         next();
3442 
3443         if (type == PERIOD && isES6()) {
3444             next();
3445             if (type == IDENT && "target".equals(getValue())) {
3446                 if (lc.getCurrentFunction().isProgram()) {
3447                     throw error(AbstractParser.message("new.target.in.function"), token);
3448                 }
3449                 next();
3450                 markNewTarget(lc);
3451                 return new IdentNode(newToken, finish, "new.target");
3452             } else {
3453                 throw error(AbstractParser.message("expected.target"), token);
3454             }
3455         }
3456 
3457         // Get function base.
3458         final int  callLine    = line;
3459         final Expression constructor = memberExpression();
3460         if (constructor == null) {
3461             return null;
3462         }
3463         // Get arguments.
3464         ArrayList<Expression> arguments;
3465 
3466         // Allow for missing arguments.
3467         if (type == LPAREN) {
3468             arguments = argumentList();
3469         } else {
3470             arguments = new ArrayList<>();
3471         }
3472 
3473         // Nashorn extension: This is to support the following interface implementation
3474         // syntax:
3475         //
3476         //     var r = new java.lang.Runnable() {
3477         //         run: function() { println("run"); }
3478         //     };
3479         //
3480         // The object literal following the "new Constructor()" expression
3481         // is passed as an additional (last) argument to the constructor.
3482         if (!env._no_syntax_extensions && type == LBRACE) {
3483             arguments.add(objectLiteral());
3484         }
3485 
3486         final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
3487 
3488         return new UnaryNode(newToken, callNode);
3489     }
3490 
3491     /**
3492      * MemberExpression :
3493      *      PrimaryExpression
3494      *        FunctionExpression
3495      *        ClassExpression
3496      *        GeneratorExpression
3497      *      MemberExpression [ Expression ]
3498      *      MemberExpression . IdentifierName
3499      *      MemberExpression TemplateLiteral
3500      *      SuperProperty
3501      *      MetaProperty
3502      *      new MemberExpression Arguments
3503      *
3504      * SuperProperty :
3505      *      super [ Expression ]
3506      *      super . IdentifierName
3507      *
3508      * MetaProperty :
3509      *      NewTarget
3510      *
3511      * Parse member expression.
3512      * @return Expression node.
3513      */
3514     @SuppressWarnings("fallthrough")
3515     private Expression memberExpression() {
3516         // Prepare to build operation.
3517         Expression lhs;
3518         boolean isSuper = false;
3519 
3520         switch (type) {
3521         case NEW:
3522             // Get new expression.
3523             lhs = newExpression();
3524             break;
3525 
3526         case FUNCTION:
3527             // Get function expression.
3528             lhs = functionExpression(false, false);
3529             break;
3530 
3531         case CLASS:
3532             if (isES6()) {
3533                 lhs = classExpression(false);
3534                 break;
3535             } else {
3536                 // fall through
3537             }
3538 
3539         case SUPER:
3540             if (isES6()) {
3541                 final ParserContextFunctionNode currentFunction = getCurrentNonArrowFunction();
3542                 if (currentFunction.isMethod()) {
3543                     long identToken = Token.recast(token, IDENT);
3544                     next();
3545                     lhs = createIdentNode(identToken, finish, SUPER.getName());
3546 
3547                     switch (type) {
3548                         case LBRACKET:
3549                         case PERIOD:
3550                             getCurrentNonArrowFunction().setFlag(FunctionNode.ES6_USES_SUPER);
3551                             isSuper = true;
3552                             break;
3553                         case LPAREN:
3554                             if (currentFunction.isSubclassConstructor()) {
3555                                 lhs = ((IdentNode)lhs).setIsDirectSuper();
3556                                 break;
3557                             } else {
3558                                 // fall through to throw error
3559                             }
3560                         default:
3561                             throw error(AbstractParser.message("invalid.super"), identToken);
3562                     }
3563                     break;
3564                 } else {
3565                     // fall through
3566                 }
3567             } else {
3568                 // fall through
3569             }
3570 
3571         default:
3572             // Get primary expression.
3573             lhs = primaryExpression();
3574             break;
3575         }
3576 
3577         loop:
3578         while (true) {
3579             // Capture token.
3580             final long callToken = token;
3581 
3582             switch (type) {
3583             case LBRACKET: {
3584                 next();
3585 
3586                 // Get array index.
3587                 final Expression index = expression();
3588 
3589                 expect(RBRACKET);
3590 
3591                 // Create indexing node.
3592                 lhs = new IndexNode(callToken, finish, lhs, index);
3593 
3594                 if (isSuper) {
3595                     isSuper = false;
3596                     lhs = ((BaseNode) lhs).setIsSuper();
3597                 }
3598 
3599                 break;
3600             }
3601             case PERIOD: {
3602                 if (lhs == null) {
3603                     throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3604                 }
3605 
3606                 next();
3607 
3608                 final IdentNode property = getIdentifierName();
3609 
3610                 // Create property access node.
3611                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
3612 
3613                 if (isSuper) {
3614                     isSuper = false;
3615                     lhs = ((BaseNode) lhs).setIsSuper();
3616                 }
3617 
3618                 break;
3619             }
3620             case TEMPLATE:
3621             case TEMPLATE_HEAD: {
3622                 // tagged template literal
3623                 final int callLine = line;
3624                 final List<Expression> arguments = templateLiteralArgumentList();
3625 
3626                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3627 
3628                 break;
3629             }
3630             default:
3631                 break loop;
3632             }
3633         }
3634 
3635         return lhs;
3636     }
3637 
3638     /**
3639      * Arguments :
3640      *      ( )
3641      *      ( ArgumentList )
3642      *
3643      * ArgumentList :
3644      *      AssignmentExpression
3645      *      ... AssignmentExpression
3646      *      ArgumentList , AssignmentExpression
3647      *      ArgumentList , ... AssignmentExpression
3648      *
3649      * See 11.2
3650      *
3651      * Parse function call arguments.
3652      * @return Argument list.
3653      */
3654     private ArrayList<Expression> argumentList() {
3655         // Prepare to accumulate list of arguments.
3656         final ArrayList<Expression> nodeList = new ArrayList<>();
3657         // LPAREN tested in caller.
3658         next();
3659 
3660         // Track commas.
3661         boolean first = true;
3662 
3663         while (type != RPAREN) {
3664             // Comma prior to every argument except the first.
3665             if (!first) {
3666                 expect(COMMARIGHT);
3667             } else {
3668                 first = false;
3669             }
3670 
3671             long spreadToken = 0;
3672             if (type == ELLIPSIS && isES6()) {
3673                 spreadToken = token;
3674                 next();
3675             }
3676 
3677             // Get argument expression.
3678             Expression expression = assignmentExpression(false);
3679             if (spreadToken != 0) {
3680                 expression = new UnaryNode(Token.recast(spreadToken, TokenType.SPREAD_ARGUMENT), expression);
3681             }
3682             nodeList.add(expression);
3683         }
3684 
3685         expect(RPAREN);
3686         return nodeList;
3687     }
3688 
3689     private static <T> List<T> optimizeList(final ArrayList<T> list) {
3690         switch(list.size()) {
3691             case 0: {
3692                 return Collections.emptyList();
3693             }
3694             case 1: {
3695                 return Collections.singletonList(list.get(0));
3696             }
3697             default: {
3698                 list.trimToSize();
3699                 return list;
3700             }
3701         }
3702     }
3703 
3704     /**
3705      * FunctionDeclaration :
3706      *      function Identifier ( FormalParameterList? ) { FunctionBody }
3707      *
3708      * FunctionExpression :
3709      *      function Identifier? ( FormalParameterList? ) { FunctionBody }
3710      *
3711      * See 13
3712      *
3713      * Parse function declaration.
3714      * @param isStatement True if for is a statement.
3715      *
3716      * @return Expression node.
3717      */
3718     private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
3719         final long functionToken = token;
3720         final int  functionLine  = line;
3721         // FUNCTION is tested in caller.
3722         assert type == FUNCTION;
3723         next();
3724 
3725         boolean generator = false;
3726         if (type == MUL && isES6()) {
3727             generator = true;
3728             next();
3729         }
3730 
3731         IdentNode name = null;
3732 
3733         if (isBindingIdentifier()) {
3734             if (type == YIELD && ((!isStatement && generator) || (isStatement && inGeneratorFunction()))) {
3735                 // 12.1.1 Early SyntaxError if:
3736                 // GeneratorExpression with BindingIdentifier yield
3737                 // HoistableDeclaration with BindingIdentifier yield in generator function body
3738                 expect(IDENT);
3739             }
3740             name = getIdent();
3741             verifyStrictIdent(name, "function name");
3742         } else if (isStatement) {
3743             // Nashorn extension: anonymous function statements.
3744             // Do not allow anonymous function statement if extensions
3745             // are now allowed. But if we are reparsing then anon function
3746             // statement is possible - because it was used as function
3747             // expression in surrounding code.
3748             if (env._no_syntax_extensions && reparsedFunction == null) {
3749                 expect(IDENT);
3750             }
3751         }
3752 
3753         // name is null, generate anonymous name
3754         boolean isAnonymous = false;
3755         if (name == null) {
3756             final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
3757             name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
3758             isAnonymous = true;
3759         }
3760 
3761         FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
3762         List<IdentNode> parameters = Collections.emptyList();
3763         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, functionKind, functionLine, parameters);
3764         lc.push(functionNode);
3765 
3766         Block functionBody = null;
3767         // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
3768         // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
3769         hideDefaultName();
3770         try {
3771             final ParserContextBlockNode parameterBlock = newBlock();
3772             try {
3773                 expect(LPAREN);
3774                 parameters = formalParameterList(generator);
3775                 functionNode.setParameters(parameters);
3776                 expect(RPAREN);
3777             } finally {
3778                 restoreBlock(parameterBlock);
3779             }
3780 
3781             functionBody = functionBody(functionNode);
3782 
3783             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
3784         } finally {
3785             defaultNames.pop();
3786             lc.pop(functionNode);
3787         }
3788 
3789         if (isStatement) {
3790             if (topLevel || useBlockScope() || (!isStrictMode && env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ACCEPT)) {
3791                 functionNode.setFlag(FunctionNode.IS_DECLARED);
3792             } else if (isStrictMode) {
3793                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
3794             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
3795                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
3796             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
3797                 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
3798             }
3799             if (isArguments(name)) {
3800                lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
3801             }
3802         }
3803 
3804         if (isAnonymous) {
3805             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3806         }
3807 
3808         verifyParameterList(parameters, functionNode);
3809 
3810         final FunctionNode function = createFunctionNode(
3811                 functionNode,
3812                 functionToken,
3813                 name,
3814                 parameters,
3815                 functionKind,
3816                 functionLine,
3817                 functionBody);
3818 
3819         if (isStatement) {
3820             if (isAnonymous) {
3821                 appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function));
3822                 return function;
3823             }
3824 
3825             // mark ES6 block functions as lexically scoped
3826             final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
3827             final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
3828             if (topLevel) {
3829                 functionDeclarations.add(varNode);
3830             } else if (useBlockScope()) {
3831                 prependStatement(varNode); // Hoist to beginning of current block
3832             } else {
3833                 appendStatement(varNode);
3834             }
3835         }
3836 
3837         return function;
3838     }
3839 
3840     private void verifyParameterList(final List<IdentNode> parameters, final ParserContextFunctionNode functionNode) {
3841         final IdentNode duplicateParameter = functionNode.getDuplicateParameterBinding();
3842         if (duplicateParameter != null) {
3843             if (functionNode.isStrict() || functionNode.getKind() == FunctionNode.Kind.ARROW || !functionNode.isSimpleParameterList()) {
3844                 throw error(AbstractParser.message("strict.param.redefinition", duplicateParameter.getName()), duplicateParameter.getToken());
3845             }
3846 
3847             final int arity = parameters.size();
3848             final HashSet<String> parametersSet = new HashSet<>(arity);
3849 
3850             for (int i = arity - 1; i >= 0; i--) {
3851                 final IdentNode parameter = parameters.get(i);
3852                 String parameterName = parameter.getName();
3853 
3854                 if (parametersSet.contains(parameterName)) {
3855                     // redefinition of parameter name, rename in non-strict mode
3856                     parameterName = functionNode.uniqueName(parameterName);
3857                     final long parameterToken = parameter.getToken();
3858                     parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
3859                 }
3860                 parametersSet.add(parameterName);
3861             }
3862         }
3863     }
3864 
3865     private static Block maybeWrapBodyInParameterBlock(Block functionBody, ParserContextBlockNode parameterBlock) {
3866         assert functionBody.isFunctionBody();
3867         if (!parameterBlock.getStatements().isEmpty()) {
3868             parameterBlock.appendStatement(new BlockStatement(functionBody));
3869             return new Block(parameterBlock.getToken(), functionBody.getFinish(), (functionBody.getFlags() | Block.IS_PARAMETER_BLOCK) & ~Block.IS_BODY, parameterBlock.getStatements());
3870         }
3871         return functionBody;
3872     }
3873 
3874     private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
3875         final String defaultFunctionName = getDefaultFunctionName();
3876         if (isValidIdentifier(defaultFunctionName)) {
3877             if (isStatement) {
3878                 // The name will be used as the LHS of a symbol assignment. We add the anonymous function
3879                 // prefix to ensure that it can't clash with another variable.
3880                 return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
3881             }
3882             return defaultFunctionName;
3883         }
3884         return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
3885     }
3886 
3887     private static boolean isValidIdentifier(final String name) {
3888         if (name == null || name.isEmpty()) {
3889             return false;
3890         }
3891         if (!Character.isJavaIdentifierStart(name.charAt(0))) {
3892             return false;
3893         }
3894         for (int i = 1; i < name.length(); ++i) {
3895             if (!Character.isJavaIdentifierPart(name.charAt(i))) {
3896                 return false;
3897             }
3898         }
3899         return true;
3900     }
3901 
3902     private String getDefaultFunctionName() {
3903         if (!defaultNames.isEmpty()) {
3904             final Object nameExpr = defaultNames.peek();
3905             if (nameExpr instanceof PropertyKey) {
3906                 markDefaultNameUsed();
3907                 return ((PropertyKey)nameExpr).getPropertyName();
3908             } else if (nameExpr instanceof AccessNode) {
3909                 markDefaultNameUsed();
3910                 return ((AccessNode)nameExpr).getProperty();
3911             }
3912         }
3913         return null;
3914     }
3915 
3916     private void markDefaultNameUsed() {
3917         defaultNames.pop();
3918         hideDefaultName();
3919     }
3920 
3921     private void hideDefaultName() {
3922         // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
3923         // from. Can't be null
3924         defaultNames.push("");
3925     }
3926 
3927     /**
3928      * FormalParameterList :
3929      *      Identifier
3930      *      FormalParameterList , Identifier
3931      *
3932      * See 13
3933      *
3934      * Parse function parameter list.
3935      * @return List of parameter nodes.
3936      */
3937     private List<IdentNode> formalParameterList(final boolean yield) {
3938         return formalParameterList(RPAREN, yield);
3939     }
3940 
3941     /**
3942      * Same as the other method of the same name - except that the end
3943      * token type expected is passed as argument to this method.
3944      *
3945      * FormalParameterList :
3946      *      Identifier
3947      *      FormalParameterList , Identifier
3948      *
3949      * See 13
3950      *
3951      * Parse function parameter list.
3952      * @return List of parameter nodes.
3953      */
3954     private List<IdentNode> formalParameterList(final TokenType endType, final boolean yield) {
3955         // Prepare to gather parameters.
3956         final ArrayList<IdentNode> parameters = new ArrayList<>();
3957         // Track commas.
3958         boolean first = true;
3959 
3960         while (type != endType) {
3961             // Comma prior to every argument except the first.
3962             if (!first) {
3963                 expect(COMMARIGHT);
3964             } else {
3965                 first = false;
3966             }
3967 
3968             boolean restParameter = false;
3969             if (type == ELLIPSIS && isES6()) {
3970                 next();
3971                 restParameter = true;
3972             }
3973 
3974             if (type == YIELD && yield) {
3975                 expect(IDENT);
3976             }
3977 
3978             final long paramToken = token;
3979             final int paramLine = line;
3980             final String contextString = "function parameter";
3981             IdentNode ident;
3982             if (isBindingIdentifier() || restParameter || !isES6()) {
3983                 ident = bindingIdentifier(contextString);
3984 
3985                 if (restParameter) {
3986                     ident = ident.setIsRestParameter();
3987                     // rest parameter must be last
3988                     expectDontAdvance(endType);
3989                     parameters.add(ident);
3990                     break;
3991                 } else if (type == ASSIGN && isES6()) {
3992                     next();
3993                     ident = ident.setIsDefaultParameter();
3994 
3995                     if (type == YIELD && yield) {
3996                         // error: yield in default expression
3997                         expect(IDENT);
3998                     }
3999 
4000                     // default parameter
4001                     Expression initializer = assignmentExpression(false);
4002 
4003                     ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4004                     if (currentFunction != null) {
4005                         // desugar to: param = (param === undefined) ? initializer : param;
4006                         // possible alternative: if (param === undefined) param = initializer;
4007                         BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4008                         TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4009                         BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
4010                         lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4011                     }
4012                 }
4013 
4014                 ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4015                 if (currentFunction != null) {
4016                     currentFunction.addParameterBinding(ident);
4017                     if (ident.isRestParameter() || ident.isDefaultParameter()) {
4018                         currentFunction.setSimpleParameterList(false);
4019                     }
4020                 }
4021             } else {
4022                 final Expression pattern = bindingPattern();
4023                 // Introduce synthetic temporary parameter to capture the object to be destructured.
4024                 ident = createIdentNode(paramToken, pattern.getFinish(), String.format("arguments[%d]", parameters.size())).setIsDestructuredParameter();
4025                 verifyDestructuringParameterBindingPattern(pattern, paramToken, paramLine, contextString);
4026 
4027                 Expression value = ident;
4028                 if (type == ASSIGN) {
4029                     next();
4030                     ident = ident.setIsDefaultParameter();
4031 
4032                     // binding pattern with initializer. desugar to: (param === undefined) ? initializer : param
4033                     Expression initializer = assignmentExpression(false);
4034                     // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list)
4035                     BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4036                     value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4037                 }
4038 
4039                 ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4040                 if (currentFunction != null) {
4041                     // destructuring assignment
4042                     BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), pattern, value);
4043                     lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4044                 }
4045             }
4046             parameters.add(ident);
4047         }
4048 
4049         parameters.trimToSize();
4050         return parameters;
4051     }
4052 
4053     private void verifyDestructuringParameterBindingPattern(final Expression pattern, final long paramToken, final int paramLine, final String contextString) {
4054         verifyDestructuringBindingPattern(pattern, new Consumer<IdentNode>() {
4055             public void accept(IdentNode identNode) {
4056                 verifyIdent(identNode, contextString);
4057 
4058                 ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4059                 if (currentFunction != null) {
4060                     // declare function-scope variables for destructuring bindings
4061                     lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null));
4062                     // detect duplicate bounds names in parameter list
4063                     currentFunction.addParameterBinding(identNode);
4064                     currentFunction.setSimpleParameterList(false);
4065                 }
4066             }
4067         });
4068     }
4069 
4070     /**
4071      * FunctionBody :
4072      *      SourceElements?
4073      *
4074      * See 13
4075      *
4076      * Parse function body.
4077      * @return function node (body.)
4078      */
4079     private Block functionBody(final ParserContextFunctionNode functionNode) {
4080         long lastToken = 0L;
4081         ParserContextBlockNode body = null;
4082         final long bodyToken = token;
4083         Block functionBody;
4084         int bodyFinish = 0;
4085 
4086         final boolean parseBody;
4087         Object endParserState = null;
4088         try {
4089             // Create a new function block.
4090             body = newBlock();
4091             if (env._debug_scopes) {
4092                 // debug scope options forces everything to be in scope
4093                 markEval(lc);
4094             }
4095             assert functionNode != null;
4096             final int functionId = functionNode.getId();
4097             parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
4098             // Nashorn extension: expression closures
4099             if ((!env._no_syntax_extensions || functionNode.getKind() == FunctionNode.Kind.ARROW) && type != LBRACE) {
4100                 /*
4101                  * Example:
4102                  *
4103                  * function square(x) x * x;
4104                  * print(square(3));
4105                  */
4106 
4107                 // just expression as function body
4108                 final Expression expr = assignmentExpression(false);
4109                 lastToken = previousToken;
4110                 functionNode.setLastToken(previousToken);
4111                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
4112                 // EOL uses length field to store the line number
4113                 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
4114                 // Only create the return node if we aren't skipping nested functions. Note that we aren't
4115                 // skipping parsing of these extended functions; they're considered to be small anyway. Also,
4116                 // they don't end with a single well known token, so it'd be very hard to get correctly (see
4117                 // the note below for reasoning on skipping happening before instead of after RBRACE for
4118                 // details).
4119                 if (parseBody) {
4120                     final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
4121                     appendStatement(returnNode);
4122                 }
4123                 // bodyFinish = finish;
4124             } else {
4125                 expectDontAdvance(LBRACE);
4126                 if (parseBody || !skipFunctionBody(functionNode)) {
4127                     next();
4128                     // Gather the function elements.
4129                     final List<Statement> prevFunctionDecls = functionDeclarations;
4130                     functionDeclarations = new ArrayList<>();
4131                     try {
4132                         sourceElements(false);
4133                         addFunctionDeclarations(functionNode);
4134                     } finally {
4135                         functionDeclarations = prevFunctionDecls;
4136                     }
4137 
4138                     lastToken = token;
4139                     if (parseBody) {
4140                         // Since the lexer can read ahead and lexify some number of tokens in advance and have
4141                         // them buffered in the TokenStream, we need to produce a lexer state as it was just
4142                         // before it lexified RBRACE, and not whatever is its current (quite possibly well read
4143                         // ahead) state.
4144                         endParserState = new ParserState(Token.descPosition(token), line, linePosition);
4145 
4146                         // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
4147                         // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
4148                         // state after it. The reason is that RBRACE is a well-known token that we can expect and
4149                         // will never involve us getting into a weird lexer state, and as such is a great reparse
4150                         // point. Typical example of a weird lexer state after RBRACE would be:
4151                         //     function this_is_skipped() { ... } "use strict";
4152                         // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
4153                         // of compensating for the possibility of a string literal (or similar) after RBRACE,
4154                         // we'll rather just restart parsing from this well-known, friendly token instead.
4155                     }
4156                 }
4157                 bodyFinish = finish;
4158                 functionNode.setLastToken(token);
4159                 expect(RBRACE);
4160             }
4161         } finally {
4162             restoreBlock(body);
4163         }
4164 
4165         // NOTE: we can only do alterations to the function node after restoreFunctionNode.
4166 
4167         if (parseBody) {
4168             functionNode.setEndParserState(endParserState);
4169         } else if (!body.getStatements().isEmpty()){
4170             // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
4171             // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
4172             // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
4173             // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
4174             // nested bodies early if we were supposed to skip 'em.
4175             body.setStatements(Collections.<Statement>emptyList());
4176         }
4177 
4178         if (reparsedFunction != null) {
4179             // We restore the flags stored in the function's ScriptFunctionData that we got when we first
4180             // eagerly parsed the code. We're doing it because some flags would be set based on the
4181             // content of the function, or even content of its nested functions, most of which are normally
4182             // skipped during an on-demand compilation.
4183             final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
4184             if (data != null) {
4185                 // Data can be null if when we originally parsed the file, we removed the function declaration
4186                 // as it was dead code.
4187                 functionNode.setFlag(data.getFunctionFlags());
4188                 // This compensates for missing markEval() in case the function contains an inner function
4189                 // that contains eval(), that now we didn't discover since we skipped the inner function.
4190                 if (functionNode.hasNestedEval()) {
4191                     assert functionNode.hasScopeBlock();
4192                     body.setFlag(Block.NEEDS_SCOPE);
4193                 }
4194             }
4195         }
4196         functionBody = new Block(bodyToken, bodyFinish, body.getFlags() | Block.IS_BODY, body.getStatements());
4197         return functionBody;
4198     }
4199 
4200     private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
4201         if (reparsedFunction == null) {
4202             // Not reparsing, so don't skip any function body.
4203             return false;
4204         }
4205         // Skip to the RBRACE of this function, and continue parsing from there.
4206         final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
4207         if (data == null) {
4208             // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
4209             // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
4210             // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
4211             return false;
4212         }
4213         final ParserState parserState = (ParserState)data.getEndParserState();
4214         assert parserState != null;
4215 
4216         if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) {
4217             // RBRACE is already in the token stream, so fast forward to it
4218             for (; k < stream.last(); k++) {
4219                 final long nextToken = stream.get(k + 1);
4220                 if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) {
4221                     token = stream.get(k);
4222                     type = Token.descType(token);
4223                     next();
4224                     assert type == RBRACE && start == parserState.position;
4225                     return true;
4226                 }
4227             }
4228         }
4229 
4230         stream.reset();
4231         lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
4232         line = parserState.line;
4233         linePosition = parserState.linePosition;
4234         // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
4235         // the RBRACE.
4236         type = SEMICOLON;
4237         scanFirstToken();
4238 
4239         return true;
4240     }
4241 
4242     /**
4243      * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
4244      * for resuming parsing after skipping a function body.
4245      */
4246     private static class ParserState implements Serializable {
4247         private final int position;
4248         private final int line;
4249         private final int linePosition;
4250 
4251         private static final long serialVersionUID = -2382565130754093694L;
4252 
4253         ParserState(final int position, final int line, final int linePosition) {
4254             this.position = position;
4255             this.line = line;
4256             this.linePosition = linePosition;
4257         }
4258 
4259         Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
4260             final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
4261             newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
4262             return newLexer;
4263         }
4264     }
4265 
4266     private void printAST(final FunctionNode functionNode) {
4267         if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) {
4268             env.getErr().println(new ASTWriter(functionNode));
4269         }
4270 
4271         if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) {
4272             env.getErr().println(new PrintVisitor(functionNode, true, false));
4273         }
4274     }
4275 
4276     private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
4277         VarNode lastDecl = null;
4278         for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
4279             Statement decl = functionDeclarations.get(i);
4280             if (lastDecl == null && decl instanceof VarNode) {
4281                 decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
4282                 functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
4283             }
4284             prependStatement(decl);
4285         }
4286     }
4287 
4288     private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
4289         if (earlyError) {
4290             throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
4291         }
4292         final ArrayList<Expression> args = new ArrayList<>();
4293         args.add(lhs);
4294         if (rhs == null) {
4295             args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
4296         } else {
4297             args.add(rhs);
4298         }
4299         args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
4300         return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
4301     }
4302 
4303     /**
4304      * PostfixExpression :
4305      *      LeftHandSideExpression
4306      *      LeftHandSideExpression ++ // [no LineTerminator here]
4307      *      LeftHandSideExpression -- // [no LineTerminator here]
4308      *
4309      * See 11.3
4310      *
4311      * UnaryExpression :
4312      *      PostfixExpression
4313      *      delete UnaryExpression
4314      *      void UnaryExpression
4315      *      typeof UnaryExpression
4316      *      ++ UnaryExpression
4317      *      -- UnaryExpression
4318      *      + UnaryExpression
4319      *      - UnaryExpression
4320      *      ~ UnaryExpression
4321      *      ! UnaryExpression
4322      *
4323      * See 11.4
4324      *
4325      * Parse unary expression.
4326      * @return Expression node.
4327      */
4328     private Expression unaryExpression() {
4329         final int  unaryLine  = line;
4330         final long unaryToken = token;
4331 
4332         switch (type) {
4333         case DELETE: {
4334             next();
4335             final Expression expr = unaryExpression();
4336             if (expr instanceof BaseNode || expr instanceof IdentNode) {
4337                 return new UnaryNode(unaryToken, expr);
4338             }
4339             appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
4340             return LiteralNode.newInstance(unaryToken, finish, true);
4341         }
4342         case VOID:
4343         case TYPEOF:
4344         case ADD:
4345         case SUB:
4346         case BIT_NOT:
4347         case NOT:
4348             next();
4349             final Expression expr = unaryExpression();
4350             return new UnaryNode(unaryToken, expr);
4351 
4352         case INCPREFIX:
4353         case DECPREFIX:
4354             final TokenType opType = type;
4355             next();
4356 
4357             final Expression lhs = leftHandSideExpression();
4358             // ++, -- without operand..
4359             if (lhs == null) {
4360                 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
4361             }
4362 
4363             return verifyIncDecExpression(unaryToken, opType, lhs, false);
4364 
4365         default:
4366             break;
4367         }
4368 
4369         Expression expression = leftHandSideExpression();
4370 
4371         if (last != EOL) {
4372             switch (type) {
4373             case INCPREFIX:
4374             case DECPREFIX:
4375                 final long opToken = token;
4376                 final TokenType opType = type;
4377                 final Expression lhs = expression;
4378                 // ++, -- without operand..
4379                 if (lhs == null) {
4380                     throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
4381                 }
4382                 next();
4383 
4384                 return verifyIncDecExpression(opToken, opType, lhs, true);
4385             default:
4386                 break;
4387             }
4388         }
4389 
4390         if (expression == null) {
4391             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
4392         }
4393 
4394         return expression;
4395     }
4396 
4397     private Expression verifyIncDecExpression(final long unaryToken, final TokenType opType, final Expression lhs, final boolean isPostfix) {
4398         assert lhs != null;
4399 
4400         if (!(lhs instanceof AccessNode ||
4401               lhs instanceof IndexNode ||
4402               lhs instanceof IdentNode)) {
4403             return referenceError(lhs, null, env._early_lvalue_error);
4404         }
4405 
4406         if (lhs instanceof IdentNode) {
4407             if (!checkIdentLValue((IdentNode)lhs)) {
4408                 return referenceError(lhs, null, false);
4409             }
4410             verifyIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
4411         }
4412 
4413         return incDecExpression(unaryToken, opType, lhs, isPostfix);
4414     }
4415 
4416     /**
4417      * {@code
4418      * MultiplicativeExpression :
4419      *      UnaryExpression
4420      *      MultiplicativeExpression * UnaryExpression
4421      *      MultiplicativeExpression / UnaryExpression
4422      *      MultiplicativeExpression % UnaryExpression
4423      *
4424      * See 11.5
4425      *
4426      * AdditiveExpression :
4427      *      MultiplicativeExpression
4428      *      AdditiveExpression + MultiplicativeExpression
4429      *      AdditiveExpression - MultiplicativeExpression
4430      *
4431      * See 11.6
4432      *
4433      * ShiftExpression :
4434      *      AdditiveExpression
4435      *      ShiftExpression << AdditiveExpression
4436      *      ShiftExpression >> AdditiveExpression
4437      *      ShiftExpression >>> AdditiveExpression
4438      *
4439      * See 11.7
4440      *
4441      * RelationalExpression :
4442      *      ShiftExpression
4443      *      RelationalExpression < ShiftExpression
4444      *      RelationalExpression > ShiftExpression
4445      *      RelationalExpression <= ShiftExpression
4446      *      RelationalExpression >= ShiftExpression
4447      *      RelationalExpression instanceof ShiftExpression
4448      *      RelationalExpression in ShiftExpression // if !noIf
4449      *
4450      * See 11.8
4451      *
4452      *      RelationalExpression
4453      *      EqualityExpression == RelationalExpression
4454      *      EqualityExpression != RelationalExpression
4455      *      EqualityExpression === RelationalExpression
4456      *      EqualityExpression !== RelationalExpression
4457      *
4458      * See 11.9
4459      *
4460      * BitwiseANDExpression :
4461      *      EqualityExpression
4462      *      BitwiseANDExpression & EqualityExpression
4463      *
4464      * BitwiseXORExpression :
4465      *      BitwiseANDExpression
4466      *      BitwiseXORExpression ^ BitwiseANDExpression
4467      *
4468      * BitwiseORExpression :
4469      *      BitwiseXORExpression
4470      *      BitwiseORExpression | BitwiseXORExpression
4471      *
4472      * See 11.10
4473      *
4474      * LogicalANDExpression :
4475      *      BitwiseORExpression
4476      *      LogicalANDExpression && BitwiseORExpression
4477      *
4478      * LogicalORExpression :
4479      *      LogicalANDExpression
4480      *      LogicalORExpression || LogicalANDExpression
4481      *
4482      * See 11.11
4483      *
4484      * ConditionalExpression :
4485      *      LogicalORExpression
4486      *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
4487      *
4488      * See 11.12
4489      *
4490      * AssignmentExpression :
4491      *      ConditionalExpression
4492      *      LeftHandSideExpression AssignmentOperator AssignmentExpression
4493      *
4494      * AssignmentOperator :
4495      *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
4496      *
4497      * See 11.13
4498      *
4499      * Expression :
4500      *      AssignmentExpression
4501      *      Expression , AssignmentExpression
4502      *
4503      * See 11.14
4504      * }
4505      *
4506      * Parse expression.
4507      * @return Expression node.
4508      */
4509     protected Expression expression() {
4510         // This method is protected so that subclass can get details
4511         // at expression start point!
4512 
4513         // Include commas in expression parsing.
4514         return expression(false);
4515     }
4516 
4517     private Expression expression(final boolean noIn) {
4518         Expression assignmentExpression = assignmentExpression(noIn);
4519         while (type == COMMARIGHT) {
4520             long commaToken = token;
4521             next();
4522 
4523             boolean rhsRestParameter = false;
4524             if (type == ELLIPSIS && isES6()) {
4525                 // (a, b, ...rest) is not a valid expression, unless we're parsing the parameter list of an arrow function (we need to throw the right error).
4526                 // But since the rest parameter is always last, at least we know that the expression has to end here and be followed by RPAREN and ARROW, so peek ahead.
4527                 if (isRestParameterEndOfArrowFunctionParameterList()) {
4528                     next();
4529                     rhsRestParameter = true;
4530                 }
4531             }
4532 
4533             Expression rhs = assignmentExpression(noIn);
4534 
4535             if (rhsRestParameter) {
4536                 rhs = ((IdentNode)rhs).setIsRestParameter();
4537                 // Our only valid move is to end Expression here and continue with ArrowFunction.
4538                 // We've already checked that this is the parameter list of an arrow function (see above).
4539                 // RPAREN is next, so we'll finish the binary expression and drop out of the loop.
4540                 assert type == RPAREN;
4541             }
4542 
4543             assignmentExpression = new BinaryNode(commaToken, assignmentExpression, rhs);
4544         }
4545         return assignmentExpression;
4546     }
4547 
4548     private Expression expression(final int minPrecedence, final boolean noIn) {
4549         return expression(unaryExpression(), minPrecedence, noIn);
4550     }
4551 
4552     private JoinPredecessorExpression joinPredecessorExpression() {
4553         return new JoinPredecessorExpression(expression());
4554     }
4555 
4556     private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
4557         // Get the precedence of the next operator.
4558         int precedence = type.getPrecedence();
4559         Expression lhs = exprLhs;
4560 
4561         // While greater precedence.
4562         while (type.isOperator(noIn) && precedence >= minPrecedence) {
4563             // Capture the operator token.
4564             final long op = token;
4565 
4566             if (type == TERNARY) {
4567                 // Skip operator.
4568                 next();
4569 
4570                 // Pass expression. Middle expression of a conditional expression can be a "in"
4571                 // expression - even in the contexts where "in" is not permitted.
4572                 final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
4573 
4574                 expect(COLON);
4575 
4576                 // Fail expression.
4577                 final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
4578 
4579                 // Build up node.
4580                 lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
4581             } else {
4582                 // Skip operator.
4583                 next();
4584 
4585                  // Get the next primary expression.
4586                 Expression rhs;
4587                 final boolean isAssign = Token.descType(op) == ASSIGN;
4588                 if(isAssign) {
4589                     defaultNames.push(lhs);
4590                 }
4591                 try {
4592                     rhs = unaryExpression();
4593                     // Get precedence of next operator.
4594                     int nextPrecedence = type.getPrecedence();
4595 
4596                     // Subtask greater precedence.
4597                     while (type.isOperator(noIn) &&
4598                            (nextPrecedence > precedence ||
4599                            nextPrecedence == precedence && !type.isLeftAssociative())) {
4600                         rhs = expression(rhs, nextPrecedence, noIn);
4601                         nextPrecedence = type.getPrecedence();
4602                     }
4603                 } finally {
4604                     if(isAssign) {
4605                         defaultNames.pop();
4606                     }
4607                 }
4608                 lhs = verifyAssignment(op, lhs, rhs);
4609             }
4610 
4611             precedence = type.getPrecedence();
4612         }
4613 
4614         return lhs;
4615     }
4616 
4617     /**
4618      * AssignmentExpression.
4619      *
4620      * AssignmentExpression[In, Yield] :
4621      *   ConditionalExpression[?In, ?Yield]
4622      *   [+Yield] YieldExpression[?In]
4623      *   ArrowFunction[?In, ?Yield]
4624      *   LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield]
4625      *   LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield]
4626      */
4627     protected Expression assignmentExpression(final boolean noIn) {
4628         // This method is protected so that subclass can get details
4629         // at assignment expression start point!
4630 
4631         if (type == YIELD && inGeneratorFunction() && isES6()) {
4632             return yieldExpression(noIn);
4633         }
4634 
4635         final long startToken = token;
4636         final int startLine = line;
4637         final Expression exprLhs = conditionalExpression(noIn);
4638 
4639         if (type == ARROW && isES6()) {
4640             if (checkNoLineTerminator()) {
4641                 final Expression paramListExpr;
4642                 if (exprLhs instanceof ExpressionList) {
4643                     paramListExpr = (((ExpressionList)exprLhs).getExpressions().isEmpty() ? null : ((ExpressionList)exprLhs).getExpressions().get(0));
4644                 } else {
4645                     paramListExpr = exprLhs;
4646                 }
4647                 return arrowFunction(startToken, startLine, paramListExpr);
4648             }
4649         }
4650         assert !(exprLhs instanceof ExpressionList);
4651 
4652         if (isAssignmentOperator(type)) {
4653             final boolean isAssign = type == ASSIGN;
4654             if (isAssign) {
4655                 defaultNames.push(exprLhs);
4656             }
4657             try {
4658                 final long assignToken = token;
4659                 next();
4660                 final Expression exprRhs = assignmentExpression(noIn);
4661                 return verifyAssignment(assignToken, exprLhs, exprRhs);
4662             } finally {
4663                 if (isAssign) {
4664                     defaultNames.pop();
4665                 }
4666             }
4667         } else {
4668             return exprLhs;
4669         }
4670     }
4671 
4672     /**
4673      * Is type one of {@code = *= /= %= += -= <<= >>= >>>= &= ^= |=}?
4674      */
4675     private static boolean isAssignmentOperator(TokenType type) {
4676         switch (type) {
4677         case ASSIGN:
4678         case ASSIGN_ADD:
4679         case ASSIGN_BIT_AND:
4680         case ASSIGN_BIT_OR:
4681         case ASSIGN_BIT_XOR:
4682         case ASSIGN_DIV:
4683         case ASSIGN_MOD:
4684         case ASSIGN_MUL:
4685         case ASSIGN_SAR:
4686         case ASSIGN_SHL:
4687         case ASSIGN_SHR:
4688         case ASSIGN_SUB:
4689             return true;
4690         }
4691         return false;
4692     }
4693 
4694     /**
4695      * ConditionalExpression.
4696      */
4697     private Expression conditionalExpression(boolean noIn) {
4698         return expression(TERNARY.getPrecedence(), noIn);
4699     }
4700 
4701     /**
4702      * ArrowFunction.
4703      *
4704      * @param startToken start token of the ArrowParameters expression
4705      * @param functionLine start line of the arrow function
4706      * @param paramListExpr ArrowParameters expression or {@code null} for {@code ()} (empty list)
4707      */
4708     private Expression arrowFunction(final long startToken, final int functionLine, final Expression paramListExpr) {
4709         // caller needs to check that there's no LineTerminator between parameter list and arrow
4710         assert type != ARROW || checkNoLineTerminator();
4711         expect(ARROW);
4712 
4713         final long functionToken = Token.recast(startToken, ARROW);
4714         final IdentNode name = new IdentNode(functionToken, Token.descPosition(functionToken), "=>:" + functionLine);
4715         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.ARROW, functionLine, null);
4716         functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
4717 
4718         lc.push(functionNode);
4719         try {
4720             ParserContextBlockNode parameterBlock = newBlock();
4721             final List<IdentNode> parameters;
4722             try {
4723                 parameters = convertArrowFunctionParameterList(paramListExpr, functionLine);
4724                 functionNode.setParameters(parameters);
4725 
4726                 if (!functionNode.isSimpleParameterList()) {
4727                     markEvalInArrowParameterList(parameterBlock);
4728                 }
4729             } finally {
4730                 restoreBlock(parameterBlock);
4731             }
4732             Block functionBody = functionBody(functionNode);
4733 
4734             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
4735 
4736             verifyParameterList(parameters, functionNode);
4737 
4738             final FunctionNode function = createFunctionNode(
4739                             functionNode,
4740                             functionToken,
4741                             name,
4742                             parameters,
4743                             FunctionNode.Kind.ARROW,
4744                             functionLine,
4745                             functionBody);
4746             return function;
4747         } finally {
4748             lc.pop(functionNode);
4749         }
4750     }
4751 
4752     private void markEvalInArrowParameterList(final ParserContextBlockNode parameterBlock) {
4753         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
4754         final ParserContextFunctionNode current = iter.next();
4755         final ParserContextFunctionNode parent = iter.next();
4756 
4757         if (parent.getFlag(FunctionNode.HAS_EVAL) != 0) {
4758             // we might have flagged has-eval in the parent function during parsing the parameter list,
4759             // if the parameter list contains eval; must tag arrow function as has-eval.
4760             for (final Statement st : parameterBlock.getStatements()) {
4761                 st.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
4762                     @Override
4763                     public boolean enterCallNode(final CallNode callNode) {
4764                         if (callNode.getFunction() instanceof IdentNode && ((IdentNode) callNode.getFunction()).getName().equals("eval")) {
4765                             current.setFlag(FunctionNode.HAS_EVAL);
4766                         }
4767                         return true;
4768                     }
4769                 });
4770             }
4771             // TODO: function containing the arrow function should not be flagged has-eval
4772         }
4773     }
4774 
4775     private List<IdentNode> convertArrowFunctionParameterList(final Expression paramListExpr, final int functionLine) {
4776         final List<IdentNode> parameters;
4777         if (paramListExpr == null) {
4778             // empty parameter list, i.e. () =>
4779             parameters = Collections.emptyList();
4780         } else if (paramListExpr instanceof IdentNode || paramListExpr.isTokenType(ASSIGN) || isDestructuringLhs(paramListExpr)) {
4781             parameters = Collections.singletonList(verifyArrowParameter(paramListExpr, 0, functionLine));
4782         } else if (paramListExpr instanceof BinaryNode && Token.descType(paramListExpr.getToken()) == COMMARIGHT) {
4783             parameters = new ArrayList<>();
4784             Expression car = paramListExpr;
4785             do {
4786                 final Expression cdr = ((BinaryNode) car).rhs();
4787                 parameters.add(0, verifyArrowParameter(cdr, parameters.size(), functionLine));
4788                 car = ((BinaryNode) car).lhs();
4789             } while (car instanceof BinaryNode && Token.descType(car.getToken()) == COMMARIGHT);
4790             parameters.add(0, verifyArrowParameter(car, parameters.size(), functionLine));
4791         } else {
4792             throw error(AbstractParser.message("expected.arrow.parameter"), paramListExpr.getToken());
4793         }
4794         return parameters;
4795     }
4796 
4797     private IdentNode verifyArrowParameter(Expression param, int index, int paramLine) {
4798         final String contextString = "function parameter";
4799         if (param instanceof IdentNode) {
4800             IdentNode ident = (IdentNode)param;
4801             verifyStrictIdent(ident, contextString);
4802             ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4803             if (currentFunction != null) {
4804                 currentFunction.addParameterBinding(ident);
4805             }
4806             return ident;
4807         }
4808 
4809         if (param.isTokenType(ASSIGN)) {
4810             Expression lhs = ((BinaryNode) param).lhs();
4811             long paramToken = lhs.getToken();
4812             Expression initializer = ((BinaryNode) param).rhs();
4813             if (lhs instanceof IdentNode) {
4814                 // default parameter
4815                 IdentNode ident = (IdentNode) lhs;
4816 
4817                 ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4818                 if (currentFunction != null) {
4819                     BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4820                     TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4821                     BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
4822                     lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4823 
4824                     currentFunction.addParameterBinding(ident);
4825                     currentFunction.setSimpleParameterList(false);
4826                 }
4827                 return ident;
4828             } else if (isDestructuringLhs(lhs)) {
4829                 // binding pattern with initializer
4830                 // Introduce synthetic temporary parameter to capture the object to be destructured.
4831                 IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter().setIsDefaultParameter();
4832                 verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
4833 
4834                 ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4835                 if (currentFunction != null) {
4836                     BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4837                     TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4838                     BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value);
4839                     lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4840                 }
4841                 return ident;
4842             }
4843         } else if (isDestructuringLhs(param)) {
4844             // binding pattern
4845             long paramToken = param.getToken();
4846 
4847             // Introduce synthetic temporary parameter to capture the object to be destructured.
4848             IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter();
4849             verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
4850 
4851             ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4852             if (currentFunction != null) {
4853                 BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident);
4854                 lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4855             }
4856             return ident;
4857         }
4858         throw error(AbstractParser.message("invalid.arrow.parameter"), param.getToken());
4859     }
4860 
4861     private boolean checkNoLineTerminator() {
4862         assert type == ARROW;
4863         if (last == RPAREN) {
4864             return true;
4865         } else if (last == IDENT) {
4866             return true;
4867         }
4868         for (int i = k - 1; i >= 0; i--) {
4869             TokenType t = T(i);
4870             switch (t) {
4871             case RPAREN:
4872             case IDENT:
4873                 return true;
4874             case EOL:
4875                 return false;
4876             case COMMENT:
4877                 continue;
4878             default:
4879                 if (t.getKind() == TokenKind.FUTURESTRICT) {
4880                     return true;
4881                 }
4882                 return false;
4883             }
4884         }
4885         return false;
4886     }
4887 
4888     /**
4889      * Peek ahead to see if what follows after the ellipsis is a rest parameter
4890      * at the end of an arrow function parameter list.
4891      */
4892     private boolean isRestParameterEndOfArrowFunctionParameterList() {
4893         assert type == ELLIPSIS;
4894         // find IDENT, RPAREN, ARROW, in that order, skipping over EOL (where allowed) and COMMENT
4895         int i = 1;
4896         for (;;) {
4897             TokenType t = T(k + i++);
4898             if (t == IDENT) {
4899                 break;
4900             } else if (t == EOL || t == COMMENT) {
4901                 continue;
4902             } else {
4903                 return false;
4904             }
4905         }
4906         for (;;) {
4907             TokenType t = T(k + i++);
4908             if (t == RPAREN) {
4909                 break;
4910             } else if (t == EOL || t == COMMENT) {
4911                 continue;
4912             } else {
4913                 return false;
4914             }
4915         }
4916         for (;;) {
4917             TokenType t = T(k + i++);
4918             if (t == ARROW) {
4919                 break;
4920             } else if (t == COMMENT) {
4921                 continue;
4922             } else {
4923                 return false;
4924             }
4925         }
4926         return true;
4927     }
4928 
4929     /**
4930      * Parse an end of line.
4931      */
4932     private void endOfLine() {
4933         switch (type) {
4934         case SEMICOLON:
4935         case EOL:
4936             next();
4937             break;
4938         case RPAREN:
4939         case RBRACKET:
4940         case RBRACE:
4941         case EOF:
4942             break;
4943         default:
4944             if (last != EOL) {
4945                 expect(SEMICOLON);
4946             }
4947             break;
4948         }
4949     }
4950 
4951     /**
4952      * Parse untagged template literal as string concatenation.
4953      */
4954     private Expression templateLiteral() {
4955         assert type == TEMPLATE || type == TEMPLATE_HEAD;
4956         final boolean noSubstitutionTemplate = type == TEMPLATE;
4957         long lastLiteralToken = token;
4958         LiteralNode<?> literal = getLiteral();
4959         if (noSubstitutionTemplate) {
4960             return literal;
4961         }
4962 
4963         Expression concat = literal;
4964         TokenType lastLiteralType;
4965         do {
4966             final Expression expression = expression();
4967             if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
4968                 throw error(AbstractParser.message("unterminated.template.expression"), token);
4969             }
4970             concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression);
4971             lastLiteralType = type;
4972             lastLiteralToken = token;
4973             literal = getLiteral();
4974             concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal);
4975         } while (lastLiteralType == TEMPLATE_MIDDLE);
4976         return concat;
4977     }
4978 
4979     /**
4980      * Parse tagged template literal as argument list.
4981      * @return argument list for a tag function call (template object, ...substitutions)
4982      */
4983     private List<Expression> templateLiteralArgumentList() {
4984         assert type == TEMPLATE || type == TEMPLATE_HEAD;
4985         final ArrayList<Expression> argumentList = new ArrayList<>();
4986         final ArrayList<Expression> rawStrings = new ArrayList<>();
4987         final ArrayList<Expression> cookedStrings = new ArrayList<>();
4988         argumentList.add(null); // filled at the end
4989 
4990         final long templateToken = token;
4991         final boolean hasSubstitutions = type == TEMPLATE_HEAD;
4992         addTemplateLiteralString(rawStrings, cookedStrings);
4993 
4994         if (hasSubstitutions) {
4995             TokenType lastLiteralType;
4996             do {
4997                 final Expression expression = expression();
4998                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
4999                     throw error(AbstractParser.message("unterminated.template.expression"), token);
5000                 }
5001                 argumentList.add(expression);
5002 
5003                 lastLiteralType = type;
5004                 addTemplateLiteralString(rawStrings, cookedStrings);
5005             } while (lastLiteralType == TEMPLATE_MIDDLE);
5006         }
5007 
5008         final LiteralNode<Expression[]> rawStringArray = LiteralNode.newInstance(templateToken, finish, rawStrings);
5009         final LiteralNode<Expression[]> cookedStringArray = LiteralNode.newInstance(templateToken, finish, cookedStrings);
5010         final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray);
5011         argumentList.set(0, templateObject);
5012         return optimizeList(argumentList);
5013     }
5014 
5015     private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) {
5016         final long stringToken = token;
5017         final String rawString = lexer.valueOfRawString(stringToken);
5018         final String cookedString = (String) getValue();
5019         next();
5020         rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString));
5021         cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
5022     }
5023 
5024 
5025     /**
5026      * Parse a module.
5027      *
5028      * Module :
5029      *      ModuleBody?
5030      *
5031      * ModuleBody :
5032      *      ModuleItemList
5033      */
5034     private FunctionNode module(final String moduleName) {
5035         boolean oldStrictMode = isStrictMode;
5036         try {
5037             isStrictMode = true; // Module code is always strict mode code. (ES6 10.2.1)
5038 
5039             // Make a pseudo-token for the script holding its start and length.
5040             int functionStart = Math.min(Token.descPosition(Token.withDelimiter(token)), finish);
5041             final long functionToken = Token.toDesc(FUNCTION, functionStart, source.getLength() - functionStart);
5042             final int  functionLine  = line;
5043 
5044             final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), moduleName);
5045             final ParserContextFunctionNode script = createParserContextFunctionNode(
5046                             ident,
5047                             functionToken,
5048                             FunctionNode.Kind.MODULE,
5049                             functionLine,
5050                             Collections.<IdentNode>emptyList());
5051             lc.push(script);
5052 
5053             final ParserContextModuleNode module = new ParserContextModuleNode(moduleName);
5054             lc.push(module);
5055 
5056             final ParserContextBlockNode body = newBlock();
5057 
5058             functionDeclarations = new ArrayList<>();
5059             moduleBody();
5060             addFunctionDeclarations(script);
5061             functionDeclarations = null;
5062 
5063             restoreBlock(body);
5064             body.setFlag(Block.NEEDS_SCOPE);
5065             final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
5066             lc.pop(module);
5067             lc.pop(script);
5068             script.setLastToken(token);
5069 
5070             expect(EOF);
5071 
5072             script.setModule(module.createModule());
5073             return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.MODULE, functionLine, programBody);
5074         } finally {
5075             isStrictMode = oldStrictMode;
5076         }
5077     }
5078 
5079     /**
5080      * Parse module body.
5081      *
5082      * ModuleBody :
5083      *      ModuleItemList
5084      *
5085      * ModuleItemList :
5086      *      ModuleItem
5087      *      ModuleItemList ModuleItem
5088      *
5089      * ModuleItem :
5090      *      ImportDeclaration
5091      *      ExportDeclaration
5092      *      StatementListItem
5093      */
5094     private void moduleBody() {
5095         loop:
5096         while (type != EOF) {
5097             switch (type) {
5098             case EOF:
5099                 break loop;
5100             case IMPORT:
5101                 importDeclaration();
5102                 break;
5103             case EXPORT:
5104                 exportDeclaration();
5105                 break;
5106             default:
5107                 // StatementListItem
5108                 statement(true, false, false, false);
5109                 break;
5110             }
5111         }
5112     }
5113 
5114 
5115     /**
5116      * Parse import declaration.
5117      *
5118      * ImportDeclaration :
5119      *     import ImportClause FromClause ;
5120      *     import ModuleSpecifier ;
5121      * ImportClause :
5122      *     ImportedDefaultBinding
5123      *     NameSpaceImport
5124      *     NamedImports
5125      *     ImportedDefaultBinding , NameSpaceImport
5126      *     ImportedDefaultBinding , NamedImports
5127      * ImportedDefaultBinding :
5128      *     ImportedBinding
5129      * ModuleSpecifier :
5130      *     StringLiteral
5131      * ImportedBinding :
5132      *     BindingIdentifier
5133      */
5134     private void importDeclaration() {
5135         expect(IMPORT);
5136         final ParserContextModuleNode module = lc.getCurrentModule();
5137         if (type == STRING || type == ESCSTRING) {
5138             // import ModuleSpecifier ;
5139             final String moduleSpecifier = (String) getValue();
5140             next();
5141             module.addModuleRequest(moduleSpecifier);
5142         } else {
5143             // import ImportClause FromClause ;
5144             List<Module.ImportEntry> importEntries;
5145             if (type == MUL) {
5146                 importEntries = Collections.singletonList(nameSpaceImport());
5147             } else if (type == LBRACE) {
5148                 importEntries = namedImports();
5149             } else if (isBindingIdentifier()) {
5150                 // ImportedDefaultBinding
5151                 final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding");
5152                 Module.ImportEntry defaultImport = Module.ImportEntry.importDefault(importedDefaultBinding.getName());
5153 
5154                 if (type == COMMARIGHT) {
5155                     next();
5156                     importEntries = new ArrayList<>();
5157                     if (type == MUL) {
5158                         importEntries.add(nameSpaceImport());
5159                     } else if (type == LBRACE) {
5160                         importEntries.addAll(namedImports());
5161                     } else {
5162                         throw error(AbstractParser.message("expected.named.import"));
5163                     }
5164                 } else {
5165                     importEntries = Collections.singletonList(defaultImport);
5166                 }
5167             } else {
5168                 throw error(AbstractParser.message("expected.import"));
5169             }
5170 
5171             final String moduleSpecifier = fromClause();
5172             module.addModuleRequest(moduleSpecifier);
5173             for (int i = 0; i < importEntries.size(); i++) {
5174                 module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier));
5175             }
5176         }
5177         expect(SEMICOLON);
5178     }
5179 
5180     /**
5181      * NameSpaceImport :
5182      *     * as ImportedBinding
5183      *
5184      * @return imported binding identifier
5185      */
5186     private Module.ImportEntry nameSpaceImport() {
5187         assert type == MUL;
5188         next();
5189         final long asToken = token;
5190         final String as = (String) expectValue(IDENT);
5191         if (!"as".equals(as)) {
5192             throw error(AbstractParser.message("expected.as"), asToken);
5193         }
5194         final IdentNode localNameSpace = bindingIdentifier("ImportedBinding");
5195         return Module.ImportEntry.importStarAsNameSpaceFrom(localNameSpace.getName());
5196     }
5197 
5198     /**
5199      * NamedImports :
5200      *     { }
5201      *     { ImportsList }
5202      *     { ImportsList , }
5203      * ImportsList :
5204      *     ImportSpecifier
5205      *     ImportsList , ImportSpecifier
5206      * ImportSpecifier :
5207      *     ImportedBinding
5208      *     IdentifierName as ImportedBinding
5209      * ImportedBinding :
5210      *     BindingIdentifier
5211      */
5212     private List<Module.ImportEntry> namedImports() {
5213         assert type == LBRACE;
5214         next();
5215         List<Module.ImportEntry> importEntries = new ArrayList<>();
5216         while (type != RBRACE) {
5217             final boolean bindingIdentifier = isBindingIdentifier();
5218             final long nameToken = token;
5219             final IdentNode importName = getIdentifierName();
5220             if (type == IDENT && "as".equals(getValue())) {
5221                 next();
5222                 final IdentNode localName = bindingIdentifier("ImportedBinding");
5223                 importEntries.add(Module.ImportEntry.importSpecifier(importName.getName(), localName.getName()));
5224             } else if (!bindingIdentifier) {
5225                 throw error(AbstractParser.message("expected.binding.identifier"), nameToken);
5226             } else {
5227                 importEntries.add(Module.ImportEntry.importSpecifier(importName.getName()));
5228             }
5229             if (type == COMMARIGHT) {
5230                 next();
5231             } else {
5232                 break;
5233             }
5234         }
5235         expect(RBRACE);
5236         return importEntries;
5237     }
5238 
5239     /**
5240      * FromClause :
5241      *     from ModuleSpecifier
5242      */
5243     private String fromClause() {
5244         final long fromToken = token;
5245         final String name = (String) expectValue(IDENT);
5246         if (!"from".equals(name)) {
5247             throw error(AbstractParser.message("expected.from"), fromToken);
5248         }
5249         if (type == STRING || type == ESCSTRING) {
5250             final String moduleSpecifier = (String) getValue();
5251             next();
5252             return moduleSpecifier;
5253         } else {
5254             throw error(expectMessage(STRING));
5255         }
5256     }
5257 
5258     /**
5259      * Parse export declaration.
5260      *
5261      * ExportDeclaration :
5262      *     export * FromClause ;
5263      *     export ExportClause FromClause ;
5264      *     export ExportClause ;
5265      *     export VariableStatement
5266      *     export Declaration
5267      *     export default HoistableDeclaration[Default]
5268      *     export default ClassDeclaration[Default]
5269      *     export default [lookahead !in {function, class}] AssignmentExpression[In] ;
5270      */
5271     private void exportDeclaration() {
5272         expect(EXPORT);
5273         final ParserContextModuleNode module = lc.getCurrentModule();
5274         switch (type) {
5275             case MUL: {
5276                 next();
5277                 final String moduleRequest = fromClause();
5278                 expect(SEMICOLON);
5279                 module.addModuleRequest(moduleRequest);
5280                 module.addStarExportEntry(Module.ExportEntry.exportStarFrom(moduleRequest));
5281                 break;
5282             }
5283             case LBRACE: {
5284                 final List<Module.ExportEntry> exportEntries = exportClause();
5285                 if (type == IDENT && "from".equals(getValue())) {
5286                     final String moduleRequest = fromClause();
5287                     module.addModuleRequest(moduleRequest);
5288                     for (Module.ExportEntry exportEntry : exportEntries) {
5289                         module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest));
5290                     }
5291                 } else {
5292                     for (Module.ExportEntry exportEntry : exportEntries) {
5293                         module.addLocalExportEntry(exportEntry);
5294                     }
5295                 }
5296                 expect(SEMICOLON);
5297                 break;
5298             }
5299             case DEFAULT:
5300                 next();
5301                 final Expression assignmentExpression;
5302                 IdentNode ident;
5303                 final int lineNumber = line;
5304                 final long rhsToken = token;
5305                 final boolean declaration;
5306                 switch (type) {
5307                     case FUNCTION:
5308                         assignmentExpression = functionExpression(false, true);
5309                         ident = ((FunctionNode) assignmentExpression).getIdent();
5310                         declaration = true;
5311                         break;
5312                     case CLASS:
5313                         assignmentExpression = classDeclaration(true);
5314                         ident = ((ClassNode) assignmentExpression).getIdent();
5315                         declaration = true;
5316                         break;
5317                     default:
5318                         assignmentExpression = assignmentExpression(false);
5319                         ident = null;
5320                         declaration = false;
5321                         break;
5322                 }
5323                 if (ident != null) {
5324                     module.addLocalExportEntry(Module.ExportEntry.exportDefault(ident.getName()));
5325                 } else {
5326                     ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME);
5327                     lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression));
5328                     if (!declaration) {
5329                         expect(SEMICOLON);
5330                     }
5331                     module.addLocalExportEntry(Module.ExportEntry.exportDefault());
5332                 }
5333                 break;
5334             case VAR:
5335             case LET:
5336             case CONST:
5337                 final List<Statement> statements = lc.getCurrentBlock().getStatements();
5338                 final int previousEnd = statements.size();
5339                 variableStatement(type);
5340                 for (final Statement statement : statements.subList(previousEnd, statements.size())) {
5341                     if (statement instanceof VarNode) {
5342                         module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName().getName()));
5343                     }
5344                 }
5345                 break;
5346             case CLASS: {
5347                 final ClassNode classDeclaration = classDeclaration(false);
5348                 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent().getName()));
5349                 break;
5350             }
5351             case FUNCTION: {
5352                 final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true);
5353                 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent().getName()));
5354                 break;
5355             }
5356             default:
5357                 throw error(AbstractParser.message("invalid.export"), token);
5358         }
5359     }
5360 
5361     /**
5362      * ExportClause :
5363      *     { }
5364      *     { ExportsList }
5365      *     { ExportsList , }
5366      * ExportsList :
5367      *     ExportSpecifier
5368      *     ExportsList , ExportSpecifier
5369      * ExportSpecifier :
5370      *     IdentifierName
5371      *     IdentifierName as IdentifierName
5372      *
5373      * @return a list of ExportSpecifiers
5374      */
5375     private List<Module.ExportEntry> exportClause() {
5376         assert type == LBRACE;
5377         next();
5378         List<Module.ExportEntry> exports = new ArrayList<>();
5379         while (type != RBRACE) {
5380             final IdentNode localName = getIdentifierName();
5381             if (type == IDENT && "as".equals(getValue())) {
5382                 next();
5383                 final IdentNode exportName = getIdentifierName();
5384                 exports.add(Module.ExportEntry.exportSpecifier(exportName.getName(), localName.getName()));
5385             } else {
5386                 exports.add(Module.ExportEntry.exportSpecifier(localName.getName()));
5387             }
5388             if (type == COMMARIGHT) {
5389                 next();
5390             } else {
5391                 break;
5392             }
5393         }
5394         expect(RBRACE);
5395         return exports;
5396     }
5397 
5398     @Override
5399     public String toString() {
5400         return "'JavaScript Parsing'";
5401     }
5402 
5403     private static void markEval(final ParserContext lc) {
5404         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5405         boolean flaggedCurrentFn = false;
5406         while (iter.hasNext()) {
5407             final ParserContextFunctionNode fn = iter.next();
5408             if (!flaggedCurrentFn) {
5409                 fn.setFlag(FunctionNode.HAS_EVAL);
5410                 flaggedCurrentFn = true;
5411                 if (fn.getKind() == FunctionNode.Kind.ARROW) {
5412                     // possible use of this in an eval that's nested in an arrow function, e.g.:
5413                     // function fun(){ return (() => eval("this"))(); };
5414                     markThis(lc);
5415                     markNewTarget(lc);
5416                 }
5417             } else {
5418                 fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
5419             }
5420             final ParserContextBlockNode body = lc.getFunctionBody(fn);
5421             // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
5422             // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
5423             // this method when the parser skips a nested function.
5424             body.setFlag(Block.NEEDS_SCOPE);
5425             fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
5426         }
5427     }
5428 
5429     private void prependStatement(final Statement statement) {
5430         lc.prependStatementToCurrentNode(statement);
5431     }
5432 
5433     private void appendStatement(final Statement statement) {
5434         lc.appendStatementToCurrentNode(statement);
5435     }
5436 
5437     private static void markSuperCall(final ParserContext lc) {
5438         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5439         while (iter.hasNext()) {
5440             final ParserContextFunctionNode fn = iter.next();
5441             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5442                 assert fn.isSubclassConstructor();
5443                 fn.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
5444                 break;
5445             }
5446         }
5447     }
5448 
5449     private ParserContextFunctionNode getCurrentNonArrowFunction() {
5450         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5451         while (iter.hasNext()) {
5452             final ParserContextFunctionNode fn = iter.next();
5453             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5454                 return fn;
5455             }
5456         }
5457         return null;
5458     }
5459 
5460     private static void markThis(final ParserContext lc) {
5461         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5462         while (iter.hasNext()) {
5463             final ParserContextFunctionNode fn = iter.next();
5464             fn.setFlag(FunctionNode.USES_THIS);
5465             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5466                 break;
5467             }
5468         }
5469     }
5470 
5471     private static void markNewTarget(final ParserContext lc) {
5472         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5473         while (iter.hasNext()) {
5474             final ParserContextFunctionNode fn = iter.next();
5475             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5476                 if (!fn.isProgram()) {
5477                     fn.setFlag(FunctionNode.ES6_USES_NEW_TARGET);
5478                 }
5479                 break;
5480             }
5481         }
5482     }
5483 
5484     private boolean inGeneratorFunction() {
5485         return lc.getCurrentFunction().getKind() == FunctionNode.Kind.GENERATOR;
5486     }
5487 }