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.ASSIGN;
  32 import static jdk.nashorn.internal.parser.TokenType.CASE;
  33 import static jdk.nashorn.internal.parser.TokenType.CATCH;
  34 import static jdk.nashorn.internal.parser.TokenType.COLON;
  35 import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
  36 import static jdk.nashorn.internal.parser.TokenType.CONST;
  37 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
  38 import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
  39 import static jdk.nashorn.internal.parser.TokenType.ELSE;
  40 import static jdk.nashorn.internal.parser.TokenType.EOF;
  41 import static jdk.nashorn.internal.parser.TokenType.EOL;
  42 import static jdk.nashorn.internal.parser.TokenType.FINALLY;
  43 import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
  44 import static jdk.nashorn.internal.parser.TokenType.IDENT;
  45 import static jdk.nashorn.internal.parser.TokenType.IF;
  46 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
  47 import static jdk.nashorn.internal.parser.TokenType.LBRACE;
  48 import static jdk.nashorn.internal.parser.TokenType.LET;
  49 import static jdk.nashorn.internal.parser.TokenType.LPAREN;
  50 import static jdk.nashorn.internal.parser.TokenType.RBRACE;
  51 import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
  52 import static jdk.nashorn.internal.parser.TokenType.RPAREN;
  53 import static jdk.nashorn.internal.parser.TokenType.SEMICOLON;
  54 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE;
  55 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_HEAD;
  56 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_MIDDLE;
  57 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_TAIL;
  58 import static jdk.nashorn.internal.parser.TokenType.TERNARY;
  59 import static jdk.nashorn.internal.parser.TokenType.WHILE;
  60 
  61 import java.io.Serializable;
  62 import java.util.ArrayDeque;
  63 import java.util.ArrayList;
  64 import java.util.Collections;
  65 import java.util.Deque;
  66 import java.util.HashMap;
  67 import java.util.HashSet;
  68 import java.util.Iterator;
  69 import java.util.List;
  70 import java.util.Map;
  71 import jdk.nashorn.internal.codegen.CompilerConstants;
  72 import jdk.nashorn.internal.codegen.Namespace;
  73 import jdk.nashorn.internal.ir.AccessNode;
  74 import jdk.nashorn.internal.ir.BaseNode;
  75 import jdk.nashorn.internal.ir.BinaryNode;
  76 import jdk.nashorn.internal.ir.Block;
  77 import jdk.nashorn.internal.ir.BlockStatement;
  78 import jdk.nashorn.internal.ir.BreakNode;
  79 import jdk.nashorn.internal.ir.CallNode;
  80 import jdk.nashorn.internal.ir.CaseNode;
  81 import jdk.nashorn.internal.ir.CatchNode;
  82 import jdk.nashorn.internal.ir.ContinueNode;
  83 import jdk.nashorn.internal.ir.DebuggerNode;
  84 import jdk.nashorn.internal.ir.EmptyNode;
  85 import jdk.nashorn.internal.ir.ErrorNode;
  86 import jdk.nashorn.internal.ir.Expression;
  87 import jdk.nashorn.internal.ir.ExpressionStatement;
  88 import jdk.nashorn.internal.ir.ForNode;
  89 import jdk.nashorn.internal.ir.FunctionNode;
  90 import jdk.nashorn.internal.ir.IdentNode;
  91 import jdk.nashorn.internal.ir.IfNode;
  92 import jdk.nashorn.internal.ir.IndexNode;
  93 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
  94 import jdk.nashorn.internal.ir.LabelNode;
  95 import jdk.nashorn.internal.ir.LiteralNode;
  96 import jdk.nashorn.internal.ir.Node;
  97 import jdk.nashorn.internal.ir.ObjectNode;
  98 import jdk.nashorn.internal.ir.PropertyKey;
  99 import jdk.nashorn.internal.ir.PropertyNode;
 100 import jdk.nashorn.internal.ir.ReturnNode;
 101 import jdk.nashorn.internal.ir.RuntimeNode;
 102 import jdk.nashorn.internal.ir.Statement;
 103 import jdk.nashorn.internal.ir.SwitchNode;
 104 import jdk.nashorn.internal.ir.TernaryNode;
 105 import jdk.nashorn.internal.ir.ThrowNode;
 106 import jdk.nashorn.internal.ir.TryNode;
 107 import jdk.nashorn.internal.ir.UnaryNode;
 108 import jdk.nashorn.internal.ir.VarNode;
 109 import jdk.nashorn.internal.ir.WhileNode;
 110 import jdk.nashorn.internal.ir.WithNode;
 111 import jdk.nashorn.internal.ir.debug.ASTWriter;
 112 import jdk.nashorn.internal.ir.debug.PrintVisitor;
 113 import jdk.nashorn.internal.runtime.Context;
 114 import jdk.nashorn.internal.runtime.ErrorManager;
 115 import jdk.nashorn.internal.runtime.JSErrorType;
 116 import jdk.nashorn.internal.runtime.ParserException;
 117 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 118 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 119 import jdk.nashorn.internal.runtime.ScriptingFunctions;
 120 import jdk.nashorn.internal.runtime.Source;
 121 import jdk.nashorn.internal.runtime.Timing;
 122 import jdk.nashorn.internal.runtime.linker.NameCodec;
 123 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 124 import jdk.nashorn.internal.runtime.logging.Loggable;
 125 import jdk.nashorn.internal.runtime.logging.Logger;
 126 
 127 /**
 128  * Builds the IR.
 129  */
 130 @Logger(name="parser")
 131 public class Parser extends AbstractParser implements Loggable {
 132     private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName();
 133 
 134     /** Current env. */
 135     private final ScriptEnvironment env;
 136 
 137     /** Is scripting mode. */
 138     private final boolean scripting;
 139 
 140     private List<Statement> functionDeclarations;
 141 
 142     private final ParserContext lc;
 143     private final Deque<Object> defaultNames;
 144 
 145     /** Namespace for function names where not explicitly given */
 146     private final Namespace namespace;
 147 
 148     private final DebugLogger log;
 149 
 150     /** to receive line information from Lexer when scanning multine literals. */
 151     protected final Lexer.LineInfoReceiver lineInfoReceiver;
 152 
 153     private RecompilableScriptFunctionData reparsedFunction;
 154 
 155     /**
 156      * Constructor
 157      *
 158      * @param env     script environment
 159      * @param source  source to parse
 160      * @param errors  error manager
 161      */
 162     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors) {
 163         this(env, source, errors, env._strict, null);
 164     }
 165 
 166     /**
 167      * Constructor
 168      *
 169      * @param env     script environment
 170      * @param source  source to parse
 171      * @param errors  error manager
 172      * @param strict  strict
 173      * @param log debug logger if one is needed
 174      */
 175     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) {
 176         this(env, source, errors, strict, 0, log);
 177     }
 178 
 179     /**
 180      * Construct a parser.
 181      *
 182      * @param env     script environment
 183      * @param source  source to parse
 184      * @param errors  error manager
 185      * @param strict  parser created with strict mode enabled.
 186      * @param lineOffset line offset to start counting lines from
 187      * @param log debug logger if one is needed
 188      */
 189     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) {
 190         super(source, errors, strict, lineOffset);
 191         this.lc = new ParserContext();
 192         this.defaultNames = new ArrayDeque<>();
 193         this.env = env;
 194         this.namespace = new Namespace(env.getNamespace());
 195         this.scripting = env._scripting;
 196         if (this.scripting) {
 197             this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
 198                 @Override
 199                 public void lineInfo(final int receiverLine, final int receiverLinePosition) {
 200                     // update the parser maintained line information
 201                     Parser.this.line = receiverLine;
 202                     Parser.this.linePosition = receiverLinePosition;
 203                 }
 204             };
 205         } else {
 206             // non-scripting mode script can't have multi-line literals
 207             this.lineInfoReceiver = null;
 208         }
 209 
 210         this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
 211     }
 212 
 213     @Override
 214     public DebugLogger getLogger() {
 215         return log;
 216     }
 217 
 218     @Override
 219     public DebugLogger initLogger(final Context context) {
 220         return context.getLogger(this.getClass());
 221     }
 222 
 223     /**
 224      * Sets the name for the first function. This is only used when reparsing anonymous functions to ensure they can
 225      * preserve their already assigned name, as that name doesn't appear in their source text.
 226      * @param name the name for the first parsed function.
 227      */
 228     public void setFunctionName(final String name) {
 229         defaultNames.push(createIdentNode(0, 0, name));
 230     }
 231 
 232     /**
 233      * Sets the {@link RecompilableScriptFunctionData} representing the function being reparsed (when this
 234      * parser instance is used to reparse a previously parsed function, as part of its on-demand compilation).
 235      * This will trigger various special behaviors, such as skipping nested function bodies.
 236      * @param reparsedFunction the function being reparsed.
 237      */
 238     public void setReparsedFunction(final RecompilableScriptFunctionData reparsedFunction) {
 239         this.reparsedFunction = reparsedFunction;
 240     }
 241 
 242     /**
 243      * Execute parse and return the resulting function node.
 244      * Errors will be thrown and the error manager will contain information
 245      * if parsing should fail
 246      *
 247      * This is the default parse call, which will name the function node
 248      * {code :program} {@link CompilerConstants#PROGRAM}
 249      *
 250      * @return function node resulting from successful parse
 251      */
 252     public FunctionNode parse() {
 253         return parse(PROGRAM.symbolName(), 0, source.getLength(), false);
 254     }
 255 
 256     /**
 257      * Execute parse and return the resulting function node.
 258      * Errors will be thrown and the error manager will contain information
 259      * if parsing should fail
 260      *
 261      * This should be used to create one and only one function node
 262      *
 263      * @param scriptName name for the script, given to the parsed FunctionNode
 264      * @param startPos start position in source
 265      * @param len length of parse
 266      * @param allowPropertyFunction if true, "get" and "set" are allowed as first tokens of the program, followed by
 267      * a property getter or setter function. This is used when reparsing a function that can potentially be defined as a
 268      * property getter or setter in an object literal.
 269      *
 270      * @return function node resulting from successful parse
 271      */
 272     public FunctionNode parse(final String scriptName, final int startPos, final int len, final boolean allowPropertyFunction) {
 273         final boolean isTimingEnabled = env.isTimingEnabled();
 274         final long t0 = isTimingEnabled ? System.nanoTime() : 0L;
 275         log.info(this, " begin for '", scriptName, "'");
 276 
 277         try {
 278             stream = new TokenStream();
 279             lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
 280             lexer.line = lexer.pendingLine = lineOffset + 1;
 281             line = lineOffset;
 282 
 283             // Set up first token (skips opening EOL.)
 284             k = -1;
 285             next();
 286             // Begin parse.
 287             return program(scriptName, allowPropertyFunction);
 288         } catch (final Exception e) {
 289             handleParseException(e);
 290 
 291             return null;
 292         } finally {
 293             final String end = this + " end '" + scriptName + "'";
 294             if (isTimingEnabled) {
 295                 env._timing.accumulateTime(toString(), System.nanoTime() - t0);
 296                 log.info(end, "' in ", Timing.toMillisPrint(System.nanoTime() - t0), " ms");
 297             } else {
 298                 log.info(end);
 299             }
 300         }
 301     }
 302 
 303     /**
 304      * Parse and return the list of function parameter list. A comma
 305      * separated list of function parameter identifiers is expected to be parsed.
 306      * Errors will be thrown and the error manager will contain information
 307      * if parsing should fail. This method is used to check if parameter Strings
 308      * passed to "Function" constructor is a valid or not.
 309      *
 310      * @return the list of IdentNodes representing the formal parameter list
 311      */
 312     public List<IdentNode> parseFormalParameterList() {
 313         try {
 314             stream = new TokenStream();
 315             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
 316 
 317             // Set up first token (skips opening EOL.)
 318             k = -1;
 319             next();
 320 
 321             return formalParameterList(TokenType.EOF);
 322         } catch (final Exception e) {
 323             handleParseException(e);
 324             return null;
 325         }
 326     }
 327 
 328     /**
 329      * Execute parse and return the resulting function node.
 330      * Errors will be thrown and the error manager will contain information
 331      * if parsing should fail. This method is used to check if code String
 332      * passed to "Function" constructor is a valid function body or not.
 333      *
 334      * @return function node resulting from successful parse
 335      */
 336     public FunctionNode parseFunctionBody() {
 337         try {
 338             stream = new TokenStream();
 339             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
 340             final int functionLine = line;
 341 
 342             // Set up first token (skips opening EOL.)
 343             k = -1;
 344             next();
 345 
 346             // Make a fake token for the function.
 347             final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
 348             // Set up the function to append elements.
 349 
 350             final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName());
 351             final ParserContextFunctionNode function = createParserContextFunctionNode(ident, functionToken, FunctionNode.Kind.NORMAL, functionLine, Collections.<IdentNode>emptyList());
 352             lc.push(function);
 353 
 354             final ParserContextBlockNode body = newBlock();
 355 
 356             functionDeclarations = new ArrayList<>();
 357             sourceElements(false);
 358             addFunctionDeclarations(function);
 359             functionDeclarations = null;
 360 
 361             restoreBlock(body);
 362             body.setFlag(Block.NEEDS_SCOPE);
 363 
 364             final Block functionBody = new Block(functionToken, source.getLength() - 1,
 365                 body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
 366             lc.pop(function);
 367 
 368             expect(EOF);
 369 
 370             final FunctionNode functionNode = createFunctionNode(
 371                     function,
 372                     functionToken,
 373                     ident,
 374                     Collections.<IdentNode>emptyList(),
 375                     FunctionNode.Kind.NORMAL,
 376                     functionLine,
 377                     functionBody);
 378             printAST(functionNode);
 379             return functionNode;
 380         } catch (final Exception e) {
 381             handleParseException(e);
 382             return null;
 383         }
 384     }
 385 
 386     private void handleParseException(final Exception e) {
 387         // Extract message from exception.  The message will be in error
 388         // message format.
 389         String message = e.getMessage();
 390 
 391         // If empty message.
 392         if (message == null) {
 393             message = e.toString();
 394         }
 395 
 396         // Issue message.
 397         if (e instanceof ParserException) {
 398             errors.error((ParserException)e);
 399         } else {
 400             errors.error(message);
 401         }
 402 
 403         if (env._dump_on_error) {
 404             e.printStackTrace(env.getErr());
 405         }
 406     }
 407 
 408     /**
 409      * Skip to a good parsing recovery point.
 410      */
 411     private void recover(final Exception e) {
 412         if (e != null) {
 413             // Extract message from exception.  The message will be in error
 414             // message format.
 415             String message = e.getMessage();
 416 
 417             // If empty message.
 418             if (message == null) {
 419                 message = e.toString();
 420             }
 421 
 422             // Issue message.
 423             if (e instanceof ParserException) {
 424                 errors.error((ParserException)e);
 425             } else {
 426                 errors.error(message);
 427             }
 428 
 429             if (env._dump_on_error) {
 430                 e.printStackTrace(env.getErr());
 431             }
 432         }
 433 
 434         // Skip to a recovery point.
 435 loop:
 436         while (true) {
 437             switch (type) {
 438             case EOF:
 439                 // Can not go any further.
 440                 break loop;
 441             case EOL:
 442             case SEMICOLON:
 443             case RBRACE:
 444                 // Good recovery points.
 445                 next();
 446                 break loop;
 447             default:
 448                 // So we can recover after EOL.
 449                 nextOrEOL();
 450                 break;
 451             }
 452         }
 453     }
 454 
 455     /**
 456      * Set up a new block.
 457      *
 458      * @return New block.
 459      */
 460     private ParserContextBlockNode newBlock() {
 461         return lc.push(new ParserContextBlockNode(token));
 462     }
 463 
 464     private ParserContextFunctionNode createParserContextFunctionNode(final IdentNode ident, final long functionToken, final FunctionNode.Kind kind, final int functionLine, final List<IdentNode> parameters) {
 465         // Build function name.
 466         final StringBuilder sb = new StringBuilder();
 467 
 468         final ParserContextFunctionNode parentFunction = lc.getCurrentFunction();
 469         if (parentFunction != null && !parentFunction.isProgram()) {
 470             sb.append(parentFunction.getName()).append('$');
 471         }
 472 
 473         assert ident.getName() != null;
 474         sb.append(ident.getName());
 475 
 476         final String name = namespace.uniqueName(sb.toString());
 477         assert parentFunction != null || name.equals(PROGRAM.symbolName()) || name.startsWith(RecompilableScriptFunctionData.RECOMPILATION_PREFIX) : "name = " + name;
 478 
 479         int flags = 0;
 480         if (isStrictMode) {
 481             flags |= FunctionNode.IS_STRICT;
 482         }
 483         if (parentFunction == null) {
 484             flags |= FunctionNode.IS_PROGRAM;
 485         }
 486 
 487         final ParserContextFunctionNode functionNode = new ParserContextFunctionNode(functionToken, ident, name, namespace, functionLine, kind, parameters);
 488         functionNode.setFlag(flags);
 489         return functionNode;
 490     }
 491 
 492     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){
 493         // Start new block.
 494         final FunctionNode functionNode =
 495             new FunctionNode(
 496                 source,
 497                 functionLine,
 498                 body.getToken(),
 499                 Token.descPosition(body.getToken()),
 500                 startToken,
 501                 function.getLastToken(),
 502                 namespace,
 503                 ident,
 504                 function.getName(),
 505                 parameters,
 506                 kind,
 507                 function.getFlags(),
 508                 body,
 509                 function.getEndParserState());
 510 
 511         printAST(functionNode);
 512 
 513         return functionNode;
 514     }
 515 
 516     /**
 517      * Restore the current block.
 518      */
 519     private ParserContextBlockNode restoreBlock(final ParserContextBlockNode block) {
 520         return lc.pop(block);
 521     }
 522 
 523     /**
 524      * Get the statements in a block.
 525      * @return Block statements.
 526      */
 527     private Block getBlock(final boolean needsBraces) {
 528         final long blockToken = token;
 529         final ParserContextBlockNode newBlock = newBlock();
 530         try {
 531             // Block opening brace.
 532             if (needsBraces) {
 533                 expect(LBRACE);
 534             }
 535             // Accumulate block statements.
 536             statementList();
 537 
 538         } finally {
 539             restoreBlock(newBlock);
 540         }
 541 
 542         // Block closing brace.
 543         if (needsBraces) {
 544             expect(RBRACE);
 545         }
 546 
 547         final int flags = newBlock.getFlags() | (needsBraces? 0 : Block.IS_SYNTHETIC);
 548         return new Block(blockToken, finish, flags, newBlock.getStatements());
 549     }
 550 
 551 
 552     /**
 553      * Get all the statements generated by a single statement.
 554      * @return Statements.
 555      */
 556     private Block getStatement() {
 557         if (type == LBRACE) {
 558             return getBlock(true);
 559         }
 560         // Set up new block. Captures first token.
 561         final ParserContextBlockNode newBlock = newBlock();
 562         try {
 563             statement(false, false, true);
 564         } finally {
 565             restoreBlock(newBlock);
 566         }
 567         return new Block(newBlock.getToken(), finish, newBlock.getFlags() | Block.IS_SYNTHETIC, newBlock.getStatements());
 568     }
 569 
 570     /**
 571      * Detect calls to special functions.
 572      * @param ident Called function.
 573      */
 574     private void detectSpecialFunction(final IdentNode ident) {
 575         final String name = ident.getName();
 576 
 577         if (EVAL.symbolName().equals(name)) {
 578             markEval(lc);
 579         }
 580     }
 581 
 582     /**
 583      * Detect use of special properties.
 584      * @param ident Referenced property.
 585      */
 586     private void detectSpecialProperty(final IdentNode ident) {
 587         if (isArguments(ident)) {
 588             lc.getCurrentFunction().setFlag(FunctionNode.USES_ARGUMENTS);
 589         }
 590     }
 591 
 592     private boolean useBlockScope() {
 593         return env._es6;
 594     }
 595 
 596     private static boolean isArguments(final String name) {
 597         return ARGUMENTS_NAME.equals(name);
 598     }
 599 
 600     private static boolean isArguments(final IdentNode ident) {
 601         return isArguments(ident.getName());
 602     }
 603 
 604     /**
 605      * Tells whether a IdentNode can be used as L-value of an assignment
 606      *
 607      * @param ident IdentNode to be checked
 608      * @return whether the ident can be used as L-value
 609      */
 610     private static boolean checkIdentLValue(final IdentNode ident) {
 611         return ident.tokenType().getKind() != TokenKind.KEYWORD;
 612     }
 613 
 614     /**
 615      * Verify an assignment expression.
 616      * @param op  Operation token.
 617      * @param lhs Left hand side expression.
 618      * @param rhs Right hand side expression.
 619      * @return Verified expression.
 620      */
 621     private Expression verifyAssignment(final long op, final Expression lhs, final Expression rhs) {
 622         final TokenType opType = Token.descType(op);
 623 
 624         switch (opType) {
 625         case ASSIGN:
 626         case ASSIGN_ADD:
 627         case ASSIGN_BIT_AND:
 628         case ASSIGN_BIT_OR:
 629         case ASSIGN_BIT_XOR:
 630         case ASSIGN_DIV:
 631         case ASSIGN_MOD:
 632         case ASSIGN_MUL:
 633         case ASSIGN_SAR:
 634         case ASSIGN_SHL:
 635         case ASSIGN_SHR:
 636         case ASSIGN_SUB:
 637             if (!(lhs instanceof AccessNode ||
 638                   lhs instanceof IndexNode ||
 639                   lhs instanceof IdentNode)) {
 640                 return referenceError(lhs, rhs, env._early_lvalue_error);
 641             }
 642 
 643             if (lhs instanceof IdentNode) {
 644                 if (!checkIdentLValue((IdentNode)lhs)) {
 645                     return referenceError(lhs, rhs, false);
 646                 }
 647                 verifyStrictIdent((IdentNode)lhs, "assignment");
 648             }
 649             break;
 650 
 651         default:
 652             break;
 653         }
 654 
 655         // Build up node.
 656         if(BinaryNode.isLogical(opType)) {
 657             return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs));
 658         }
 659         return new BinaryNode(op, lhs, rhs);
 660     }
 661 
 662 
 663     /**
 664      * Reduce increment/decrement to simpler operations.
 665      * @param firstToken First token.
 666      * @param tokenType  Operation token (INCPREFIX/DEC.)
 667      * @param expression Left hand side expression.
 668      * @param isPostfix  Prefix or postfix.
 669      * @return           Reduced expression.
 670      */
 671     private static UnaryNode incDecExpression(final long firstToken, final TokenType tokenType, final Expression expression, final boolean isPostfix) {
 672         if (isPostfix) {
 673             return new UnaryNode(Token.recast(firstToken, tokenType == DECPREFIX ? DECPOSTFIX : INCPOSTFIX), expression.getStart(), Token.descPosition(firstToken) + Token.descLength(firstToken), expression);
 674         }
 675 
 676         return new UnaryNode(firstToken, expression);
 677     }
 678 
 679     /**
 680      * -----------------------------------------------------------------------
 681      *
 682      * Grammar based on
 683      *
 684      *      ECMAScript Language Specification
 685      *      ECMA-262 5th Edition / December 2009
 686      *
 687      * -----------------------------------------------------------------------
 688      */
 689 
 690     /**
 691      * Program :
 692      *      SourceElements?
 693      *
 694      * See 14
 695      *
 696      * Parse the top level script.
 697      */
 698     private FunctionNode program(final String scriptName, final boolean allowPropertyFunction) {
 699         // Make a pseudo-token for the script holding its start and length.
 700         final long functionToken = Token.toDesc(FUNCTION, Token.descPosition(Token.withDelimiter(token)), source.getLength());
 701         final int  functionLine  = line;
 702 
 703         final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), scriptName);
 704         final ParserContextFunctionNode script = createParserContextFunctionNode(
 705                 ident,
 706                 functionToken,
 707                 FunctionNode.Kind.SCRIPT,
 708                 functionLine,
 709                 Collections.<IdentNode>emptyList());
 710         lc.push(script);
 711         final ParserContextBlockNode body = newBlock();
 712 
 713         functionDeclarations = new ArrayList<>();
 714         sourceElements(allowPropertyFunction);
 715         addFunctionDeclarations(script);
 716         functionDeclarations = null;
 717 
 718         restoreBlock(body);
 719         body.setFlag(Block.NEEDS_SCOPE);
 720         final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
 721         lc.pop(script);
 722         script.setLastToken(token);
 723 
 724         expect(EOF);
 725 
 726         return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.SCRIPT, functionLine, programBody);
 727     }
 728 
 729     /**
 730      * Directive value or null if statement is not a directive.
 731      *
 732      * @param stmt Statement to be checked
 733      * @return Directive value if the given statement is a directive
 734      */
 735     private String getDirective(final Node stmt) {
 736         if (stmt instanceof ExpressionStatement) {
 737             final Node expr = ((ExpressionStatement)stmt).getExpression();
 738             if (expr instanceof LiteralNode) {
 739                 final LiteralNode<?> lit = (LiteralNode<?>)expr;
 740                 final long litToken = lit.getToken();
 741                 final TokenType tt = Token.descType(litToken);
 742                 // A directive is either a string or an escape string
 743                 if (tt == TokenType.STRING || tt == TokenType.ESCSTRING) {
 744                     // Make sure that we don't unescape anything. Return as seen in source!
 745                     return source.getString(lit.getStart(), Token.descLength(litToken));
 746                 }
 747             }
 748         }
 749 
 750         return null;
 751     }
 752 
 753     /**
 754      * SourceElements :
 755      *      SourceElement
 756      *      SourceElements SourceElement
 757      *
 758      * See 14
 759      *
 760      * Parse the elements of the script or function.
 761      */
 762     private void sourceElements(final boolean shouldAllowPropertyFunction) {
 763         List<Node>    directiveStmts        = null;
 764         boolean       checkDirective        = true;
 765         boolean       allowPropertyFunction = shouldAllowPropertyFunction;
 766         final boolean oldStrictMode         = isStrictMode;
 767 
 768 
 769         try {
 770             // If is a script, then process until the end of the script.
 771             while (type != EOF) {
 772                 // Break if the end of a code block.
 773                 if (type == RBRACE) {
 774                     break;
 775                 }
 776 
 777                 try {
 778                     // Get the next element.
 779                     statement(true, allowPropertyFunction, false);
 780                     allowPropertyFunction = false;
 781 
 782                     // check for directive prologues
 783                     if (checkDirective) {
 784                         // skip any debug statement like line number to get actual first line
 785                         final Statement lastStatement = lc.getLastStatement();
 786 
 787                         // get directive prologue, if any
 788                         final String directive = getDirective(lastStatement);
 789 
 790                         // If we have seen first non-directive statement,
 791                         // no more directive statements!!
 792                         checkDirective = directive != null;
 793 
 794                         if (checkDirective) {
 795                             if (!oldStrictMode) {
 796                                 if (directiveStmts == null) {
 797                                     directiveStmts = new ArrayList<>();
 798                                 }
 799                                 directiveStmts.add(lastStatement);
 800                             }
 801 
 802                             // handle use strict directive
 803                             if ("use strict".equals(directive)) {
 804                                 isStrictMode = true;
 805                                 final ParserContextFunctionNode function = lc.getCurrentFunction();
 806                                 function.setFlag(FunctionNode.IS_STRICT);
 807 
 808                                 // We don't need to check these, if lexical environment is already strict
 809                                 if (!oldStrictMode && directiveStmts != null) {
 810                                     // check that directives preceding this one do not violate strictness
 811                                     for (final Node statement : directiveStmts) {
 812                                         // the get value will force unescape of preceding
 813                                         // escaped string directives
 814                                         getValue(statement.getToken());
 815                                     }
 816 
 817                                     // verify that function name as well as parameter names
 818                                     // satisfy strict mode restrictions.
 819                                     verifyStrictIdent(function.getIdent(), "function name");
 820                                     for (final IdentNode param : function.getParameters()) {
 821                                         verifyStrictIdent(param, "function parameter");
 822                                     }
 823                                 }
 824                             } else if (Context.DEBUG) {
 825                                 final int flag = FunctionNode.getDirectiveFlag(directive);
 826                                 if (flag != 0) {
 827                                     final ParserContextFunctionNode function = lc.getCurrentFunction();
 828                                     function.setFlag(flag);
 829                                 }
 830                             }
 831                         }
 832                     }
 833                 } catch (final Exception e) {
 834                     final int errorLine = line;
 835                     final long errorToken = token;
 836                     //recover parsing
 837                     recover(e);
 838                     final ErrorNode errorExpr = new ErrorNode(errorToken, finish);
 839                     final ExpressionStatement expressionStatement = new ExpressionStatement(errorLine, errorToken, finish, errorExpr);
 840                     appendStatement(expressionStatement);
 841                 }
 842 
 843                 // No backtracking from here on.
 844                 stream.commit(k);
 845             }
 846         } finally {
 847             isStrictMode = oldStrictMode;
 848         }
 849     }
 850 
 851     /**
 852      * Statement :
 853      *      Block
 854      *      VariableStatement
 855      *      EmptyStatement
 856      *      ExpressionStatement
 857      *      IfStatement
 858      *      IterationStatement
 859      *      ContinueStatement
 860      *      BreakStatement
 861      *      ReturnStatement
 862      *      WithStatement
 863      *      LabelledStatement
 864      *      SwitchStatement
 865      *      ThrowStatement
 866      *      TryStatement
 867      *      DebuggerStatement
 868      *
 869      * see 12
 870      *
 871      * Parse any of the basic statement types.
 872      */
 873     private void statement() {
 874         statement(false, false, false);
 875     }
 876 
 877     /**
 878      * @param topLevel does this statement occur at the "top level" of a script or a function?
 879      * @param allowPropertyFunction allow property "get" and "set" functions?
 880      * @param singleStatement are we in a single statement context?
 881      */
 882     private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
 883         if (type == FUNCTION) {
 884             // As per spec (ECMA section 12), function declarations as arbitrary statement
 885             // is not "portable". Implementation can issue a warning or disallow the same.
 886             functionExpression(true, topLevel);
 887             return;
 888         }
 889 
 890         switch (type) {
 891         case LBRACE:
 892             block();
 893             break;
 894         case VAR:
 895             variableStatement(type, true);
 896             break;
 897         case SEMICOLON:
 898             emptyStatement();
 899             break;
 900         case IF:
 901             ifStatement();
 902             break;
 903         case FOR:
 904             forStatement();
 905             break;
 906         case WHILE:
 907             whileStatement();
 908             break;
 909         case DO:
 910             doStatement();
 911             break;
 912         case CONTINUE:
 913             continueStatement();
 914             break;
 915         case BREAK:
 916             breakStatement();
 917             break;
 918         case RETURN:
 919             returnStatement();
 920             break;
 921         case YIELD:
 922             yieldStatement();
 923             break;
 924         case WITH:
 925             withStatement();
 926             break;
 927         case SWITCH:
 928             switchStatement();
 929             break;
 930         case THROW:
 931             throwStatement();
 932             break;
 933         case TRY:
 934             tryStatement();
 935             break;
 936         case DEBUGGER:
 937             debuggerStatement();
 938             break;
 939         case RPAREN:
 940         case RBRACKET:
 941         case EOF:
 942             expect(SEMICOLON);
 943             break;
 944         default:
 945             if (useBlockScope() && (type == LET || type == CONST)) {
 946                 if (singleStatement) {
 947                     throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
 948                 }
 949                 variableStatement(type, true);
 950                 break;
 951             }
 952             if (env._const_as_var && type == CONST) {
 953                 variableStatement(TokenType.VAR, true);
 954                 break;
 955             }
 956 
 957             if (type == IDENT || isNonStrictModeIdent()) {
 958                 if (T(k + 1) == COLON) {
 959                     labelStatement();
 960                     return;
 961                 }
 962                 if(allowPropertyFunction) {
 963                     final String ident = (String)getValue();
 964                     final long propertyToken = token;
 965                     final int propertyLine = line;
 966                     if("get".equals(ident)) {
 967                         next();
 968                         addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
 969                         return;
 970                     } else if("set".equals(ident)) {
 971                         next();
 972                         addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
 973                         return;
 974                     }
 975                 }
 976             }
 977 
 978             expressionStatement();
 979             break;
 980         }
 981     }
 982 
 983     private void addPropertyFunctionStatement(final PropertyFunction propertyFunction) {
 984         final FunctionNode fn = propertyFunction.functionNode;
 985         functionDeclarations.add(new ExpressionStatement(fn.getLineNumber(), fn.getToken(), finish, fn));
 986     }
 987 
 988     /**
 989      * block :
 990      *      { StatementList? }
 991      *
 992      * see 12.1
 993      *
 994      * Parse a statement block.
 995      */
 996     private void block() {
 997         appendStatement(new BlockStatement(line, getBlock(true)));
 998     }
 999 
1000     /**
1001      * StatementList :
1002      *      Statement
1003      *      StatementList Statement
1004      *
1005      * See 12.1
1006      *
1007      * Parse a list of statements.
1008      */
1009     private void statementList() {
1010         // Accumulate statements until end of list. */
1011 loop:
1012         while (type != EOF) {
1013             switch (type) {
1014             case EOF:
1015             case CASE:
1016             case DEFAULT:
1017             case RBRACE:
1018                 break loop;
1019             default:
1020                 break;
1021             }
1022 
1023             // Get next statement.
1024             statement();
1025         }
1026     }
1027 
1028     /**
1029      * Make sure that in strict mode, the identifier name used is allowed.
1030      *
1031      * @param ident         Identifier that is verified
1032      * @param contextString String used in error message to give context to the user
1033      */
1034     private void verifyStrictIdent(final IdentNode ident, final String contextString) {
1035         if (isStrictMode) {
1036             switch (ident.getName()) {
1037             case "eval":
1038             case "arguments":
1039                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1040             default:
1041                 break;
1042             }
1043 
1044             if (ident.isFutureStrictName()) {
1045                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1046             }
1047         }
1048     }
1049 
1050     /**
1051      * VariableStatement :
1052      *      var VariableDeclarationList ;
1053      *
1054      * VariableDeclarationList :
1055      *      VariableDeclaration
1056      *      VariableDeclarationList , VariableDeclaration
1057      *
1058      * VariableDeclaration :
1059      *      Identifier Initializer?
1060      *
1061      * Initializer :
1062      *      = AssignmentExpression
1063      *
1064      * See 12.2
1065      *
1066      * Parse a VAR statement.
1067      * @param isStatement True if a statement (not used in a FOR.)
1068      */
1069     private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
1070         return variableStatement(varType, isStatement, -1);
1071     }
1072 
1073     private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) {
1074         // VAR tested in caller.
1075         next();
1076 
1077         final List<VarNode> vars = new ArrayList<>();
1078         int varFlags = 0;
1079         if (varType == LET) {
1080             varFlags |= VarNode.IS_LET;
1081         } else if (varType == CONST) {
1082             varFlags |= VarNode.IS_CONST;
1083         }
1084 
1085         while (true) {
1086             // Get starting token.
1087             final int  varLine  = line;
1088             final long varToken = token;
1089             // Get name of var.
1090             final IdentNode name = getIdent();
1091             verifyStrictIdent(name, "variable name");
1092 
1093             // Assume no init.
1094             Expression init = null;
1095 
1096             // Look for initializer assignment.
1097             if (type == ASSIGN) {
1098                 next();
1099 
1100                 // Get initializer expression. Suppress IN if not statement.
1101                 defaultNames.push(name);
1102                 try {
1103                     init = assignmentExpression(!isStatement);
1104                 } finally {
1105                     defaultNames.pop();
1106                 }
1107             } else if (varType == CONST && isStatement) {
1108                 throw error(AbstractParser.message("missing.const.assignment", name.getName()));
1109             }
1110 
1111             // Only set declaration flag on lexically scoped let/const as it adds runtime overhead.
1112             final IdentNode actualName = varType == LET || varType == CONST ? name.setIsDeclaredHere() : name;
1113             // Allocate var node.
1114             final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, actualName, init, varFlags);
1115             vars.add(var);
1116             appendStatement(var);
1117 
1118             if (type != COMMARIGHT) {
1119                 break;
1120             }
1121             next();
1122         }
1123 
1124         // If is a statement then handle end of line.
1125         if (isStatement) {
1126             endOfLine();
1127         }
1128 
1129         return vars;
1130     }
1131 
1132     /**
1133      * EmptyStatement :
1134      *      ;
1135      *
1136      * See 12.3
1137      *
1138      * Parse an empty statement.
1139      */
1140     private void emptyStatement() {
1141         if (env._empty_statements) {
1142             appendStatement(new EmptyNode(line, token, Token.descPosition(token) + Token.descLength(token)));
1143         }
1144 
1145         // SEMICOLON checked in caller.
1146         next();
1147     }
1148 
1149     /**
1150      * ExpressionStatement :
1151      *      Expression ; // [lookahead ~( or  function )]
1152      *
1153      * See 12.4
1154      *
1155      * Parse an expression used in a statement block.
1156      */
1157     private void expressionStatement() {
1158         // Lookahead checked in caller.
1159         final int  expressionLine  = line;
1160         final long expressionToken = token;
1161 
1162         // Get expression and add as statement.
1163         final Expression expression = expression();
1164 
1165         ExpressionStatement expressionStatement = null;
1166         if (expression != null) {
1167             expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
1168             appendStatement(expressionStatement);
1169         } else {
1170             expect(null);
1171         }
1172 
1173         endOfLine();
1174     }
1175 
1176     /**
1177      * IfStatement :
1178      *      if ( Expression ) Statement else Statement
1179      *      if ( Expression ) Statement
1180      *
1181      * See 12.5
1182      *
1183      * Parse an IF statement.
1184      */
1185     private void ifStatement() {
1186         // Capture IF token.
1187         final int  ifLine  = line;
1188         final long ifToken = token;
1189          // IF tested in caller.
1190         next();
1191 
1192         expect(LPAREN);
1193         final Expression test = expression();
1194         expect(RPAREN);
1195         final Block pass = getStatement();
1196 
1197         Block fail = null;
1198         if (type == ELSE) {
1199             next();
1200             fail = getStatement();
1201         }
1202 
1203         appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1204     }
1205 
1206     /**
1207      * ... IterationStatement:
1208      *           ...
1209      *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1210      *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1211      *           for ( LeftHandSideExpression in Expression ) Statement
1212      *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1213      *
1214      * See 12.6
1215      *
1216      * Parse a FOR statement.
1217      */
1218     private void forStatement() {
1219         final long forToken = token;
1220         final int forLine = line;
1221         // start position of this for statement. This is used
1222         // for sort order for variables declared in the initializer
1223         // part of this 'for' statement (if any).
1224         final int forStart = Token.descPosition(forToken);
1225         // When ES6 for-let is enabled we create a container block to capture the LET.
1226         final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1227 
1228         // Create FOR node, capturing FOR token.
1229         final ParserContextLoopNode forNode = new ParserContextLoopNode();
1230         lc.push(forNode);
1231         Block body = null;
1232         List<VarNode> vars = null;
1233         Expression init = null;
1234         JoinPredecessorExpression test = null;
1235         JoinPredecessorExpression modify = null;
1236 
1237         int flags = 0;
1238 
1239         try {
1240             // FOR tested in caller.
1241             next();
1242 
1243             // Nashorn extension: for each expression.
1244             // iterate property values rather than property names.
1245             if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1246                 flags |= ForNode.IS_FOR_EACH;
1247                 next();
1248             }
1249 
1250             expect(LPAREN);
1251 
1252             switch (type) {
1253             case VAR:
1254                 // Var declaration captured in for outer block.
1255                 vars = variableStatement(type, false, forStart);
1256                 break;
1257             case SEMICOLON:
1258                 break;
1259             default:
1260                 if (useBlockScope() && (type == LET || type == CONST)) {
1261                     if (type == LET) {
1262                         flags |= ForNode.PER_ITERATION_SCOPE;
1263                     }
1264                     // LET/CONST declaration captured in container block created above.
1265                     vars = variableStatement(type, false, forStart);
1266                     break;
1267                 }
1268                 if (env._const_as_var && type == CONST) {
1269                     // Var declaration captured in for outer block.
1270                     vars = variableStatement(TokenType.VAR, false, forStart);
1271                     break;
1272                 }
1273 
1274                 init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1275                 break;
1276             }
1277 
1278             switch (type) {
1279             case SEMICOLON:
1280                 // for (init; test; modify)
1281 
1282                 // for each (init; test; modify) is invalid
1283                 if ((flags & ForNode.IS_FOR_EACH) != 0) {
1284                     throw error(AbstractParser.message("for.each.without.in"), token);
1285                 }
1286 
1287                 expect(SEMICOLON);
1288                 if (type != SEMICOLON) {
1289                     test = joinPredecessorExpression();
1290                 }
1291                 expect(SEMICOLON);
1292                 if (type != RPAREN) {
1293                     modify = joinPredecessorExpression();
1294                 }
1295                 break;
1296 
1297             case IN:
1298                 flags |= ForNode.IS_FOR_IN;
1299                 test = new JoinPredecessorExpression();
1300                 if (vars != null) {
1301                     // for (var i in obj)
1302                     if (vars.size() == 1) {
1303                         init = new IdentNode(vars.get(0).getName());
1304                     } else {
1305                         // for (var i, j in obj) is invalid
1306                         throw error(AbstractParser.message("many.vars.in.for.in.loop"), vars.get(1).getToken());
1307                     }
1308 
1309                 } else {
1310                     // for (expr in obj)
1311                     assert init != null : "for..in init expression can not be null here";
1312 
1313                     // check if initial expression is a valid L-value
1314                     if (!(init instanceof AccessNode ||
1315                           init instanceof IndexNode ||
1316                           init instanceof IdentNode)) {
1317                         throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
1318                     }
1319 
1320                     if (init instanceof IdentNode) {
1321                         if (!checkIdentLValue((IdentNode)init)) {
1322                             throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
1323                         }
1324                         verifyStrictIdent((IdentNode)init, "for-in iterator");
1325                     }
1326                 }
1327 
1328                 next();
1329 
1330                 // Get the collection expression.
1331                 modify = joinPredecessorExpression();
1332                 break;
1333 
1334             default:
1335                 expect(SEMICOLON);
1336                 break;
1337             }
1338 
1339             expect(RPAREN);
1340 
1341             // Set the for body.
1342             body = getStatement();
1343         } finally {
1344             lc.pop(forNode);
1345 
1346             if (vars != null) {
1347                 for (final VarNode var : vars) {
1348                     appendStatement(var);
1349                 }
1350             }
1351             if (body != null) {
1352                 appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
1353             }
1354             if (outer != null) {
1355                 restoreBlock(outer);
1356                 if (body != null) {
1357                     appendStatement(new BlockStatement(forLine, new Block(
1358                                     outer.getToken(),
1359                                     body.getFinish(),
1360                                     outer.getStatements())));
1361                 }
1362             }
1363         }
1364     }
1365 
1366     /**
1367      * ...IterationStatement :
1368      *           ...
1369      *           while ( Expression ) Statement
1370      *           ...
1371      *
1372      * See 12.6
1373      *
1374      * Parse while statement.
1375      */
1376     private void whileStatement() {
1377         // Capture WHILE token.
1378         final long whileToken = token;
1379         final int whileLine = line;
1380         // WHILE tested in caller.
1381         next();
1382 
1383         final ParserContextLoopNode whileNode = new ParserContextLoopNode();
1384         lc.push(whileNode);
1385 
1386         JoinPredecessorExpression test = null;
1387         Block body = null;
1388 
1389         try {
1390             expect(LPAREN);
1391             test = joinPredecessorExpression();
1392             expect(RPAREN);
1393             body = getStatement();
1394         } finally {
1395             lc.pop(whileNode);
1396         }
1397 
1398         if (body != null) {
1399             appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
1400         }
1401     }
1402 
1403     /**
1404      * ...IterationStatement :
1405      *           ...
1406      *           do Statement while( Expression ) ;
1407      *           ...
1408      *
1409      * See 12.6
1410      *
1411      * Parse DO WHILE statement.
1412      */
1413     private void doStatement() {
1414         // Capture DO token.
1415         final long doToken = token;
1416         int doLine = 0;
1417         // DO tested in the caller.
1418         next();
1419 
1420         final ParserContextLoopNode doWhileNode = new ParserContextLoopNode();
1421         lc.push(doWhileNode);
1422 
1423         Block body = null;
1424         JoinPredecessorExpression test = null;
1425 
1426         try {
1427            // Get DO body.
1428             body = getStatement();
1429 
1430             expect(WHILE);
1431             expect(LPAREN);
1432             doLine = line;
1433             test = joinPredecessorExpression();
1434             expect(RPAREN);
1435 
1436             if (type == SEMICOLON) {
1437                 endOfLine();
1438             }
1439         } finally {
1440             lc.pop(doWhileNode);
1441         }
1442 
1443         appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
1444     }
1445 
1446     /**
1447      * ContinueStatement :
1448      *      continue Identifier? ; // [no LineTerminator here]
1449      *
1450      * See 12.7
1451      *
1452      * Parse CONTINUE statement.
1453      */
1454     private void continueStatement() {
1455         // Capture CONTINUE token.
1456         final int  continueLine  = line;
1457         final long continueToken = token;
1458         // CONTINUE tested in caller.
1459         nextOrEOL();
1460 
1461         ParserContextLabelNode labelNode = null;
1462 
1463         // SEMICOLON or label.
1464         switch (type) {
1465         case RBRACE:
1466         case SEMICOLON:
1467         case EOL:
1468         case EOF:
1469             break;
1470 
1471         default:
1472             final IdentNode ident = getIdent();
1473             labelNode = lc.findLabel(ident.getName());
1474 
1475             if (labelNode == null) {
1476                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1477             }
1478 
1479             break;
1480         }
1481 
1482         final String labelName = labelNode == null ? null : labelNode.getLabelName();
1483         final ParserContextLoopNode targetNode = lc.getContinueTo(labelName);
1484 
1485         if (targetNode == null) {
1486             throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
1487         }
1488 
1489         endOfLine();
1490 
1491         // Construct and add CONTINUE node.
1492         appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
1493     }
1494 
1495     /**
1496      * BreakStatement :
1497      *      break Identifier? ; // [no LineTerminator here]
1498      *
1499      * See 12.8
1500      *
1501      */
1502     private void breakStatement() {
1503         // Capture BREAK token.
1504         final int  breakLine  = line;
1505         final long breakToken = token;
1506         // BREAK tested in caller.
1507         nextOrEOL();
1508 
1509         ParserContextLabelNode labelNode = null;
1510 
1511         // SEMICOLON or label.
1512         switch (type) {
1513         case RBRACE:
1514         case SEMICOLON:
1515         case EOL:
1516         case EOF:
1517             break;
1518 
1519         default:
1520             final IdentNode ident = getIdent();
1521             labelNode = lc.findLabel(ident.getName());
1522 
1523             if (labelNode == null) {
1524                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1525             }
1526 
1527             break;
1528         }
1529 
1530         //either an explicit label - then get its node or just a "break" - get first breakable
1531         //targetNode is what we are breaking out from.
1532         final String labelName = labelNode == null ? null : labelNode.getLabelName();
1533         final ParserContextBreakableNode targetNode = lc.getBreakable(labelName);
1534         if (targetNode == null) {
1535             throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
1536         }
1537 
1538         endOfLine();
1539 
1540         // Construct and add BREAK node.
1541         appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
1542     }
1543 
1544     /**
1545      * ReturnStatement :
1546      *      return Expression? ; // [no LineTerminator here]
1547      *
1548      * See 12.9
1549      *
1550      * Parse RETURN statement.
1551      */
1552     private void returnStatement() {
1553         // check for return outside function
1554         if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT) {
1555             throw error(AbstractParser.message("invalid.return"));
1556         }
1557 
1558         // Capture RETURN token.
1559         final int  returnLine  = line;
1560         final long returnToken = token;
1561         // RETURN tested in caller.
1562         nextOrEOL();
1563 
1564         Expression expression = null;
1565 
1566         // SEMICOLON or expression.
1567         switch (type) {
1568         case RBRACE:
1569         case SEMICOLON:
1570         case EOL:
1571         case EOF:
1572             break;
1573 
1574         default:
1575             expression = expression();
1576             break;
1577         }
1578 
1579         endOfLine();
1580 
1581         // Construct and add RETURN node.
1582         appendStatement(new ReturnNode(returnLine, returnToken, finish, expression));
1583     }
1584 
1585     /**
1586      * YieldStatement :
1587      *      yield Expression? ; // [no LineTerminator here]
1588      *
1589      * JavaScript 1.8
1590      *
1591      * Parse YIELD statement.
1592      */
1593     private void yieldStatement() {
1594         // Capture YIELD token.
1595         final int  yieldLine  = line;
1596         final long yieldToken = token;
1597         // YIELD tested in caller.
1598         nextOrEOL();
1599 
1600         Expression expression = null;
1601 
1602         // SEMICOLON or expression.
1603         switch (type) {
1604         case RBRACE:
1605         case SEMICOLON:
1606         case EOL:
1607         case EOF:
1608             break;
1609 
1610         default:
1611             expression = expression();
1612             break;
1613         }
1614 
1615         endOfLine();
1616 
1617         // Construct and add YIELD node.
1618         appendStatement(new ReturnNode(yieldLine, yieldToken, finish, expression));
1619     }
1620 
1621     /**
1622      * WithStatement :
1623      *      with ( Expression ) Statement
1624      *
1625      * See 12.10
1626      *
1627      * Parse WITH statement.
1628      */
1629     private void withStatement() {
1630         // Capture WITH token.
1631         final int  withLine  = line;
1632         final long withToken = token;
1633         // WITH tested in caller.
1634         next();
1635 
1636         // ECMA 12.10.1 strict mode restrictions
1637         if (isStrictMode) {
1638             throw error(AbstractParser.message("strict.no.with"), withToken);
1639         }
1640 
1641         expect(LPAREN);
1642         final Expression expression = expression();
1643         expect(RPAREN);
1644         final Block body = getStatement();
1645 
1646         appendStatement(new WithNode(withLine, withToken, finish, expression, body));
1647     }
1648 
1649     /**
1650      * SwitchStatement :
1651      *      switch ( Expression ) CaseBlock
1652      *
1653      * CaseBlock :
1654      *      { CaseClauses? }
1655      *      { CaseClauses? DefaultClause CaseClauses }
1656      *
1657      * CaseClauses :
1658      *      CaseClause
1659      *      CaseClauses CaseClause
1660      *
1661      * CaseClause :
1662      *      case Expression : StatementList?
1663      *
1664      * DefaultClause :
1665      *      default : StatementList?
1666      *
1667      * See 12.11
1668      *
1669      * Parse SWITCH statement.
1670      */
1671     private void switchStatement() {
1672         final int  switchLine  = line;
1673         final long switchToken = token;
1674         // SWITCH tested in caller.
1675         next();
1676 
1677         // Create and add switch statement.
1678         final ParserContextSwitchNode switchNode= new ParserContextSwitchNode();
1679         lc.push(switchNode);
1680 
1681         CaseNode defaultCase = null;
1682         // Prepare to accumulate cases.
1683         final List<CaseNode> cases = new ArrayList<>();
1684 
1685         Expression expression = null;
1686 
1687         try {
1688             expect(LPAREN);
1689             expression = expression();
1690             expect(RPAREN);
1691 
1692             expect(LBRACE);
1693 
1694 
1695             while (type != RBRACE) {
1696                 // Prepare for next case.
1697                 Expression caseExpression = null;
1698                 final long caseToken = token;
1699 
1700                 switch (type) {
1701                 case CASE:
1702                     next();
1703                     caseExpression = expression();
1704                     break;
1705 
1706                 case DEFAULT:
1707                     if (defaultCase != null) {
1708                         throw error(AbstractParser.message("duplicate.default.in.switch"));
1709                     }
1710                     next();
1711                     break;
1712 
1713                 default:
1714                     // Force an error.
1715                     expect(CASE);
1716                     break;
1717                 }
1718 
1719                 expect(COLON);
1720 
1721                 // Get CASE body.
1722                 final Block statements = getBlock(false);
1723                 final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
1724 
1725                 if (caseExpression == null) {
1726                     defaultCase = caseNode;
1727                 }
1728 
1729                 cases.add(caseNode);
1730             }
1731 
1732             next();
1733         } finally {
1734             lc.pop(switchNode);
1735         }
1736 
1737         appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase));
1738     }
1739 
1740     /**
1741      * LabelledStatement :
1742      *      Identifier : Statement
1743      *
1744      * See 12.12
1745      *
1746      * Parse label statement.
1747      */
1748     private void labelStatement() {
1749         // Capture label token.
1750         final long labelToken = token;
1751         // Get label ident.
1752         final IdentNode ident = getIdent();
1753 
1754         expect(COLON);
1755 
1756         if (lc.findLabel(ident.getName()) != null) {
1757             throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
1758         }
1759 
1760         final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName());
1761         Block body = null;
1762         try {
1763             lc.push(labelNode);
1764             body = getStatement();
1765         } finally {
1766             assert lc.peek() instanceof ParserContextLabelNode;
1767             lc.pop(labelNode);
1768         }
1769 
1770         appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
1771     }
1772 
1773     /**
1774      * ThrowStatement :
1775      *      throw Expression ; // [no LineTerminator here]
1776      *
1777      * See 12.13
1778      *
1779      * Parse throw statement.
1780      */
1781     private void throwStatement() {
1782         // Capture THROW token.
1783         final int  throwLine  = line;
1784         final long throwToken = token;
1785         // THROW tested in caller.
1786         nextOrEOL();
1787 
1788         Expression expression = null;
1789 
1790         // SEMICOLON or expression.
1791         switch (type) {
1792         case RBRACE:
1793         case SEMICOLON:
1794         case EOL:
1795             break;
1796 
1797         default:
1798             expression = expression();
1799             break;
1800         }
1801 
1802         if (expression == null) {
1803             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
1804         }
1805 
1806         endOfLine();
1807 
1808         appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
1809     }
1810 
1811     /**
1812      * TryStatement :
1813      *      try Block Catch
1814      *      try Block Finally
1815      *      try Block Catch Finally
1816      *
1817      * Catch :
1818      *      catch( Identifier if Expression ) Block
1819      *      catch( Identifier ) Block
1820      *
1821      * Finally :
1822      *      finally Block
1823      *
1824      * See 12.14
1825      *
1826      * Parse TRY statement.
1827      */
1828     private void tryStatement() {
1829         // Capture TRY token.
1830         final int  tryLine  = line;
1831         final long tryToken = token;
1832         // TRY tested in caller.
1833         next();
1834 
1835         // Container block needed to act as target for labeled break statements
1836         final int startLine = line;
1837         final ParserContextBlockNode outer = newBlock();
1838         // Create try.
1839 
1840         try {
1841             final Block       tryBody     = getBlock(true);
1842             final List<Block> catchBlocks = new ArrayList<>();
1843 
1844             while (type == CATCH) {
1845                 final int  catchLine  = line;
1846                 final long catchToken = token;
1847                 next();
1848                 expect(LPAREN);
1849                 final IdentNode exception = getIdent();
1850 
1851                 // ECMA 12.4.1 strict mode restrictions
1852                 verifyStrictIdent(exception, "catch argument");
1853 
1854                 // Nashorn extension: catch clause can have optional
1855                 // condition. So, a single try can have more than one
1856                 // catch clause each with it's own condition.
1857                 final Expression ifExpression;
1858                 if (!env._no_syntax_extensions && type == IF) {
1859                     next();
1860                     // Get the exception condition.
1861                     ifExpression = expression();
1862                 } else {
1863                     ifExpression = null;
1864                 }
1865 
1866                 expect(RPAREN);
1867 
1868                 final ParserContextBlockNode catchBlock = newBlock();
1869                 try {
1870                     // Get CATCH body.
1871                     final Block catchBody = getBlock(true);
1872                     final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
1873                     appendStatement(catchNode);
1874                 } finally {
1875                     restoreBlock(catchBlock);
1876                     catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements()));
1877                 }
1878 
1879                 // If unconditional catch then should to be the end.
1880                 if (ifExpression == null) {
1881                     break;
1882                 }
1883             }
1884 
1885             // Prepare to capture finally statement.
1886             Block finallyStatements = null;
1887 
1888             if (type == FINALLY) {
1889                 next();
1890                 finallyStatements = getBlock(true);
1891             }
1892 
1893             // Need at least one catch or a finally.
1894             if (catchBlocks.isEmpty() && finallyStatements == null) {
1895                 throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
1896             }
1897 
1898             final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
1899             // Add try.
1900             assert lc.peek() == outer;
1901             appendStatement(tryNode);
1902         } finally {
1903             restoreBlock(outer);
1904         }
1905 
1906         appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements())));
1907     }
1908 
1909     /**
1910      * DebuggerStatement :
1911      *      debugger ;
1912      *
1913      * See 12.15
1914      *
1915      * Parse debugger statement.
1916      */
1917     private void  debuggerStatement() {
1918         // Capture DEBUGGER token.
1919         final int  debuggerLine  = line;
1920         final long debuggerToken = token;
1921         // DEBUGGER tested in caller.
1922         next();
1923         endOfLine();
1924         appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish));
1925     }
1926 
1927     /**
1928      * PrimaryExpression :
1929      *      this
1930      *      Identifier
1931      *      Literal
1932      *      ArrayLiteral
1933      *      ObjectLiteral
1934      *      RegularExpressionLiteral
1935      *      TemplateLiteral
1936      *      ( Expression )
1937      *
1938      * Parse primary expression.
1939      * @return Expression node.
1940      */
1941     @SuppressWarnings("fallthrough")
1942     private Expression primaryExpression() {
1943         // Capture first token.
1944         final int  primaryLine  = line;
1945         final long primaryToken = token;
1946 
1947         switch (type) {
1948         case THIS:
1949             final String name = type.getName();
1950             next();
1951             lc.getCurrentFunction().setFlag(FunctionNode.USES_THIS);
1952             return new IdentNode(primaryToken, finish, name);
1953         case IDENT:
1954             final IdentNode ident = getIdent();
1955             if (ident == null) {
1956                 break;
1957             }
1958             detectSpecialProperty(ident);
1959             return ident;
1960         case OCTAL_LEGACY:
1961             if (isStrictMode) {
1962                throw error(AbstractParser.message("strict.no.octal"), token);
1963             }
1964         case STRING:
1965         case ESCSTRING:
1966         case DECIMAL:
1967         case HEXADECIMAL:
1968         case OCTAL:
1969         case BINARY_NUMBER:
1970         case FLOATING:
1971         case REGEX:
1972         case XML:
1973             return getLiteral();
1974         case EXECSTRING:
1975             return execString(primaryLine, primaryToken);
1976         case FALSE:
1977             next();
1978             return LiteralNode.newInstance(primaryToken, finish, false);
1979         case TRUE:
1980             next();
1981             return LiteralNode.newInstance(primaryToken, finish, true);
1982         case NULL:
1983             next();
1984             return LiteralNode.newInstance(primaryToken, finish);
1985         case LBRACKET:
1986             return arrayLiteral();
1987         case LBRACE:
1988             return objectLiteral();
1989         case LPAREN:
1990             next();
1991 
1992             final Expression expression = expression();
1993 
1994             expect(RPAREN);
1995 
1996             return expression;
1997         case TEMPLATE:
1998         case TEMPLATE_HEAD:
1999             return templateLiteral();
2000 
2001         default:
2002             // In this context some operator tokens mark the start of a literal.
2003             if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
2004                 next();
2005                 return getLiteral();
2006             }
2007             if (isNonStrictModeIdent()) {
2008                 return getIdent();
2009             }
2010             break;
2011         }
2012 
2013         return null;
2014     }
2015 
2016     /**
2017      * Convert execString to a call to $EXEC.
2018      *
2019      * @param primaryToken Original string token.
2020      * @return callNode to $EXEC.
2021      */
2022     CallNode execString(final int primaryLine, final long primaryToken) {
2023         // Synthesize an ident to call $EXEC.
2024         final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
2025         // Skip over EXECSTRING.
2026         next();
2027         // Set up argument list for call.
2028         // Skip beginning of edit string expression.
2029         expect(LBRACE);
2030         // Add the following expression to arguments.
2031         final List<Expression> arguments = Collections.singletonList(expression());
2032         // Skip ending of edit string expression.
2033         expect(RBRACE);
2034 
2035         return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
2036     }
2037 
2038     /**
2039      * ArrayLiteral :
2040      *      [ Elision? ]
2041      *      [ ElementList ]
2042      *      [ ElementList , Elision? ]
2043      *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
2044      *
2045      * ElementList : Elision? AssignmentExpression
2046      *      ElementList , Elision? AssignmentExpression
2047      *
2048      * Elision :
2049      *      ,
2050      *      Elision ,
2051      *
2052      * See 12.1.4
2053      * JavaScript 1.8
2054      *
2055      * Parse array literal.
2056      * @return Expression node.
2057      */
2058     private LiteralNode<Expression[]> arrayLiteral() {
2059         // Capture LBRACKET token.
2060         final long arrayToken = token;
2061         // LBRACKET tested in caller.
2062         next();
2063 
2064         // Prepare to accumulate elements.
2065         final List<Expression> elements = new ArrayList<>();
2066         // Track elisions.
2067         boolean elision = true;
2068 loop:
2069         while (true) {
2070             switch (type) {
2071             case RBRACKET:
2072                 next();
2073 
2074                 break loop;
2075 
2076             case COMMARIGHT:
2077                 next();
2078 
2079                 // If no prior expression
2080                 if (elision) {
2081                     elements.add(null);
2082                 }
2083 
2084                 elision = true;
2085 
2086                 break;
2087 
2088             default:
2089                 if (!elision) {
2090                     throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2091                 }
2092                 // Add expression element.
2093                 final Expression expression = assignmentExpression(false);
2094 
2095                 if (expression != null) {
2096                     elements.add(expression);
2097                 } else {
2098                     expect(RBRACKET);
2099                 }
2100 
2101                 elision = false;
2102                 break;
2103             }
2104         }
2105 
2106         return LiteralNode.newInstance(arrayToken, finish, elements);
2107     }
2108 
2109     /**
2110      * ObjectLiteral :
2111      *      { }
2112      *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2113      *
2114      * PropertyNameAndValueList :
2115      *      PropertyAssignment
2116      *      PropertyNameAndValueList , PropertyAssignment
2117      *
2118      * See 11.1.5
2119      *
2120      * Parse an object literal.
2121      * @return Expression node.
2122      */
2123     private ObjectNode objectLiteral() {
2124         // Capture LBRACE token.
2125         final long objectToken = token;
2126         // LBRACE tested in caller.
2127         next();
2128 
2129         // Object context.
2130         // Prepare to accumulate elements.
2131         final List<PropertyNode> elements = new ArrayList<>();
2132         final Map<String, Integer> map = new HashMap<>();
2133 
2134         // Create a block for the object literal.
2135         boolean commaSeen = true;
2136 loop:
2137         while (true) {
2138             switch (type) {
2139                 case RBRACE:
2140                     next();
2141                     break loop;
2142 
2143                 case COMMARIGHT:
2144                     if (commaSeen) {
2145                         throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2146                     }
2147                     next();
2148                     commaSeen = true;
2149                     break;
2150 
2151                 default:
2152                     if (!commaSeen) {
2153                         throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2154                     }
2155 
2156                     commaSeen = false;
2157                     // Get and add the next property.
2158                     final PropertyNode property = propertyAssignment();
2159                     final String key = property.getKeyName();
2160                     final Integer existing = map.get(key);
2161 
2162                     if (existing == null) {
2163                         map.put(key, elements.size());
2164                         elements.add(property);
2165                         break;
2166                     }
2167 
2168                     final PropertyNode existingProperty = elements.get(existing);
2169 
2170                     // ECMA section 11.1.5 Object Initialiser
2171                     // point # 4 on property assignment production
2172                     final Expression   value  = property.getValue();
2173                     final FunctionNode getter = property.getGetter();
2174                     final FunctionNode setter = property.getSetter();
2175 
2176                     final Expression   prevValue  = existingProperty.getValue();
2177                     final FunctionNode prevGetter = existingProperty.getGetter();
2178                     final FunctionNode prevSetter = existingProperty.getSetter();
2179 
2180                     // ECMA 11.1.5 strict mode restrictions
2181                     if (isStrictMode && value != null && prevValue != null) {
2182                         throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2183                     }
2184 
2185                     final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
2186                     final boolean isAccessor     = getter != null     || setter != null;
2187 
2188                     // data property redefined as accessor property
2189                     if (prevValue != null && isAccessor) {
2190                         throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2191                     }
2192 
2193                     // accessor property redefined as data
2194                     if (isPrevAccessor && value != null) {
2195                         throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2196                     }
2197 
2198                     if (isAccessor && isPrevAccessor) {
2199                         if (getter != null && prevGetter != null ||
2200                                 setter != null && prevSetter != null) {
2201                             throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2202                         }
2203                     }
2204 
2205                     if (value != null) {
2206                         elements.add(property);
2207                     } else if (getter != null) {
2208                         elements.set(existing, existingProperty.setGetter(getter));
2209                     } else if (setter != null) {
2210                         elements.set(existing, existingProperty.setSetter(setter));
2211                     }
2212                     break;
2213             }
2214         }
2215 
2216         return new ObjectNode(objectToken, finish, elements);
2217     }
2218 
2219     /**
2220      * PropertyName :
2221      *      IdentifierName
2222      *      StringLiteral
2223      *      NumericLiteral
2224      *
2225      * See 11.1.5
2226      *
2227      * @return PropertyName node
2228      */
2229     @SuppressWarnings("fallthrough")
2230     private PropertyKey propertyName() {
2231         switch (type) {
2232         case IDENT:
2233             return getIdent().setIsPropertyName();
2234         case OCTAL_LEGACY:
2235             if (isStrictMode) {
2236                 throw error(AbstractParser.message("strict.no.octal"), token);
2237             }
2238         case STRING:
2239         case ESCSTRING:
2240         case DECIMAL:
2241         case HEXADECIMAL:
2242         case OCTAL:
2243         case BINARY_NUMBER:
2244         case FLOATING:
2245             return getLiteral();
2246         default:
2247             return getIdentifierName().setIsPropertyName();
2248         }
2249     }
2250 
2251     /**
2252      * PropertyAssignment :
2253      *      PropertyName : AssignmentExpression
2254      *      get PropertyName ( ) { FunctionBody }
2255      *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
2256      *
2257      * PropertySetParameterList :
2258      *      Identifier
2259      *
2260      * PropertyName :
2261      *      IdentifierName
2262      *      StringLiteral
2263      *      NumericLiteral
2264      *
2265      * See 11.1.5
2266      *
2267      * Parse an object literal property.
2268      * @return Property or reference node.
2269      */
2270     private PropertyNode propertyAssignment() {
2271         // Capture firstToken.
2272         final long propertyToken = token;
2273         final int  functionLine  = line;
2274 
2275         PropertyKey propertyName;
2276 
2277         if (type == IDENT) {
2278             // Get IDENT.
2279             final String ident = (String)expectValue(IDENT);
2280 
2281             if (type != COLON) {
2282                 final long getSetToken = propertyToken;
2283 
2284                 switch (ident) {
2285                 case "get":
2286                     final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
2287                     return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null);
2288 
2289                 case "set":
2290                     final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
2291                     return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode);
2292                 default:
2293                     break;
2294                 }
2295             }
2296 
2297             propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
2298         } else {
2299             propertyName = propertyName();
2300         }
2301 
2302         expect(COLON);
2303 
2304         defaultNames.push(propertyName);
2305         try {
2306             return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
2307         } finally {
2308             defaultNames.pop();
2309         }
2310     }
2311 
2312     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
2313         final PropertyKey getIdent = propertyName();
2314         final String getterName = getIdent.getPropertyName();
2315         final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
2316         expect(LPAREN);
2317         expect(RPAREN);
2318 
2319         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
2320         lc.push(functionNode);
2321 
2322         Block functionBody;
2323 
2324 
2325         try {
2326             functionBody = functionBody(functionNode);
2327         } finally {
2328             lc.pop(functionNode);
2329         }
2330 
2331         final FunctionNode  function = createFunctionNode(
2332                 functionNode,
2333                 getSetToken,
2334                 getNameNode,
2335                 Collections.<IdentNode>emptyList(),
2336                 FunctionNode.Kind.GETTER,
2337                 functionLine,
2338                 functionBody);
2339 
2340         return new PropertyFunction(getIdent, function);
2341     }
2342 
2343     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
2344         final PropertyKey setIdent = propertyName();
2345         final String setterName = setIdent.getPropertyName();
2346         final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
2347         expect(LPAREN);
2348         // be sloppy and allow missing setter parameter even though
2349         // spec does not permit it!
2350         final IdentNode argIdent;
2351         if (type == IDENT || isNonStrictModeIdent()) {
2352             argIdent = getIdent();
2353             verifyStrictIdent(argIdent, "setter argument");
2354         } else {
2355             argIdent = null;
2356         }
2357         expect(RPAREN);
2358         final List<IdentNode> parameters = new ArrayList<>();
2359         if (argIdent != null) {
2360             parameters.add(argIdent);
2361         }
2362 
2363 
2364         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
2365         lc.push(functionNode);
2366 
2367         Block functionBody;
2368         try {
2369             functionBody = functionBody(functionNode);
2370         } finally {
2371             lc.pop(functionNode);
2372         }
2373 
2374 
2375         final FunctionNode  function = createFunctionNode(
2376                 functionNode,
2377                 getSetToken,
2378                 setNameNode,
2379                 parameters,
2380                 FunctionNode.Kind.SETTER,
2381                 functionLine,
2382                 functionBody);
2383 
2384         return new PropertyFunction(setIdent, function);
2385     }
2386 
2387     private static class PropertyFunction {
2388         final PropertyKey ident;
2389         final FunctionNode functionNode;
2390 
2391         PropertyFunction(final PropertyKey ident, final FunctionNode function) {
2392             this.ident = ident;
2393             this.functionNode = function;
2394         }
2395     }
2396 
2397     /**
2398      * Parse left hand side expression.
2399      *
2400      * LeftHandSideExpression :
2401      *      NewExpression
2402      *      CallExpression
2403      *
2404      * CallExpression :
2405      *      MemberExpression Arguments
2406      *      CallExpression Arguments
2407      *      CallExpression [ Expression ]
2408      *      CallExpression . IdentifierName
2409      *      CallExpression TemplateLiteral
2410      *
2411      * @return Expression node.
2412      */
2413     private Expression leftHandSideExpression() {
2414         int  callLine  = line;
2415         long callToken = token;
2416 
2417         Expression lhs = memberExpression();
2418 
2419         if (type == LPAREN) {
2420             final List<Expression> arguments = optimizeList(argumentList());
2421 
2422             // Catch special functions.
2423             if (lhs instanceof IdentNode) {
2424                 detectSpecialFunction((IdentNode)lhs);
2425             }
2426 
2427             lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2428         }
2429 
2430 loop:
2431         while (true) {
2432             // Capture token.
2433             callLine  = line;
2434             callToken = token;
2435 
2436             switch (type) {
2437             case LPAREN: {
2438                 // Get NEW or FUNCTION arguments.
2439                 final List<Expression> arguments = optimizeList(argumentList());
2440 
2441                 // Create call node.
2442                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2443 
2444                 break;
2445             }
2446             case LBRACKET: {
2447                 next();
2448 
2449                 // Get array index.
2450                 final Expression rhs = expression();
2451 
2452                 expect(RBRACKET);
2453 
2454                 // Create indexing node.
2455                 lhs = new IndexNode(callToken, finish, lhs, rhs);
2456 
2457                 break;
2458             }
2459             case PERIOD: {
2460                 next();
2461 
2462                 final IdentNode property = getIdentifierName();
2463 
2464                 // Create property access node.
2465                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
2466 
2467                 break;
2468             }
2469             case TEMPLATE:
2470             case TEMPLATE_HEAD: {
2471                 // tagged template literal
2472                 final List<Expression> arguments = templateLiteralArgumentList();
2473 
2474                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2475 
2476                 break;
2477             }
2478             default:
2479                 break loop;
2480             }
2481         }
2482 
2483         return lhs;
2484     }
2485 
2486     /**
2487      * NewExpression :
2488      *      MemberExpression
2489      *      new NewExpression
2490      *
2491      * See 11.2
2492      *
2493      * Parse new expression.
2494      * @return Expression node.
2495      */
2496     private Expression newExpression() {
2497         final long newToken = token;
2498         // NEW is tested in caller.
2499         next();
2500 
2501         // Get function base.
2502         final int  callLine    = line;
2503         final Expression constructor = memberExpression();
2504         if (constructor == null) {
2505             return null;
2506         }
2507         // Get arguments.
2508         ArrayList<Expression> arguments;
2509 
2510         // Allow for missing arguments.
2511         if (type == LPAREN) {
2512             arguments = argumentList();
2513         } else {
2514             arguments = new ArrayList<>();
2515         }
2516 
2517         // Nashorn extension: This is to support the following interface implementation
2518         // syntax:
2519         //
2520         //     var r = new java.lang.Runnable() {
2521         //         run: function() { println("run"); }
2522         //     };
2523         //
2524         // The object literal following the "new Constructor()" expression
2525         // is passed as an additional (last) argument to the constructor.
2526         if (!env._no_syntax_extensions && type == LBRACE) {
2527             arguments.add(objectLiteral());
2528         }
2529 
2530         final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
2531 
2532         return new UnaryNode(newToken, callNode);
2533     }
2534 
2535     /**
2536      * Parse member expression.
2537      *
2538      * MemberExpression :
2539      *      PrimaryExpression
2540      *      FunctionExpression
2541      *      MemberExpression [ Expression ]
2542      *      MemberExpression . IdentifierName
2543      *      MemberExpression TemplateLiteral
2544      *      new MemberExpression Arguments
2545      *
2546      * @return Expression node.
2547      */
2548     private Expression memberExpression() {
2549         // Prepare to build operation.
2550         Expression lhs;
2551 
2552         switch (type) {
2553         case NEW:
2554             // Get new expression.
2555             lhs = newExpression();
2556             break;
2557 
2558         case FUNCTION:
2559             // Get function expression.
2560             lhs = functionExpression(false, false);
2561             break;
2562 
2563         default:
2564             // Get primary expression.
2565             lhs = primaryExpression();
2566             break;
2567         }
2568 
2569 loop:
2570         while (true) {
2571             // Capture token.
2572             final long callToken = token;
2573 
2574             switch (type) {
2575             case LBRACKET: {
2576                 next();
2577 
2578                 // Get array index.
2579                 final Expression index = expression();
2580 
2581                 expect(RBRACKET);
2582 
2583                 // Create indexing node.
2584                 lhs = new IndexNode(callToken, finish, lhs, index);
2585 
2586                 break;
2587             }
2588             case PERIOD: {
2589                 if (lhs == null) {
2590                     throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2591                 }
2592 
2593                 next();
2594 
2595                 final IdentNode property = getIdentifierName();
2596 
2597                 // Create property access node.
2598                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
2599 
2600                 break;
2601             }
2602             case TEMPLATE:
2603             case TEMPLATE_HEAD: {
2604                 // tagged template literal
2605                 final int callLine = line;
2606                 final List<Expression> arguments = templateLiteralArgumentList();
2607 
2608                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2609 
2610                 break;
2611             }
2612             default:
2613                 break loop;
2614             }
2615         }
2616 
2617         return lhs;
2618     }
2619 
2620     /**
2621      * Arguments :
2622      *      ( )
2623      *      ( ArgumentList )
2624      *
2625      * ArgumentList :
2626      *      AssignmentExpression
2627      *      ArgumentList , AssignmentExpression
2628      *
2629      * See 11.2
2630      *
2631      * Parse function call arguments.
2632      * @return Argument list.
2633      */
2634     private ArrayList<Expression> argumentList() {
2635         // Prepare to accumulate list of arguments.
2636         final ArrayList<Expression> nodeList = new ArrayList<>();
2637         // LPAREN tested in caller.
2638         next();
2639 
2640         // Track commas.
2641         boolean first = true;
2642 
2643         while (type != RPAREN) {
2644             // Comma prior to every argument except the first.
2645             if (!first) {
2646                 expect(COMMARIGHT);
2647             } else {
2648                 first = false;
2649             }
2650 
2651             // Get argument expression.
2652             nodeList.add(assignmentExpression(false));
2653         }
2654 
2655         expect(RPAREN);
2656         return nodeList;
2657     }
2658 
2659     private static <T> List<T> optimizeList(final ArrayList<T> list) {
2660         switch(list.size()) {
2661             case 0: {
2662                 return Collections.emptyList();
2663             }
2664             case 1: {
2665                 return Collections.singletonList(list.get(0));
2666             }
2667             default: {
2668                 list.trimToSize();
2669                 return list;
2670             }
2671         }
2672     }
2673 
2674     /**
2675      * FunctionDeclaration :
2676      *      function Identifier ( FormalParameterList? ) { FunctionBody }
2677      *
2678      * FunctionExpression :
2679      *      function Identifier? ( FormalParameterList? ) { FunctionBody }
2680      *
2681      * See 13
2682      *
2683      * Parse function declaration.
2684      * @param isStatement True if for is a statement.
2685      *
2686      * @return Expression node.
2687      */
2688     private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
2689         final long functionToken = token;
2690         final int  functionLine  = line;
2691         // FUNCTION is tested in caller.
2692         next();
2693 
2694         IdentNode name = null;
2695 
2696         if (type == IDENT || isNonStrictModeIdent()) {
2697             name = getIdent();
2698             verifyStrictIdent(name, "function name");
2699         } else if (isStatement) {
2700             // Nashorn extension: anonymous function statements.
2701             // Do not allow anonymous function statement if extensions
2702             // are now allowed. But if we are reparsing then anon function
2703             // statement is possible - because it was used as function
2704             // expression in surrounding code.
2705             if (env._no_syntax_extensions && reparsedFunction == null) {
2706                 expect(IDENT);
2707             }
2708         }
2709 
2710         // name is null, generate anonymous name
2711         boolean isAnonymous = false;
2712         if (name == null) {
2713             final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
2714             name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
2715             isAnonymous = true;
2716         }
2717 
2718         expect(LPAREN);
2719         final List<IdentNode> parameters = formalParameterList();
2720         expect(RPAREN);
2721 
2722         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters);
2723         lc.push(functionNode);
2724         Block functionBody = null;
2725         // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
2726         // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
2727         hideDefaultName();
2728         try{
2729             functionBody = functionBody(functionNode);
2730         } finally {
2731             defaultNames.pop();
2732             lc.pop(functionNode);
2733         }
2734 
2735         if (isStatement) {
2736             if (topLevel || useBlockScope()) {
2737                 functionNode.setFlag(FunctionNode.IS_DECLARED);
2738             } else if (isStrictMode) {
2739                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
2740             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
2741                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
2742             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
2743                 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
2744             }
2745             if (isArguments(name)) {
2746                lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
2747             }
2748         }
2749 
2750         if (isAnonymous) {
2751             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
2752         }
2753 
2754         final int arity = parameters.size();
2755 
2756         final boolean strict = functionNode.isStrict();
2757         if (arity > 1) {
2758             final HashSet<String> parametersSet = new HashSet<>(arity);
2759 
2760             for (int i = arity - 1; i >= 0; i--) {
2761                 final IdentNode parameter = parameters.get(i);
2762                 String parameterName = parameter.getName();
2763 
2764                 if (isArguments(parameterName)) {
2765                     functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2766                 }
2767 
2768                 if (parametersSet.contains(parameterName)) {
2769                     // redefinition of parameter name
2770                     if (strict) {
2771                         throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2772                     }
2773                     // rename in non-strict mode
2774                     parameterName = functionNode.uniqueName(parameterName);
2775                     final long parameterToken = parameter.getToken();
2776                     parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2777                 }
2778 
2779                 parametersSet.add(parameterName);
2780             }
2781         } else if (arity == 1) {
2782             if (isArguments(parameters.get(0))) {
2783                 functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2784             }
2785         }
2786 
2787         final FunctionNode function = createFunctionNode(
2788                 functionNode,
2789                 functionToken,
2790                 name,
2791                 parameters,
2792                 FunctionNode.Kind.NORMAL,
2793                 functionLine,
2794                 functionBody);
2795 
2796         if (isStatement) {
2797             if (isAnonymous) {
2798                 appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function));
2799                 return function;
2800             }
2801 
2802             // mark ES6 block functions as lexically scoped
2803             final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
2804             final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
2805             if (topLevel) {
2806                 functionDeclarations.add(varNode);
2807             } else if (useBlockScope()) {
2808                 prependStatement(varNode); // Hoist to beginning of current block
2809             } else {
2810                 appendStatement(varNode);
2811             }
2812         }
2813 
2814         return function;
2815     }
2816 
2817     private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
2818         final String defaultFunctionName = getDefaultFunctionName();
2819         if (isValidIdentifier(defaultFunctionName)) {
2820             if (isStatement) {
2821                 // The name will be used as the LHS of a symbol assignment. We add the anonymous function
2822                 // prefix to ensure that it can't clash with another variable.
2823                 return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
2824             }
2825             return defaultFunctionName;
2826         }
2827         return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2828     }
2829 
2830     private static boolean isValidIdentifier(final String name) {
2831         if(name == null || name.isEmpty()) {
2832             return false;
2833         }
2834         if(!Character.isJavaIdentifierStart(name.charAt(0))) {
2835             return false;
2836         }
2837         for(int i = 1; i < name.length(); ++i) {
2838             if(!Character.isJavaIdentifierPart(name.charAt(i))) {
2839                 return false;
2840             }
2841         }
2842         return true;
2843     }
2844 
2845     private String getDefaultFunctionName() {
2846         if(!defaultNames.isEmpty()) {
2847             final Object nameExpr = defaultNames.peek();
2848             if(nameExpr instanceof PropertyKey) {
2849                 markDefaultNameUsed();
2850                 return ((PropertyKey)nameExpr).getPropertyName();
2851             } else if(nameExpr instanceof AccessNode) {
2852                 markDefaultNameUsed();
2853                 return ((AccessNode)nameExpr).getProperty();
2854             }
2855         }
2856         return null;
2857     }
2858 
2859     private void markDefaultNameUsed() {
2860         defaultNames.pop();
2861         hideDefaultName();
2862     }
2863 
2864     private void hideDefaultName() {
2865         // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
2866         // from. Can't be null
2867         defaultNames.push("");
2868     }
2869 
2870     /**
2871      * FormalParameterList :
2872      *      Identifier
2873      *      FormalParameterList , Identifier
2874      *
2875      * See 13
2876      *
2877      * Parse function parameter list.
2878      * @return List of parameter nodes.
2879      */
2880     private List<IdentNode> formalParameterList() {
2881         return formalParameterList(RPAREN);
2882     }
2883 
2884     /**
2885      * Same as the other method of the same name - except that the end
2886      * token type expected is passed as argument to this method.
2887      *
2888      * FormalParameterList :
2889      *      Identifier
2890      *      FormalParameterList , Identifier
2891      *
2892      * See 13
2893      *
2894      * Parse function parameter list.
2895      * @return List of parameter nodes.
2896      */
2897     private List<IdentNode> formalParameterList(final TokenType endType) {
2898         // Prepare to gather parameters.
2899         final ArrayList<IdentNode> parameters = new ArrayList<>();
2900         // Track commas.
2901         boolean first = true;
2902 
2903         while (type != endType) {
2904             // Comma prior to every argument except the first.
2905             if (!first) {
2906                 expect(COMMARIGHT);
2907             } else {
2908                 first = false;
2909             }
2910 
2911             // Get and add parameter.
2912             final IdentNode ident = getIdent();
2913 
2914             // ECMA 13.1 strict mode restrictions
2915             verifyStrictIdent(ident, "function parameter");
2916 
2917             parameters.add(ident);
2918         }
2919 
2920         parameters.trimToSize();
2921         return parameters;
2922     }
2923 
2924     /**
2925      * FunctionBody :
2926      *      SourceElements?
2927      *
2928      * See 13
2929      *
2930      * Parse function body.
2931      * @return function node (body.)
2932      */
2933     private Block functionBody(final ParserContextFunctionNode functionNode) {
2934         long lastToken = 0L;
2935         ParserContextBlockNode body = null;
2936         final long bodyToken = token;
2937         Block functionBody;
2938         int bodyFinish = 0;
2939 
2940         final boolean parseBody;
2941         Object endParserState = null;
2942         try {
2943             // Create a new function block.
2944             body = newBlock();
2945             if (env._debug_scopes) {
2946                 // debug scope options forces everything to be in scope
2947                 markEval(lc);
2948             }
2949             assert functionNode != null;
2950             final int functionId = functionNode.getId();
2951             parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
2952             // Nashorn extension: expression closures
2953             if (!env._no_syntax_extensions && type != LBRACE) {
2954                 /*
2955                  * Example:
2956                  *
2957                  * function square(x) x * x;
2958                  * print(square(3));
2959                  */
2960 
2961                 // just expression as function body
2962                 final Expression expr = assignmentExpression(true);
2963                 lastToken = previousToken;
2964                 functionNode.setLastToken(previousToken);
2965                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
2966                 // EOL uses length field to store the line number
2967                 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
2968                 // Only create the return node if we aren't skipping nested functions. Note that we aren't
2969                 // skipping parsing of these extended functions; they're considered to be small anyway. Also,
2970                 // they don't end with a single well known token, so it'd be very hard to get correctly (see
2971                 // the note below for reasoning on skipping happening before instead of after RBRACE for
2972                 // details).
2973                 if (parseBody) {
2974                     final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
2975                     appendStatement(returnNode);
2976                 }
2977             } else {
2978                 expectDontAdvance(LBRACE);
2979                 if (parseBody || !skipFunctionBody(functionNode)) {
2980                     next();
2981                     // Gather the function elements.
2982                     final List<Statement> prevFunctionDecls = functionDeclarations;
2983                     functionDeclarations = new ArrayList<>();
2984                     try {
2985                         sourceElements(false);
2986                         addFunctionDeclarations(functionNode);
2987                     } finally {
2988                         functionDeclarations = prevFunctionDecls;
2989                     }
2990 
2991                     lastToken = token;
2992                     if (parseBody) {
2993                         // Since the lexer can read ahead and lexify some number of tokens in advance and have
2994                         // them buffered in the TokenStream, we need to produce a lexer state as it was just
2995                         // before it lexified RBRACE, and not whatever is its current (quite possibly well read
2996                         // ahead) state.
2997                         endParserState = new ParserState(Token.descPosition(token), line, linePosition);
2998 
2999                         // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
3000                         // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
3001                         // state after it. The reason is that RBRACE is a well-known token that we can expect and
3002                         // will never involve us getting into a weird lexer state, and as such is a great reparse
3003                         // point. Typical example of a weird lexer state after RBRACE would be:
3004                         //     function this_is_skipped() { ... } "use strict";
3005                         // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
3006                         // of compensating for the possibility of a string literal (or similar) after RBRACE,
3007                         // we'll rather just restart parsing from this well-known, friendly token instead.
3008                     }
3009                 }
3010                 bodyFinish = finish;
3011                 functionNode.setLastToken(token);
3012                 expect(RBRACE);
3013             }
3014         } finally {
3015             restoreBlock(body);
3016         }
3017 
3018         // NOTE: we can only do alterations to the function node after restoreFunctionNode.
3019 
3020         if (parseBody) {
3021             functionNode.setEndParserState(endParserState);
3022         } else if (!body.getStatements().isEmpty()){
3023             // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
3024             // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
3025             // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
3026             // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
3027             // nested bodies early if we were supposed to skip 'em.
3028             body.setStatements(Collections.<Statement>emptyList());
3029         }
3030 
3031         if (reparsedFunction != null) {
3032             // We restore the flags stored in the function's ScriptFunctionData that we got when we first
3033             // eagerly parsed the code. We're doing it because some flags would be set based on the
3034             // content of the function, or even content of its nested functions, most of which are normally
3035             // skipped during an on-demand compilation.
3036             final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
3037             if (data != null) {
3038                 // Data can be null if when we originally parsed the file, we removed the function declaration
3039                 // as it was dead code.
3040                 functionNode.setFlag(data.getFunctionFlags());
3041                 // This compensates for missing markEval() in case the function contains an inner function
3042                 // that contains eval(), that now we didn't discover since we skipped the inner function.
3043                 if (functionNode.hasNestedEval()) {
3044                     assert functionNode.hasScopeBlock();
3045                     body.setFlag(Block.NEEDS_SCOPE);
3046                 }
3047             }
3048         }
3049         functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements());
3050         return functionBody;
3051     }
3052 
3053     private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
3054         if (reparsedFunction == null) {
3055             // Not reparsing, so don't skip any function body.
3056             return false;
3057         }
3058         // Skip to the RBRACE of this function, and continue parsing from there.
3059         final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
3060         if (data == null) {
3061             // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
3062             // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
3063             // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
3064             return false;
3065         }
3066         final ParserState parserState = (ParserState)data.getEndParserState();
3067         assert parserState != null;
3068 
3069         if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) {
3070             // RBRACE is already in the token stream, so fast forward to it
3071             for (; k < stream.last(); k++) {
3072                 final long nextToken = stream.get(k + 1);
3073                 if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) {
3074                     token = stream.get(k);
3075                     type = Token.descType(token);
3076                     next();
3077                     assert type == RBRACE && start == parserState.position;
3078                     return true;
3079                 }
3080             }
3081         }
3082 
3083         stream.reset();
3084         lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
3085         line = parserState.line;
3086         linePosition = parserState.linePosition;
3087         // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
3088         // the RBRACE.
3089         type = SEMICOLON;
3090         k = -1;
3091         next();
3092 
3093         return true;
3094     }
3095 
3096     /**
3097      * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
3098      * for resuming parsing after skipping a function body.
3099      */
3100     private static class ParserState implements Serializable {
3101         private final int position;
3102         private final int line;
3103         private final int linePosition;
3104 
3105         private static final long serialVersionUID = -2382565130754093694L;
3106 
3107         ParserState(final int position, final int line, final int linePosition) {
3108             this.position = position;
3109             this.line = line;
3110             this.linePosition = linePosition;
3111         }
3112 
3113         Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
3114             final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
3115             newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
3116             return newLexer;
3117         }
3118     }
3119 
3120     private void printAST(final FunctionNode functionNode) {
3121         if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
3122             env.getErr().println(new ASTWriter(functionNode));
3123         }
3124 
3125         if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
3126             env.getErr().println(new PrintVisitor(functionNode, true, false));
3127         }
3128     }
3129 
3130     private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
3131         VarNode lastDecl = null;
3132         for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
3133             Statement decl = functionDeclarations.get(i);
3134             if (lastDecl == null && decl instanceof VarNode) {
3135                 decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
3136                 functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
3137             }
3138             prependStatement(decl);
3139         }
3140     }
3141 
3142     private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
3143         if (earlyError) {
3144             throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
3145         }
3146         final ArrayList<Expression> args = new ArrayList<>();
3147         args.add(lhs);
3148         if (rhs == null) {
3149             args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
3150         } else {
3151             args.add(rhs);
3152         }
3153         args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
3154         return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
3155     }
3156 
3157     /**
3158      * PostfixExpression :
3159      *      LeftHandSideExpression
3160      *      LeftHandSideExpression ++ // [no LineTerminator here]
3161      *      LeftHandSideExpression -- // [no LineTerminator here]
3162      *
3163      * See 11.3
3164      *
3165      * UnaryExpression :
3166      *      PostfixExpression
3167      *      delete UnaryExpression
3168      *      void UnaryExpression
3169      *      typeof UnaryExpression
3170      *      ++ UnaryExpression
3171      *      -- UnaryExpression
3172      *      + UnaryExpression
3173      *      - UnaryExpression
3174      *      ~ UnaryExpression
3175      *      ! UnaryExpression
3176      *
3177      * See 11.4
3178      *
3179      * Parse unary expression.
3180      * @return Expression node.
3181      */
3182     private Expression unaryExpression() {
3183         final int  unaryLine  = line;
3184         final long unaryToken = token;
3185 
3186         switch (type) {
3187         case DELETE: {
3188             next();
3189             final Expression expr = unaryExpression();
3190             if (expr instanceof BaseNode || expr instanceof IdentNode) {
3191                 return new UnaryNode(unaryToken, expr);
3192             }
3193             appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
3194             return LiteralNode.newInstance(unaryToken, finish, true);
3195         }
3196         case VOID:
3197         case TYPEOF:
3198         case ADD:
3199         case SUB:
3200         case BIT_NOT:
3201         case NOT:
3202             next();
3203             final Expression expr = unaryExpression();
3204             return new UnaryNode(unaryToken, expr);
3205 
3206         case INCPREFIX:
3207         case DECPREFIX:
3208             final TokenType opType = type;
3209             next();
3210 
3211             final Expression lhs = leftHandSideExpression();
3212             // ++, -- without operand..
3213             if (lhs == null) {
3214                 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3215             }
3216 
3217             if (!(lhs instanceof AccessNode ||
3218                   lhs instanceof IndexNode ||
3219                   lhs instanceof IdentNode)) {
3220                 return referenceError(lhs, null, env._early_lvalue_error);
3221             }
3222 
3223             if (lhs instanceof IdentNode) {
3224                 if (!checkIdentLValue((IdentNode)lhs)) {
3225                     return referenceError(lhs, null, false);
3226                 }
3227                 verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3228             }
3229 
3230             return incDecExpression(unaryToken, opType, lhs, false);
3231 
3232         default:
3233             break;
3234         }
3235 
3236         Expression expression = leftHandSideExpression();
3237 
3238         if (last != EOL) {
3239             switch (type) {
3240             case INCPREFIX:
3241             case DECPREFIX:
3242                 final TokenType opType = type;
3243                 final Expression lhs = expression;
3244                 // ++, -- without operand..
3245                 if (lhs == null) {
3246                     throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3247                 }
3248 
3249                 if (!(lhs instanceof AccessNode ||
3250                    lhs instanceof IndexNode ||
3251                    lhs instanceof IdentNode)) {
3252                     next();
3253                     return referenceError(lhs, null, env._early_lvalue_error);
3254                 }
3255                 if (lhs instanceof IdentNode) {
3256                     if (!checkIdentLValue((IdentNode)lhs)) {
3257                         next();
3258                         return referenceError(lhs, null, false);
3259                     }
3260                     verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3261                 }
3262                 expression = incDecExpression(token, type, expression, true);
3263                 next();
3264                 break;
3265             default:
3266                 break;
3267             }
3268         }
3269 
3270         if (expression == null) {
3271             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3272         }
3273 
3274         return expression;
3275     }
3276 
3277     /**
3278      * {@code
3279      * MultiplicativeExpression :
3280      *      UnaryExpression
3281      *      MultiplicativeExpression * UnaryExpression
3282      *      MultiplicativeExpression / UnaryExpression
3283      *      MultiplicativeExpression % UnaryExpression
3284      *
3285      * See 11.5
3286      *
3287      * AdditiveExpression :
3288      *      MultiplicativeExpression
3289      *      AdditiveExpression + MultiplicativeExpression
3290      *      AdditiveExpression - MultiplicativeExpression
3291      *
3292      * See 11.6
3293      *
3294      * ShiftExpression :
3295      *      AdditiveExpression
3296      *      ShiftExpression << AdditiveExpression
3297      *      ShiftExpression >> AdditiveExpression
3298      *      ShiftExpression >>> AdditiveExpression
3299      *
3300      * See 11.7
3301      *
3302      * RelationalExpression :
3303      *      ShiftExpression
3304      *      RelationalExpression < ShiftExpression
3305      *      RelationalExpression > ShiftExpression
3306      *      RelationalExpression <= ShiftExpression
3307      *      RelationalExpression >= ShiftExpression
3308      *      RelationalExpression instanceof ShiftExpression
3309      *      RelationalExpression in ShiftExpression // if !noIf
3310      *
3311      * See 11.8
3312      *
3313      *      RelationalExpression
3314      *      EqualityExpression == RelationalExpression
3315      *      EqualityExpression != RelationalExpression
3316      *      EqualityExpression === RelationalExpression
3317      *      EqualityExpression !== RelationalExpression
3318      *
3319      * See 11.9
3320      *
3321      * BitwiseANDExpression :
3322      *      EqualityExpression
3323      *      BitwiseANDExpression & EqualityExpression
3324      *
3325      * BitwiseXORExpression :
3326      *      BitwiseANDExpression
3327      *      BitwiseXORExpression ^ BitwiseANDExpression
3328      *
3329      * BitwiseORExpression :
3330      *      BitwiseXORExpression
3331      *      BitwiseORExpression | BitwiseXORExpression
3332      *
3333      * See 11.10
3334      *
3335      * LogicalANDExpression :
3336      *      BitwiseORExpression
3337      *      LogicalANDExpression && BitwiseORExpression
3338      *
3339      * LogicalORExpression :
3340      *      LogicalANDExpression
3341      *      LogicalORExpression || LogicalANDExpression
3342      *
3343      * See 11.11
3344      *
3345      * ConditionalExpression :
3346      *      LogicalORExpression
3347      *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
3348      *
3349      * See 11.12
3350      *
3351      * AssignmentExpression :
3352      *      ConditionalExpression
3353      *      LeftHandSideExpression AssignmentOperator AssignmentExpression
3354      *
3355      * AssignmentOperator :
3356      *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
3357      *
3358      * See 11.13
3359      *
3360      * Expression :
3361      *      AssignmentExpression
3362      *      Expression , AssignmentExpression
3363      *
3364      * See 11.14
3365      * }
3366      *
3367      * Parse expression.
3368      * @return Expression node.
3369      */
3370     protected Expression expression() {
3371         // This method is protected so that subclass can get details
3372         // at expression start point!
3373 
3374         // Include commas in expression parsing.
3375         return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
3376     }
3377 
3378     private JoinPredecessorExpression joinPredecessorExpression() {
3379         return new JoinPredecessorExpression(expression());
3380     }
3381 
3382     private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
3383         // Get the precedence of the next operator.
3384         int precedence = type.getPrecedence();
3385         Expression lhs = exprLhs;
3386 
3387         // While greater precedence.
3388         while (type.isOperator(noIn) && precedence >= minPrecedence) {
3389             // Capture the operator token.
3390             final long op = token;
3391 
3392             if (type == TERNARY) {
3393                 // Skip operator.
3394                 next();
3395 
3396                 // Pass expression. Middle expression of a conditional expression can be a "in"
3397                 // expression - even in the contexts where "in" is not permitted.
3398                 final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
3399 
3400                 expect(COLON);
3401 
3402                 // Fail expression.
3403                 final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3404 
3405                 // Build up node.
3406                 lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
3407             } else {
3408                 // Skip operator.
3409                 next();
3410 
3411                  // Get the next primary expression.
3412                 Expression rhs;
3413                 final boolean isAssign = Token.descType(op) == ASSIGN;
3414                 if(isAssign) {
3415                     defaultNames.push(lhs);
3416                 }
3417                 try {
3418                     rhs = unaryExpression();
3419                     // Get precedence of next operator.
3420                     int nextPrecedence = type.getPrecedence();
3421 
3422                     // Subtask greater precedence.
3423                     while (type.isOperator(noIn) &&
3424                            (nextPrecedence > precedence ||
3425                            nextPrecedence == precedence && !type.isLeftAssociative())) {
3426                         rhs = expression(rhs, nextPrecedence, noIn);
3427                         nextPrecedence = type.getPrecedence();
3428                     }
3429                 } finally {
3430                     if(isAssign) {
3431                         defaultNames.pop();
3432                     }
3433                 }
3434                 lhs = verifyAssignment(op, lhs, rhs);
3435             }
3436 
3437             precedence = type.getPrecedence();
3438         }
3439 
3440         return lhs;
3441     }
3442 
3443     protected Expression assignmentExpression(final boolean noIn) {
3444         // This method is protected so that subclass can get details
3445         // at assignment expression start point!
3446 
3447         // Exclude commas in expression parsing.
3448         return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3449     }
3450 
3451     /**
3452      * Parse an end of line.
3453      */
3454     private void endOfLine() {
3455         switch (type) {
3456         case SEMICOLON:
3457         case EOL:
3458             next();
3459             break;
3460         case RPAREN:
3461         case RBRACKET:
3462         case RBRACE:
3463         case EOF:
3464             break;
3465         default:
3466             if (last != EOL) {
3467                 expect(SEMICOLON);
3468             }
3469             break;
3470         }
3471     }
3472 
3473     /**
3474      * Parse untagged template literal as string concatenation.
3475      */
3476     private Expression templateLiteral() {
3477         assert type == TEMPLATE || type == TEMPLATE_HEAD;
3478         final boolean noSubstitutionTemplate = type == TEMPLATE;
3479         long lastLiteralToken = token;
3480         LiteralNode<?> literal = getLiteral();
3481         if (noSubstitutionTemplate) {
3482             return literal;
3483         }
3484 
3485         Expression concat = literal;
3486         TokenType lastLiteralType;
3487         do {
3488             final Expression expression = expression();
3489             if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
3490                 throw error(AbstractParser.message("unterminated.template.expression"), token);
3491             }
3492             concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression);
3493             lastLiteralType = type;
3494             lastLiteralToken = token;
3495             literal = getLiteral();
3496             concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal);
3497         } while (lastLiteralType == TEMPLATE_MIDDLE);
3498         return concat;
3499     }
3500 
3501     /**
3502      * Parse tagged template literal as argument list.
3503      * @return argument list for a tag function call (template object, ...substitutions)
3504      */
3505     private List<Expression> templateLiteralArgumentList() {
3506         assert type == TEMPLATE || type == TEMPLATE_HEAD;
3507         final ArrayList<Expression> argumentList = new ArrayList<>();
3508         final ArrayList<Expression> rawStrings = new ArrayList<>();
3509         final ArrayList<Expression> cookedStrings = new ArrayList<>();
3510         argumentList.add(null); // filled at the end
3511 
3512         final long templateToken = token;
3513         final boolean hasSubstitutions = type == TEMPLATE_HEAD;
3514         addTemplateLiteralString(rawStrings, cookedStrings);
3515 
3516         if (hasSubstitutions) {
3517             TokenType lastLiteralType;
3518             do {
3519                 final Expression expression = expression();
3520                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
3521                     throw error(AbstractParser.message("unterminated.template.expression"), token);
3522                 }
3523                 argumentList.add(expression);
3524 
3525                 lastLiteralType = type;
3526                 addTemplateLiteralString(rawStrings, cookedStrings);
3527             } while (lastLiteralType == TEMPLATE_MIDDLE);
3528         }
3529 
3530         final LiteralNode<Expression[]> rawStringArray = LiteralNode.newInstance(templateToken, finish, rawStrings);
3531         final LiteralNode<Expression[]> cookedStringArray = LiteralNode.newInstance(templateToken, finish, cookedStrings);
3532         final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray);
3533         argumentList.set(0, templateObject);
3534         return optimizeList(argumentList);
3535     }
3536 
3537     private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) {
3538         final long stringToken = token;
3539         final String rawString = lexer.valueOfRawString(stringToken);
3540         final String cookedString = (String) getValue();
3541         next();
3542         rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString));
3543         cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
3544     }
3545 
3546     @Override
3547     public String toString() {
3548         return "'JavaScript Parsing'";
3549     }
3550 
3551     private static void markEval(final ParserContext lc) {
3552         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
3553         boolean flaggedCurrentFn = false;
3554         while (iter.hasNext()) {
3555             final ParserContextFunctionNode fn = iter.next();
3556             if (!flaggedCurrentFn) {
3557                 fn.setFlag(FunctionNode.HAS_EVAL);
3558                 flaggedCurrentFn = true;
3559             } else {
3560                 fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
3561             }
3562             final ParserContextBlockNode body = lc.getFunctionBody(fn);
3563             // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
3564             // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
3565             // this method when the parser skips a nested function.
3566             body.setFlag(Block.NEEDS_SCOPE);
3567             fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
3568         }
3569     }
3570 
3571     private void prependStatement(final Statement statement) {
3572         lc.prependStatementToCurrentNode(statement);
3573     }
3574 
3575     private void appendStatement(final Statement statement) {
3576         lc.appendStatementToCurrentNode(statement);
3577     }
3578 }