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);
 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);
 950                 break;
 951             }
 952             if (env._const_as_var && type == CONST) {
 953                 variableStatement(TokenType.VAR);
 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) {
1070         return variableStatement(varType, true, -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     @SuppressWarnings("fallthrough")
1219     private void forStatement() {
1220         final long forToken = token;
1221         final int forLine = line;
1222         // start position of this for statement. This is used
1223         // for sort order for variables declared in the initializer
1224         // part of this 'for' statement (if any).
1225         final int forStart = Token.descPosition(forToken);
1226         // When ES6 for-let is enabled we create a container block to capture the LET.
1227         final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1228 
1229         // Create FOR node, capturing FOR token.
1230         final ParserContextLoopNode forNode = new ParserContextLoopNode();
1231         lc.push(forNode);
1232         Block body = null;
1233         List<VarNode> vars = null;
1234         Expression init = null;
1235         JoinPredecessorExpression test = null;
1236         JoinPredecessorExpression modify = null;
1237 
1238         int flags = 0;
1239         boolean isForOf = false;
1240 
1241         try {
1242             // FOR tested in caller.
1243             next();
1244 
1245             // Nashorn extension: for each expression.
1246             // iterate property values rather than property names.
1247             if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1248                 flags |= ForNode.IS_FOR_EACH;
1249                 next();
1250             }
1251 
1252             expect(LPAREN);
1253 
1254             switch (type) {
1255             case VAR:
1256                 // Var declaration captured in for outer block.
1257                 vars = variableStatement(type, false, forStart);
1258                 break;
1259             case SEMICOLON:
1260                 break;
1261             default:
1262                 if (useBlockScope() && (type == LET || type == CONST)) {
1263                     flags |= ForNode.PER_ITERATION_SCOPE;
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 IDENT:
1298                 if (env._es6 && "of".equals(getValue())) {
1299                     isForOf = true;
1300                     // fall through
1301                 } else {
1302                     expect(SEMICOLON); // fail with expected message
1303                     break;
1304                 }
1305             case IN:
1306 
1307                 flags |= isForOf ? ForNode.IS_FOR_OF : ForNode.IS_FOR_IN;
1308                 test = new JoinPredecessorExpression();
1309                 if (vars != null) {
1310                     // for (var i in obj)
1311                     if (vars.size() == 1) {
1312                         init = new IdentNode(vars.get(0).getName());
1313                     } else {
1314                         // for (var i, j in obj) is invalid
1315                         throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), vars.get(1).getToken());
1316                     }
1317                 } else {
1318                     // for (expr in obj)
1319                     assert init != null : "for..in/of init expression can not be null here";
1320 
1321                     // check if initial expression is a valid L-value
1322                     if (!(init instanceof AccessNode ||
1323                           init instanceof IndexNode ||
1324                           init instanceof IdentNode)) {
1325                         throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
1326                     }
1327 
1328                     if (init instanceof IdentNode) {
1329                         if (!checkIdentLValue((IdentNode)init)) {
1330                             throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
1331                         }
1332                         verifyStrictIdent((IdentNode)init, isForOf ? "for-of iterator" : "for-in iterator");
1333                     }
1334                 }
1335 
1336                 next();
1337 
1338                 // For-of only allows AssignmentExpression.
1339                 modify = isForOf ? new JoinPredecessorExpression(assignmentExpression(false)) : joinPredecessorExpression();
1340                 break;
1341 
1342             default:
1343                 expect(SEMICOLON);
1344                 break;
1345             }
1346 
1347             expect(RPAREN);
1348 
1349             // Set the for body.
1350             body = getStatement();
1351         } finally {
1352             lc.pop(forNode);
1353 
1354             if (vars != null) {
1355                 for (final VarNode var : vars) {
1356                     appendStatement(var);
1357                 }
1358             }
1359             if (body != null) {
1360                 appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
1361             }
1362             if (outer != null) {
1363                 restoreBlock(outer);
1364                 if (body != null) {
1365                     appendStatement(new BlockStatement(forLine, new Block(
1366                                     outer.getToken(),
1367                                     body.getFinish(),
1368                                     outer.getStatements())));
1369                 }
1370             }
1371         }
1372     }
1373 
1374     /**
1375      * ...IterationStatement :
1376      *           ...
1377      *           while ( Expression ) Statement
1378      *           ...
1379      *
1380      * See 12.6
1381      *
1382      * Parse while statement.
1383      */
1384     private void whileStatement() {
1385         // Capture WHILE token.
1386         final long whileToken = token;
1387         final int whileLine = line;
1388         // WHILE tested in caller.
1389         next();
1390 
1391         final ParserContextLoopNode whileNode = new ParserContextLoopNode();
1392         lc.push(whileNode);
1393 
1394         JoinPredecessorExpression test = null;
1395         Block body = null;
1396 
1397         try {
1398             expect(LPAREN);
1399             test = joinPredecessorExpression();
1400             expect(RPAREN);
1401             body = getStatement();
1402         } finally {
1403             lc.pop(whileNode);
1404         }
1405 
1406         if (body != null) {
1407             appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
1408         }
1409     }
1410 
1411     /**
1412      * ...IterationStatement :
1413      *           ...
1414      *           do Statement while( Expression ) ;
1415      *           ...
1416      *
1417      * See 12.6
1418      *
1419      * Parse DO WHILE statement.
1420      */
1421     private void doStatement() {
1422         // Capture DO token.
1423         final long doToken = token;
1424         int doLine = 0;
1425         // DO tested in the caller.
1426         next();
1427 
1428         final ParserContextLoopNode doWhileNode = new ParserContextLoopNode();
1429         lc.push(doWhileNode);
1430 
1431         Block body = null;
1432         JoinPredecessorExpression test = null;
1433 
1434         try {
1435            // Get DO body.
1436             body = getStatement();
1437 
1438             expect(WHILE);
1439             expect(LPAREN);
1440             doLine = line;
1441             test = joinPredecessorExpression();
1442             expect(RPAREN);
1443 
1444             if (type == SEMICOLON) {
1445                 endOfLine();
1446             }
1447         } finally {
1448             lc.pop(doWhileNode);
1449         }
1450 
1451         appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
1452     }
1453 
1454     /**
1455      * ContinueStatement :
1456      *      continue Identifier? ; // [no LineTerminator here]
1457      *
1458      * See 12.7
1459      *
1460      * Parse CONTINUE statement.
1461      */
1462     private void continueStatement() {
1463         // Capture CONTINUE token.
1464         final int  continueLine  = line;
1465         final long continueToken = token;
1466         // CONTINUE tested in caller.
1467         nextOrEOL();
1468 
1469         ParserContextLabelNode labelNode = null;
1470 
1471         // SEMICOLON or label.
1472         switch (type) {
1473         case RBRACE:
1474         case SEMICOLON:
1475         case EOL:
1476         case EOF:
1477             break;
1478 
1479         default:
1480             final IdentNode ident = getIdent();
1481             labelNode = lc.findLabel(ident.getName());
1482 
1483             if (labelNode == null) {
1484                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1485             }
1486 
1487             break;
1488         }
1489 
1490         final String labelName = labelNode == null ? null : labelNode.getLabelName();
1491         final ParserContextLoopNode targetNode = lc.getContinueTo(labelName);
1492 
1493         if (targetNode == null) {
1494             throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
1495         }
1496 
1497         endOfLine();
1498 
1499         // Construct and add CONTINUE node.
1500         appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
1501     }
1502 
1503     /**
1504      * BreakStatement :
1505      *      break Identifier? ; // [no LineTerminator here]
1506      *
1507      * See 12.8
1508      *
1509      */
1510     private void breakStatement() {
1511         // Capture BREAK token.
1512         final int  breakLine  = line;
1513         final long breakToken = token;
1514         // BREAK tested in caller.
1515         nextOrEOL();
1516 
1517         ParserContextLabelNode labelNode = null;
1518 
1519         // SEMICOLON or label.
1520         switch (type) {
1521         case RBRACE:
1522         case SEMICOLON:
1523         case EOL:
1524         case EOF:
1525             break;
1526 
1527         default:
1528             final IdentNode ident = getIdent();
1529             labelNode = lc.findLabel(ident.getName());
1530 
1531             if (labelNode == null) {
1532                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1533             }
1534 
1535             break;
1536         }
1537 
1538         //either an explicit label - then get its node or just a "break" - get first breakable
1539         //targetNode is what we are breaking out from.
1540         final String labelName = labelNode == null ? null : labelNode.getLabelName();
1541         final ParserContextBreakableNode targetNode = lc.getBreakable(labelName);
1542         if (targetNode == null) {
1543             throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
1544         }
1545 
1546         endOfLine();
1547 
1548         // Construct and add BREAK node.
1549         appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
1550     }
1551 
1552     /**
1553      * ReturnStatement :
1554      *      return Expression? ; // [no LineTerminator here]
1555      *
1556      * See 12.9
1557      *
1558      * Parse RETURN statement.
1559      */
1560     private void returnStatement() {
1561         // check for return outside function
1562         if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT) {
1563             throw error(AbstractParser.message("invalid.return"));
1564         }
1565 
1566         // Capture RETURN token.
1567         final int  returnLine  = line;
1568         final long returnToken = token;
1569         // RETURN tested in caller.
1570         nextOrEOL();
1571 
1572         Expression expression = null;
1573 
1574         // SEMICOLON or expression.
1575         switch (type) {
1576         case RBRACE:
1577         case SEMICOLON:
1578         case EOL:
1579         case EOF:
1580             break;
1581 
1582         default:
1583             expression = expression();
1584             break;
1585         }
1586 
1587         endOfLine();
1588 
1589         // Construct and add RETURN node.
1590         appendStatement(new ReturnNode(returnLine, returnToken, finish, expression));
1591     }
1592 
1593     /**
1594      * YieldStatement :
1595      *      yield Expression? ; // [no LineTerminator here]
1596      *
1597      * JavaScript 1.8
1598      *
1599      * Parse YIELD statement.
1600      */
1601     private void yieldStatement() {
1602         // Capture YIELD token.
1603         final int  yieldLine  = line;
1604         final long yieldToken = token;
1605         // YIELD tested in caller.
1606         nextOrEOL();
1607 
1608         Expression expression = null;
1609 
1610         // SEMICOLON or expression.
1611         switch (type) {
1612         case RBRACE:
1613         case SEMICOLON:
1614         case EOL:
1615         case EOF:
1616             break;
1617 
1618         default:
1619             expression = expression();
1620             break;
1621         }
1622 
1623         endOfLine();
1624 
1625         // Construct and add YIELD node.
1626         appendStatement(new ReturnNode(yieldLine, yieldToken, finish, expression));
1627     }
1628 
1629     /**
1630      * WithStatement :
1631      *      with ( Expression ) Statement
1632      *
1633      * See 12.10
1634      *
1635      * Parse WITH statement.
1636      */
1637     private void withStatement() {
1638         // Capture WITH token.
1639         final int  withLine  = line;
1640         final long withToken = token;
1641         // WITH tested in caller.
1642         next();
1643 
1644         // ECMA 12.10.1 strict mode restrictions
1645         if (isStrictMode) {
1646             throw error(AbstractParser.message("strict.no.with"), withToken);
1647         }
1648 
1649         expect(LPAREN);
1650         final Expression expression = expression();
1651         expect(RPAREN);
1652         final Block body = getStatement();
1653 
1654         appendStatement(new WithNode(withLine, withToken, finish, expression, body));
1655     }
1656 
1657     /**
1658      * SwitchStatement :
1659      *      switch ( Expression ) CaseBlock
1660      *
1661      * CaseBlock :
1662      *      { CaseClauses? }
1663      *      { CaseClauses? DefaultClause CaseClauses }
1664      *
1665      * CaseClauses :
1666      *      CaseClause
1667      *      CaseClauses CaseClause
1668      *
1669      * CaseClause :
1670      *      case Expression : StatementList?
1671      *
1672      * DefaultClause :
1673      *      default : StatementList?
1674      *
1675      * See 12.11
1676      *
1677      * Parse SWITCH statement.
1678      */
1679     private void switchStatement() {
1680         final int  switchLine  = line;
1681         final long switchToken = token;
1682         // SWITCH tested in caller.
1683         next();
1684 
1685         // Create and add switch statement.
1686         final ParserContextSwitchNode switchNode= new ParserContextSwitchNode();
1687         lc.push(switchNode);
1688 
1689         CaseNode defaultCase = null;
1690         // Prepare to accumulate cases.
1691         final List<CaseNode> cases = new ArrayList<>();
1692 
1693         Expression expression = null;
1694 
1695         try {
1696             expect(LPAREN);
1697             expression = expression();
1698             expect(RPAREN);
1699 
1700             expect(LBRACE);
1701 
1702 
1703             while (type != RBRACE) {
1704                 // Prepare for next case.
1705                 Expression caseExpression = null;
1706                 final long caseToken = token;
1707 
1708                 switch (type) {
1709                 case CASE:
1710                     next();
1711                     caseExpression = expression();
1712                     break;
1713 
1714                 case DEFAULT:
1715                     if (defaultCase != null) {
1716                         throw error(AbstractParser.message("duplicate.default.in.switch"));
1717                     }
1718                     next();
1719                     break;
1720 
1721                 default:
1722                     // Force an error.
1723                     expect(CASE);
1724                     break;
1725                 }
1726 
1727                 expect(COLON);
1728 
1729                 // Get CASE body.
1730                 final Block statements = getBlock(false);
1731                 final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
1732 
1733                 if (caseExpression == null) {
1734                     defaultCase = caseNode;
1735                 }
1736 
1737                 cases.add(caseNode);
1738             }
1739 
1740             next();
1741         } finally {
1742             lc.pop(switchNode);
1743         }
1744 
1745         appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase));
1746     }
1747 
1748     /**
1749      * LabelledStatement :
1750      *      Identifier : Statement
1751      *
1752      * See 12.12
1753      *
1754      * Parse label statement.
1755      */
1756     private void labelStatement() {
1757         // Capture label token.
1758         final long labelToken = token;
1759         // Get label ident.
1760         final IdentNode ident = getIdent();
1761 
1762         expect(COLON);
1763 
1764         if (lc.findLabel(ident.getName()) != null) {
1765             throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
1766         }
1767 
1768         final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName());
1769         Block body = null;
1770         try {
1771             lc.push(labelNode);
1772             body = getStatement();
1773         } finally {
1774             assert lc.peek() instanceof ParserContextLabelNode;
1775             lc.pop(labelNode);
1776         }
1777 
1778         appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
1779     }
1780 
1781     /**
1782      * ThrowStatement :
1783      *      throw Expression ; // [no LineTerminator here]
1784      *
1785      * See 12.13
1786      *
1787      * Parse throw statement.
1788      */
1789     private void throwStatement() {
1790         // Capture THROW token.
1791         final int  throwLine  = line;
1792         final long throwToken = token;
1793         // THROW tested in caller.
1794         nextOrEOL();
1795 
1796         Expression expression = null;
1797 
1798         // SEMICOLON or expression.
1799         switch (type) {
1800         case RBRACE:
1801         case SEMICOLON:
1802         case EOL:
1803             break;
1804 
1805         default:
1806             expression = expression();
1807             break;
1808         }
1809 
1810         if (expression == null) {
1811             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
1812         }
1813 
1814         endOfLine();
1815 
1816         appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
1817     }
1818 
1819     /**
1820      * TryStatement :
1821      *      try Block Catch
1822      *      try Block Finally
1823      *      try Block Catch Finally
1824      *
1825      * Catch :
1826      *      catch( Identifier if Expression ) Block
1827      *      catch( Identifier ) Block
1828      *
1829      * Finally :
1830      *      finally Block
1831      *
1832      * See 12.14
1833      *
1834      * Parse TRY statement.
1835      */
1836     private void tryStatement() {
1837         // Capture TRY token.
1838         final int  tryLine  = line;
1839         final long tryToken = token;
1840         // TRY tested in caller.
1841         next();
1842 
1843         // Container block needed to act as target for labeled break statements
1844         final int startLine = line;
1845         final ParserContextBlockNode outer = newBlock();
1846         // Create try.
1847 
1848         try {
1849             final Block       tryBody     = getBlock(true);
1850             final List<Block> catchBlocks = new ArrayList<>();
1851 
1852             while (type == CATCH) {
1853                 final int  catchLine  = line;
1854                 final long catchToken = token;
1855                 next();
1856                 expect(LPAREN);
1857                 final IdentNode exception = getIdent();
1858 
1859                 // ECMA 12.4.1 strict mode restrictions
1860                 verifyStrictIdent(exception, "catch argument");
1861 
1862                 // Nashorn extension: catch clause can have optional
1863                 // condition. So, a single try can have more than one
1864                 // catch clause each with it's own condition.
1865                 final Expression ifExpression;
1866                 if (!env._no_syntax_extensions && type == IF) {
1867                     next();
1868                     // Get the exception condition.
1869                     ifExpression = expression();
1870                 } else {
1871                     ifExpression = null;
1872                 }
1873 
1874                 expect(RPAREN);
1875 
1876                 final ParserContextBlockNode catchBlock = newBlock();
1877                 try {
1878                     // Get CATCH body.
1879                     final Block catchBody = getBlock(true);
1880                     final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
1881                     appendStatement(catchNode);
1882                 } finally {
1883                     restoreBlock(catchBlock);
1884                     catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements()));
1885                 }
1886 
1887                 // If unconditional catch then should to be the end.
1888                 if (ifExpression == null) {
1889                     break;
1890                 }
1891             }
1892 
1893             // Prepare to capture finally statement.
1894             Block finallyStatements = null;
1895 
1896             if (type == FINALLY) {
1897                 next();
1898                 finallyStatements = getBlock(true);
1899             }
1900 
1901             // Need at least one catch or a finally.
1902             if (catchBlocks.isEmpty() && finallyStatements == null) {
1903                 throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
1904             }
1905 
1906             final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
1907             // Add try.
1908             assert lc.peek() == outer;
1909             appendStatement(tryNode);
1910         } finally {
1911             restoreBlock(outer);
1912         }
1913 
1914         appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements())));
1915     }
1916 
1917     /**
1918      * DebuggerStatement :
1919      *      debugger ;
1920      *
1921      * See 12.15
1922      *
1923      * Parse debugger statement.
1924      */
1925     private void  debuggerStatement() {
1926         // Capture DEBUGGER token.
1927         final int  debuggerLine  = line;
1928         final long debuggerToken = token;
1929         // DEBUGGER tested in caller.
1930         next();
1931         endOfLine();
1932         appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish));
1933     }
1934 
1935     /**
1936      * PrimaryExpression :
1937      *      this
1938      *      Identifier
1939      *      Literal
1940      *      ArrayLiteral
1941      *      ObjectLiteral
1942      *      RegularExpressionLiteral
1943      *      TemplateLiteral
1944      *      ( Expression )
1945      *
1946      * Parse primary expression.
1947      * @return Expression node.
1948      */
1949     @SuppressWarnings("fallthrough")
1950     private Expression primaryExpression() {
1951         // Capture first token.
1952         final int  primaryLine  = line;
1953         final long primaryToken = token;
1954 
1955         switch (type) {
1956         case THIS:
1957             final String name = type.getName();
1958             next();
1959             lc.getCurrentFunction().setFlag(FunctionNode.USES_THIS);
1960             return new IdentNode(primaryToken, finish, name);
1961         case IDENT:
1962             final IdentNode ident = getIdent();
1963             if (ident == null) {
1964                 break;
1965             }
1966             detectSpecialProperty(ident);
1967             return ident;
1968         case OCTAL_LEGACY:
1969             if (isStrictMode) {
1970                throw error(AbstractParser.message("strict.no.octal"), token);
1971             }
1972         case STRING:
1973         case ESCSTRING:
1974         case DECIMAL:
1975         case HEXADECIMAL:
1976         case OCTAL:
1977         case BINARY_NUMBER:
1978         case FLOATING:
1979         case REGEX:
1980         case XML:
1981             return getLiteral();
1982         case EXECSTRING:
1983             return execString(primaryLine, primaryToken);
1984         case FALSE:
1985             next();
1986             return LiteralNode.newInstance(primaryToken, finish, false);
1987         case TRUE:
1988             next();
1989             return LiteralNode.newInstance(primaryToken, finish, true);
1990         case NULL:
1991             next();
1992             return LiteralNode.newInstance(primaryToken, finish);
1993         case LBRACKET:
1994             return arrayLiteral();
1995         case LBRACE:
1996             return objectLiteral();
1997         case LPAREN:
1998             next();
1999 
2000             final Expression expression = expression();
2001 
2002             expect(RPAREN);
2003 
2004             return expression;
2005         case TEMPLATE:
2006         case TEMPLATE_HEAD:
2007             return templateLiteral();
2008 
2009         default:
2010             // In this context some operator tokens mark the start of a literal.
2011             if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
2012                 next();
2013                 return getLiteral();
2014             }
2015             if (isNonStrictModeIdent()) {
2016                 return getIdent();
2017             }
2018             break;
2019         }
2020 
2021         return null;
2022     }
2023 
2024     /**
2025      * Convert execString to a call to $EXEC.
2026      *
2027      * @param primaryToken Original string token.
2028      * @return callNode to $EXEC.
2029      */
2030     CallNode execString(final int primaryLine, final long primaryToken) {
2031         // Synthesize an ident to call $EXEC.
2032         final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
2033         // Skip over EXECSTRING.
2034         next();
2035         // Set up argument list for call.
2036         // Skip beginning of edit string expression.
2037         expect(LBRACE);
2038         // Add the following expression to arguments.
2039         final List<Expression> arguments = Collections.singletonList(expression());
2040         // Skip ending of edit string expression.
2041         expect(RBRACE);
2042 
2043         return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
2044     }
2045 
2046     /**
2047      * ArrayLiteral :
2048      *      [ Elision? ]
2049      *      [ ElementList ]
2050      *      [ ElementList , Elision? ]
2051      *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
2052      *
2053      * ElementList : Elision? AssignmentExpression
2054      *      ElementList , Elision? AssignmentExpression
2055      *
2056      * Elision :
2057      *      ,
2058      *      Elision ,
2059      *
2060      * See 12.1.4
2061      * JavaScript 1.8
2062      *
2063      * Parse array literal.
2064      * @return Expression node.
2065      */
2066     private LiteralNode<Expression[]> arrayLiteral() {
2067         // Capture LBRACKET token.
2068         final long arrayToken = token;
2069         // LBRACKET tested in caller.
2070         next();
2071 
2072         // Prepare to accumulate elements.
2073         final List<Expression> elements = new ArrayList<>();
2074         // Track elisions.
2075         boolean elision = true;
2076 loop:
2077         while (true) {
2078             switch (type) {
2079             case RBRACKET:
2080                 next();
2081 
2082                 break loop;
2083 
2084             case COMMARIGHT:
2085                 next();
2086 
2087                 // If no prior expression
2088                 if (elision) {
2089                     elements.add(null);
2090                 }
2091 
2092                 elision = true;
2093 
2094                 break;
2095 
2096             default:
2097                 if (!elision) {
2098                     throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2099                 }
2100                 // Add expression element.
2101                 final Expression expression = assignmentExpression(false);
2102 
2103                 if (expression != null) {
2104                     elements.add(expression);
2105                 } else {
2106                     expect(RBRACKET);
2107                 }
2108 
2109                 elision = false;
2110                 break;
2111             }
2112         }
2113 
2114         return LiteralNode.newInstance(arrayToken, finish, elements);
2115     }
2116 
2117     /**
2118      * ObjectLiteral :
2119      *      { }
2120      *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2121      *
2122      * PropertyNameAndValueList :
2123      *      PropertyAssignment
2124      *      PropertyNameAndValueList , PropertyAssignment
2125      *
2126      * See 11.1.5
2127      *
2128      * Parse an object literal.
2129      * @return Expression node.
2130      */
2131     private ObjectNode objectLiteral() {
2132         // Capture LBRACE token.
2133         final long objectToken = token;
2134         // LBRACE tested in caller.
2135         next();
2136 
2137         // Object context.
2138         // Prepare to accumulate elements.
2139         final List<PropertyNode> elements = new ArrayList<>();
2140         final Map<String, Integer> map = new HashMap<>();
2141 
2142         // Create a block for the object literal.
2143         boolean commaSeen = true;
2144 loop:
2145         while (true) {
2146             switch (type) {
2147                 case RBRACE:
2148                     next();
2149                     break loop;
2150 
2151                 case COMMARIGHT:
2152                     if (commaSeen) {
2153                         throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2154                     }
2155                     next();
2156                     commaSeen = true;
2157                     break;
2158 
2159                 default:
2160                     if (!commaSeen) {
2161                         throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2162                     }
2163 
2164                     commaSeen = false;
2165                     // Get and add the next property.
2166                     final PropertyNode property = propertyAssignment();
2167                     final String key = property.getKeyName();
2168                     final Integer existing = map.get(key);
2169 
2170                     if (existing == null) {
2171                         map.put(key, elements.size());
2172                         elements.add(property);
2173                         break;
2174                     }
2175 
2176                     final PropertyNode existingProperty = elements.get(existing);
2177 
2178                     // ECMA section 11.1.5 Object Initialiser
2179                     // point # 4 on property assignment production
2180                     final Expression   value  = property.getValue();
2181                     final FunctionNode getter = property.getGetter();
2182                     final FunctionNode setter = property.getSetter();
2183 
2184                     final Expression   prevValue  = existingProperty.getValue();
2185                     final FunctionNode prevGetter = existingProperty.getGetter();
2186                     final FunctionNode prevSetter = existingProperty.getSetter();
2187 
2188                     // ECMA 11.1.5 strict mode restrictions
2189                     if (isStrictMode && value != null && prevValue != null) {
2190                         throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2191                     }
2192 
2193                     final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
2194                     final boolean isAccessor     = getter != null     || setter != null;
2195 
2196                     // data property redefined as accessor property
2197                     if (prevValue != null && isAccessor) {
2198                         throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2199                     }
2200 
2201                     // accessor property redefined as data
2202                     if (isPrevAccessor && value != null) {
2203                         throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2204                     }
2205 
2206                     if (isAccessor && isPrevAccessor) {
2207                         if (getter != null && prevGetter != null ||
2208                                 setter != null && prevSetter != null) {
2209                             throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2210                         }
2211                     }
2212 
2213                     if (value != null) {
2214                         elements.add(property);
2215                     } else if (getter != null) {
2216                         elements.set(existing, existingProperty.setGetter(getter));
2217                     } else if (setter != null) {
2218                         elements.set(existing, existingProperty.setSetter(setter));
2219                     }
2220                     break;
2221             }
2222         }
2223 
2224         return new ObjectNode(objectToken, finish, elements);
2225     }
2226 
2227     /**
2228      * PropertyName :
2229      *      IdentifierName
2230      *      StringLiteral
2231      *      NumericLiteral
2232      *
2233      * See 11.1.5
2234      *
2235      * @return PropertyName node
2236      */
2237     @SuppressWarnings("fallthrough")
2238     private PropertyKey propertyName() {
2239         switch (type) {
2240         case IDENT:
2241             return getIdent().setIsPropertyName();
2242         case OCTAL_LEGACY:
2243             if (isStrictMode) {
2244                 throw error(AbstractParser.message("strict.no.octal"), token);
2245             }
2246         case STRING:
2247         case ESCSTRING:
2248         case DECIMAL:
2249         case HEXADECIMAL:
2250         case OCTAL:
2251         case BINARY_NUMBER:
2252         case FLOATING:
2253             return getLiteral();
2254         default:
2255             return getIdentifierName().setIsPropertyName();
2256         }
2257     }
2258 
2259     /**
2260      * PropertyAssignment :
2261      *      PropertyName : AssignmentExpression
2262      *      get PropertyName ( ) { FunctionBody }
2263      *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
2264      *
2265      * PropertySetParameterList :
2266      *      Identifier
2267      *
2268      * PropertyName :
2269      *      IdentifierName
2270      *      StringLiteral
2271      *      NumericLiteral
2272      *
2273      * See 11.1.5
2274      *
2275      * Parse an object literal property.
2276      * @return Property or reference node.
2277      */
2278     private PropertyNode propertyAssignment() {
2279         // Capture firstToken.
2280         final long propertyToken = token;
2281         final int  functionLine  = line;
2282 
2283         PropertyKey propertyName;
2284 
2285         if (type == IDENT) {
2286             // Get IDENT.
2287             final String ident = (String)expectValue(IDENT);
2288 
2289             if (type != COLON) {
2290                 final long getSetToken = propertyToken;
2291 
2292                 switch (ident) {
2293                 case "get":
2294                     final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
2295                     return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null);
2296 
2297                 case "set":
2298                     final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
2299                     return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode);
2300                 default:
2301                     break;
2302                 }
2303             }
2304 
2305             propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
2306         } else {
2307             propertyName = propertyName();
2308         }
2309 
2310         expect(COLON);
2311 
2312         defaultNames.push(propertyName);
2313         try {
2314             return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
2315         } finally {
2316             defaultNames.pop();
2317         }
2318     }
2319 
2320     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
2321         final PropertyKey getIdent = propertyName();
2322         final String getterName = getIdent.getPropertyName();
2323         final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
2324         expect(LPAREN);
2325         expect(RPAREN);
2326 
2327         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
2328         lc.push(functionNode);
2329 
2330         Block functionBody;
2331 
2332 
2333         try {
2334             functionBody = functionBody(functionNode);
2335         } finally {
2336             lc.pop(functionNode);
2337         }
2338 
2339         final FunctionNode  function = createFunctionNode(
2340                 functionNode,
2341                 getSetToken,
2342                 getNameNode,
2343                 Collections.<IdentNode>emptyList(),
2344                 FunctionNode.Kind.GETTER,
2345                 functionLine,
2346                 functionBody);
2347 
2348         return new PropertyFunction(getIdent, function);
2349     }
2350 
2351     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
2352         final PropertyKey setIdent = propertyName();
2353         final String setterName = setIdent.getPropertyName();
2354         final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
2355         expect(LPAREN);
2356         // be sloppy and allow missing setter parameter even though
2357         // spec does not permit it!
2358         final IdentNode argIdent;
2359         if (type == IDENT || isNonStrictModeIdent()) {
2360             argIdent = getIdent();
2361             verifyStrictIdent(argIdent, "setter argument");
2362         } else {
2363             argIdent = null;
2364         }
2365         expect(RPAREN);
2366         final List<IdentNode> parameters = new ArrayList<>();
2367         if (argIdent != null) {
2368             parameters.add(argIdent);
2369         }
2370 
2371 
2372         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
2373         lc.push(functionNode);
2374 
2375         Block functionBody;
2376         try {
2377             functionBody = functionBody(functionNode);
2378         } finally {
2379             lc.pop(functionNode);
2380         }
2381 
2382 
2383         final FunctionNode  function = createFunctionNode(
2384                 functionNode,
2385                 getSetToken,
2386                 setNameNode,
2387                 parameters,
2388                 FunctionNode.Kind.SETTER,
2389                 functionLine,
2390                 functionBody);
2391 
2392         return new PropertyFunction(setIdent, function);
2393     }
2394 
2395     private static class PropertyFunction {
2396         final PropertyKey ident;
2397         final FunctionNode functionNode;
2398 
2399         PropertyFunction(final PropertyKey ident, final FunctionNode function) {
2400             this.ident = ident;
2401             this.functionNode = function;
2402         }
2403     }
2404 
2405     /**
2406      * Parse left hand side expression.
2407      *
2408      * LeftHandSideExpression :
2409      *      NewExpression
2410      *      CallExpression
2411      *
2412      * CallExpression :
2413      *      MemberExpression Arguments
2414      *      CallExpression Arguments
2415      *      CallExpression [ Expression ]
2416      *      CallExpression . IdentifierName
2417      *      CallExpression TemplateLiteral
2418      *
2419      * @return Expression node.
2420      */
2421     private Expression leftHandSideExpression() {
2422         int  callLine  = line;
2423         long callToken = token;
2424 
2425         Expression lhs = memberExpression();
2426 
2427         if (type == LPAREN) {
2428             final List<Expression> arguments = optimizeList(argumentList());
2429 
2430             // Catch special functions.
2431             if (lhs instanceof IdentNode) {
2432                 detectSpecialFunction((IdentNode)lhs);
2433             }
2434 
2435             lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2436         }
2437 
2438 loop:
2439         while (true) {
2440             // Capture token.
2441             callLine  = line;
2442             callToken = token;
2443 
2444             switch (type) {
2445             case LPAREN: {
2446                 // Get NEW or FUNCTION arguments.
2447                 final List<Expression> arguments = optimizeList(argumentList());
2448 
2449                 // Create call node.
2450                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2451 
2452                 break;
2453             }
2454             case LBRACKET: {
2455                 next();
2456 
2457                 // Get array index.
2458                 final Expression rhs = expression();
2459 
2460                 expect(RBRACKET);
2461 
2462                 // Create indexing node.
2463                 lhs = new IndexNode(callToken, finish, lhs, rhs);
2464 
2465                 break;
2466             }
2467             case PERIOD: {
2468                 next();
2469 
2470                 final IdentNode property = getIdentifierName();
2471 
2472                 // Create property access node.
2473                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
2474 
2475                 break;
2476             }
2477             case TEMPLATE:
2478             case TEMPLATE_HEAD: {
2479                 // tagged template literal
2480                 final List<Expression> arguments = templateLiteralArgumentList();
2481 
2482                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2483 
2484                 break;
2485             }
2486             default:
2487                 break loop;
2488             }
2489         }
2490 
2491         return lhs;
2492     }
2493 
2494     /**
2495      * NewExpression :
2496      *      MemberExpression
2497      *      new NewExpression
2498      *
2499      * See 11.2
2500      *
2501      * Parse new expression.
2502      * @return Expression node.
2503      */
2504     private Expression newExpression() {
2505         final long newToken = token;
2506         // NEW is tested in caller.
2507         next();
2508 
2509         // Get function base.
2510         final int  callLine    = line;
2511         final Expression constructor = memberExpression();
2512         if (constructor == null) {
2513             return null;
2514         }
2515         // Get arguments.
2516         ArrayList<Expression> arguments;
2517 
2518         // Allow for missing arguments.
2519         if (type == LPAREN) {
2520             arguments = argumentList();
2521         } else {
2522             arguments = new ArrayList<>();
2523         }
2524 
2525         // Nashorn extension: This is to support the following interface implementation
2526         // syntax:
2527         //
2528         //     var r = new java.lang.Runnable() {
2529         //         run: function() { println("run"); }
2530         //     };
2531         //
2532         // The object literal following the "new Constructor()" expression
2533         // is passed as an additional (last) argument to the constructor.
2534         if (!env._no_syntax_extensions && type == LBRACE) {
2535             arguments.add(objectLiteral());
2536         }
2537 
2538         final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
2539 
2540         return new UnaryNode(newToken, callNode);
2541     }
2542 
2543     /**
2544      * Parse member expression.
2545      *
2546      * MemberExpression :
2547      *      PrimaryExpression
2548      *      FunctionExpression
2549      *      MemberExpression [ Expression ]
2550      *      MemberExpression . IdentifierName
2551      *      MemberExpression TemplateLiteral
2552      *      new MemberExpression Arguments
2553      *
2554      * @return Expression node.
2555      */
2556     private Expression memberExpression() {
2557         // Prepare to build operation.
2558         Expression lhs;
2559 
2560         switch (type) {
2561         case NEW:
2562             // Get new expression.
2563             lhs = newExpression();
2564             break;
2565 
2566         case FUNCTION:
2567             // Get function expression.
2568             lhs = functionExpression(false, false);
2569             break;
2570 
2571         default:
2572             // Get primary expression.
2573             lhs = primaryExpression();
2574             break;
2575         }
2576 
2577 loop:
2578         while (true) {
2579             // Capture token.
2580             final long callToken = token;
2581 
2582             switch (type) {
2583             case LBRACKET: {
2584                 next();
2585 
2586                 // Get array index.
2587                 final Expression index = expression();
2588 
2589                 expect(RBRACKET);
2590 
2591                 // Create indexing node.
2592                 lhs = new IndexNode(callToken, finish, lhs, index);
2593 
2594                 break;
2595             }
2596             case PERIOD: {
2597                 if (lhs == null) {
2598                     throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2599                 }
2600 
2601                 next();
2602 
2603                 final IdentNode property = getIdentifierName();
2604 
2605                 // Create property access node.
2606                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
2607 
2608                 break;
2609             }
2610             case TEMPLATE:
2611             case TEMPLATE_HEAD: {
2612                 // tagged template literal
2613                 final int callLine = line;
2614                 final List<Expression> arguments = templateLiteralArgumentList();
2615 
2616                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2617 
2618                 break;
2619             }
2620             default:
2621                 break loop;
2622             }
2623         }
2624 
2625         return lhs;
2626     }
2627 
2628     /**
2629      * Arguments :
2630      *      ( )
2631      *      ( ArgumentList )
2632      *
2633      * ArgumentList :
2634      *      AssignmentExpression
2635      *      ArgumentList , AssignmentExpression
2636      *
2637      * See 11.2
2638      *
2639      * Parse function call arguments.
2640      * @return Argument list.
2641      */
2642     private ArrayList<Expression> argumentList() {
2643         // Prepare to accumulate list of arguments.
2644         final ArrayList<Expression> nodeList = new ArrayList<>();
2645         // LPAREN tested in caller.
2646         next();
2647 
2648         // Track commas.
2649         boolean first = true;
2650 
2651         while (type != RPAREN) {
2652             // Comma prior to every argument except the first.
2653             if (!first) {
2654                 expect(COMMARIGHT);
2655             } else {
2656                 first = false;
2657             }
2658 
2659             // Get argument expression.
2660             nodeList.add(assignmentExpression(false));
2661         }
2662 
2663         expect(RPAREN);
2664         return nodeList;
2665     }
2666 
2667     private static <T> List<T> optimizeList(final ArrayList<T> list) {
2668         switch(list.size()) {
2669             case 0: {
2670                 return Collections.emptyList();
2671             }
2672             case 1: {
2673                 return Collections.singletonList(list.get(0));
2674             }
2675             default: {
2676                 list.trimToSize();
2677                 return list;
2678             }
2679         }
2680     }
2681 
2682     /**
2683      * FunctionDeclaration :
2684      *      function Identifier ( FormalParameterList? ) { FunctionBody }
2685      *
2686      * FunctionExpression :
2687      *      function Identifier? ( FormalParameterList? ) { FunctionBody }
2688      *
2689      * See 13
2690      *
2691      * Parse function declaration.
2692      * @param isStatement True if for is a statement.
2693      *
2694      * @return Expression node.
2695      */
2696     private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
2697         final long functionToken = token;
2698         final int  functionLine  = line;
2699         // FUNCTION is tested in caller.
2700         next();
2701 
2702         IdentNode name = null;
2703 
2704         if (type == IDENT || isNonStrictModeIdent()) {
2705             name = getIdent();
2706             verifyStrictIdent(name, "function name");
2707         } else if (isStatement) {
2708             // Nashorn extension: anonymous function statements.
2709             // Do not allow anonymous function statement if extensions
2710             // are now allowed. But if we are reparsing then anon function
2711             // statement is possible - because it was used as function
2712             // expression in surrounding code.
2713             if (env._no_syntax_extensions && reparsedFunction == null) {
2714                 expect(IDENT);
2715             }
2716         }
2717 
2718         // name is null, generate anonymous name
2719         boolean isAnonymous = false;
2720         if (name == null) {
2721             final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
2722             name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
2723             isAnonymous = true;
2724         }
2725 
2726         expect(LPAREN);
2727         final List<IdentNode> parameters = formalParameterList();
2728         expect(RPAREN);
2729 
2730         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters);
2731         lc.push(functionNode);
2732         Block functionBody = null;
2733         // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
2734         // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
2735         hideDefaultName();
2736         try{
2737             functionBody = functionBody(functionNode);
2738         } finally {
2739             defaultNames.pop();
2740             lc.pop(functionNode);
2741         }
2742 
2743         if (isStatement) {
2744             if (topLevel || useBlockScope()) {
2745                 functionNode.setFlag(FunctionNode.IS_DECLARED);
2746             } else if (isStrictMode) {
2747                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
2748             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
2749                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
2750             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
2751                 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
2752             }
2753             if (isArguments(name)) {
2754                lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
2755             }
2756         }
2757 
2758         if (isAnonymous) {
2759             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
2760         }
2761 
2762         final int arity = parameters.size();
2763 
2764         final boolean strict = functionNode.isStrict();
2765         if (arity > 1) {
2766             final HashSet<String> parametersSet = new HashSet<>(arity);
2767 
2768             for (int i = arity - 1; i >= 0; i--) {
2769                 final IdentNode parameter = parameters.get(i);
2770                 String parameterName = parameter.getName();
2771 
2772                 if (isArguments(parameterName)) {
2773                     functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2774                 }
2775 
2776                 if (parametersSet.contains(parameterName)) {
2777                     // redefinition of parameter name
2778                     if (strict) {
2779                         throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2780                     }
2781                     // rename in non-strict mode
2782                     parameterName = functionNode.uniqueName(parameterName);
2783                     final long parameterToken = parameter.getToken();
2784                     parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2785                 }
2786 
2787                 parametersSet.add(parameterName);
2788             }
2789         } else if (arity == 1) {
2790             if (isArguments(parameters.get(0))) {
2791                 functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2792             }
2793         }
2794 
2795         final FunctionNode function = createFunctionNode(
2796                 functionNode,
2797                 functionToken,
2798                 name,
2799                 parameters,
2800                 FunctionNode.Kind.NORMAL,
2801                 functionLine,
2802                 functionBody);
2803 
2804         if (isStatement) {
2805             if (isAnonymous) {
2806                 appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function));
2807                 return function;
2808             }
2809 
2810             // mark ES6 block functions as lexically scoped
2811             final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
2812             final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
2813             if (topLevel) {
2814                 functionDeclarations.add(varNode);
2815             } else if (useBlockScope()) {
2816                 prependStatement(varNode); // Hoist to beginning of current block
2817             } else {
2818                 appendStatement(varNode);
2819             }
2820         }
2821 
2822         return function;
2823     }
2824 
2825     private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
2826         final String defaultFunctionName = getDefaultFunctionName();
2827         if (isValidIdentifier(defaultFunctionName)) {
2828             if (isStatement) {
2829                 // The name will be used as the LHS of a symbol assignment. We add the anonymous function
2830                 // prefix to ensure that it can't clash with another variable.
2831                 return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
2832             }
2833             return defaultFunctionName;
2834         }
2835         return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2836     }
2837 
2838     private static boolean isValidIdentifier(final String name) {
2839         if(name == null || name.isEmpty()) {
2840             return false;
2841         }
2842         if(!Character.isJavaIdentifierStart(name.charAt(0))) {
2843             return false;
2844         }
2845         for(int i = 1; i < name.length(); ++i) {
2846             if(!Character.isJavaIdentifierPart(name.charAt(i))) {
2847                 return false;
2848             }
2849         }
2850         return true;
2851     }
2852 
2853     private String getDefaultFunctionName() {
2854         if(!defaultNames.isEmpty()) {
2855             final Object nameExpr = defaultNames.peek();
2856             if(nameExpr instanceof PropertyKey) {
2857                 markDefaultNameUsed();
2858                 return ((PropertyKey)nameExpr).getPropertyName();
2859             } else if(nameExpr instanceof AccessNode) {
2860                 markDefaultNameUsed();
2861                 return ((AccessNode)nameExpr).getProperty();
2862             }
2863         }
2864         return null;
2865     }
2866 
2867     private void markDefaultNameUsed() {
2868         defaultNames.pop();
2869         hideDefaultName();
2870     }
2871 
2872     private void hideDefaultName() {
2873         // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
2874         // from. Can't be null
2875         defaultNames.push("");
2876     }
2877 
2878     /**
2879      * FormalParameterList :
2880      *      Identifier
2881      *      FormalParameterList , Identifier
2882      *
2883      * See 13
2884      *
2885      * Parse function parameter list.
2886      * @return List of parameter nodes.
2887      */
2888     private List<IdentNode> formalParameterList() {
2889         return formalParameterList(RPAREN);
2890     }
2891 
2892     /**
2893      * Same as the other method of the same name - except that the end
2894      * token type expected is passed as argument to this method.
2895      *
2896      * FormalParameterList :
2897      *      Identifier
2898      *      FormalParameterList , Identifier
2899      *
2900      * See 13
2901      *
2902      * Parse function parameter list.
2903      * @return List of parameter nodes.
2904      */
2905     private List<IdentNode> formalParameterList(final TokenType endType) {
2906         // Prepare to gather parameters.
2907         final ArrayList<IdentNode> parameters = new ArrayList<>();
2908         // Track commas.
2909         boolean first = true;
2910 
2911         while (type != endType) {
2912             // Comma prior to every argument except the first.
2913             if (!first) {
2914                 expect(COMMARIGHT);
2915             } else {
2916                 first = false;
2917             }
2918 
2919             // Get and add parameter.
2920             final IdentNode ident = getIdent();
2921 
2922             // ECMA 13.1 strict mode restrictions
2923             verifyStrictIdent(ident, "function parameter");
2924 
2925             parameters.add(ident);
2926         }
2927 
2928         parameters.trimToSize();
2929         return parameters;
2930     }
2931 
2932     /**
2933      * FunctionBody :
2934      *      SourceElements?
2935      *
2936      * See 13
2937      *
2938      * Parse function body.
2939      * @return function node (body.)
2940      */
2941     private Block functionBody(final ParserContextFunctionNode functionNode) {
2942         long lastToken = 0L;
2943         ParserContextBlockNode body = null;
2944         final long bodyToken = token;
2945         Block functionBody;
2946         int bodyFinish = 0;
2947 
2948         final boolean parseBody;
2949         Object endParserState = null;
2950         try {
2951             // Create a new function block.
2952             body = newBlock();
2953             if (env._debug_scopes) {
2954                 // debug scope options forces everything to be in scope
2955                 markEval(lc);
2956             }
2957             assert functionNode != null;
2958             final int functionId = functionNode.getId();
2959             parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
2960             // Nashorn extension: expression closures
2961             if (!env._no_syntax_extensions && type != LBRACE) {
2962                 /*
2963                  * Example:
2964                  *
2965                  * function square(x) x * x;
2966                  * print(square(3));
2967                  */
2968 
2969                 // just expression as function body
2970                 final Expression expr = assignmentExpression(true);
2971                 lastToken = previousToken;
2972                 functionNode.setLastToken(previousToken);
2973                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
2974                 // EOL uses length field to store the line number
2975                 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
2976                 // Only create the return node if we aren't skipping nested functions. Note that we aren't
2977                 // skipping parsing of these extended functions; they're considered to be small anyway. Also,
2978                 // they don't end with a single well known token, so it'd be very hard to get correctly (see
2979                 // the note below for reasoning on skipping happening before instead of after RBRACE for
2980                 // details).
2981                 if (parseBody) {
2982                     final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
2983                     appendStatement(returnNode);
2984                 }
2985             } else {
2986                 expectDontAdvance(LBRACE);
2987                 if (parseBody || !skipFunctionBody(functionNode)) {
2988                     next();
2989                     // Gather the function elements.
2990                     final List<Statement> prevFunctionDecls = functionDeclarations;
2991                     functionDeclarations = new ArrayList<>();
2992                     try {
2993                         sourceElements(false);
2994                         addFunctionDeclarations(functionNode);
2995                     } finally {
2996                         functionDeclarations = prevFunctionDecls;
2997                     }
2998 
2999                     lastToken = token;
3000                     if (parseBody) {
3001                         // Since the lexer can read ahead and lexify some number of tokens in advance and have
3002                         // them buffered in the TokenStream, we need to produce a lexer state as it was just
3003                         // before it lexified RBRACE, and not whatever is its current (quite possibly well read
3004                         // ahead) state.
3005                         endParserState = new ParserState(Token.descPosition(token), line, linePosition);
3006 
3007                         // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
3008                         // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
3009                         // state after it. The reason is that RBRACE is a well-known token that we can expect and
3010                         // will never involve us getting into a weird lexer state, and as such is a great reparse
3011                         // point. Typical example of a weird lexer state after RBRACE would be:
3012                         //     function this_is_skipped() { ... } "use strict";
3013                         // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
3014                         // of compensating for the possibility of a string literal (or similar) after RBRACE,
3015                         // we'll rather just restart parsing from this well-known, friendly token instead.
3016                     }
3017                 }
3018                 bodyFinish = finish;
3019                 functionNode.setLastToken(token);
3020                 expect(RBRACE);
3021             }
3022         } finally {
3023             restoreBlock(body);
3024         }
3025 
3026         // NOTE: we can only do alterations to the function node after restoreFunctionNode.
3027 
3028         if (parseBody) {
3029             functionNode.setEndParserState(endParserState);
3030         } else if (!body.getStatements().isEmpty()){
3031             // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
3032             // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
3033             // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
3034             // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
3035             // nested bodies early if we were supposed to skip 'em.
3036             body.setStatements(Collections.<Statement>emptyList());
3037         }
3038 
3039         if (reparsedFunction != null) {
3040             // We restore the flags stored in the function's ScriptFunctionData that we got when we first
3041             // eagerly parsed the code. We're doing it because some flags would be set based on the
3042             // content of the function, or even content of its nested functions, most of which are normally
3043             // skipped during an on-demand compilation.
3044             final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
3045             if (data != null) {
3046                 // Data can be null if when we originally parsed the file, we removed the function declaration
3047                 // as it was dead code.
3048                 functionNode.setFlag(data.getFunctionFlags());
3049                 // This compensates for missing markEval() in case the function contains an inner function
3050                 // that contains eval(), that now we didn't discover since we skipped the inner function.
3051                 if (functionNode.hasNestedEval()) {
3052                     assert functionNode.hasScopeBlock();
3053                     body.setFlag(Block.NEEDS_SCOPE);
3054                 }
3055             }
3056         }
3057         functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements());
3058         return functionBody;
3059     }
3060 
3061     private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
3062         if (reparsedFunction == null) {
3063             // Not reparsing, so don't skip any function body.
3064             return false;
3065         }
3066         // Skip to the RBRACE of this function, and continue parsing from there.
3067         final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
3068         if (data == null) {
3069             // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
3070             // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
3071             // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
3072             return false;
3073         }
3074         final ParserState parserState = (ParserState)data.getEndParserState();
3075         assert parserState != null;
3076 
3077         if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) {
3078             // RBRACE is already in the token stream, so fast forward to it
3079             for (; k < stream.last(); k++) {
3080                 final long nextToken = stream.get(k + 1);
3081                 if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) {
3082                     token = stream.get(k);
3083                     type = Token.descType(token);
3084                     next();
3085                     assert type == RBRACE && start == parserState.position;
3086                     return true;
3087                 }
3088             }
3089         }
3090 
3091         stream.reset();
3092         lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
3093         line = parserState.line;
3094         linePosition = parserState.linePosition;
3095         // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
3096         // the RBRACE.
3097         type = SEMICOLON;
3098         k = -1;
3099         next();
3100 
3101         return true;
3102     }
3103 
3104     /**
3105      * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
3106      * for resuming parsing after skipping a function body.
3107      */
3108     private static class ParserState implements Serializable {
3109         private final int position;
3110         private final int line;
3111         private final int linePosition;
3112 
3113         private static final long serialVersionUID = -2382565130754093694L;
3114 
3115         ParserState(final int position, final int line, final int linePosition) {
3116             this.position = position;
3117             this.line = line;
3118             this.linePosition = linePosition;
3119         }
3120 
3121         Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
3122             final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
3123             newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
3124             return newLexer;
3125         }
3126     }
3127 
3128     private void printAST(final FunctionNode functionNode) {
3129         if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
3130             env.getErr().println(new ASTWriter(functionNode));
3131         }
3132 
3133         if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
3134             env.getErr().println(new PrintVisitor(functionNode, true, false));
3135         }
3136     }
3137 
3138     private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
3139         VarNode lastDecl = null;
3140         for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
3141             Statement decl = functionDeclarations.get(i);
3142             if (lastDecl == null && decl instanceof VarNode) {
3143                 decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
3144                 functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
3145             }
3146             prependStatement(decl);
3147         }
3148     }
3149 
3150     private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
3151         if (earlyError) {
3152             throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
3153         }
3154         final ArrayList<Expression> args = new ArrayList<>();
3155         args.add(lhs);
3156         if (rhs == null) {
3157             args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
3158         } else {
3159             args.add(rhs);
3160         }
3161         args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
3162         return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
3163     }
3164 
3165     /**
3166      * PostfixExpression :
3167      *      LeftHandSideExpression
3168      *      LeftHandSideExpression ++ // [no LineTerminator here]
3169      *      LeftHandSideExpression -- // [no LineTerminator here]
3170      *
3171      * See 11.3
3172      *
3173      * UnaryExpression :
3174      *      PostfixExpression
3175      *      delete UnaryExpression
3176      *      void UnaryExpression
3177      *      typeof UnaryExpression
3178      *      ++ UnaryExpression
3179      *      -- UnaryExpression
3180      *      + UnaryExpression
3181      *      - UnaryExpression
3182      *      ~ UnaryExpression
3183      *      ! UnaryExpression
3184      *
3185      * See 11.4
3186      *
3187      * Parse unary expression.
3188      * @return Expression node.
3189      */
3190     private Expression unaryExpression() {
3191         final int  unaryLine  = line;
3192         final long unaryToken = token;
3193 
3194         switch (type) {
3195         case DELETE: {
3196             next();
3197             final Expression expr = unaryExpression();
3198             if (expr instanceof BaseNode || expr instanceof IdentNode) {
3199                 return new UnaryNode(unaryToken, expr);
3200             }
3201             appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
3202             return LiteralNode.newInstance(unaryToken, finish, true);
3203         }
3204         case VOID:
3205         case TYPEOF:
3206         case ADD:
3207         case SUB:
3208         case BIT_NOT:
3209         case NOT:
3210             next();
3211             final Expression expr = unaryExpression();
3212             return new UnaryNode(unaryToken, expr);
3213 
3214         case INCPREFIX:
3215         case DECPREFIX:
3216             final TokenType opType = type;
3217             next();
3218 
3219             final Expression lhs = leftHandSideExpression();
3220             // ++, -- without operand..
3221             if (lhs == null) {
3222                 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3223             }
3224 
3225             if (!(lhs instanceof AccessNode ||
3226                   lhs instanceof IndexNode ||
3227                   lhs instanceof IdentNode)) {
3228                 return referenceError(lhs, null, env._early_lvalue_error);
3229             }
3230 
3231             if (lhs instanceof IdentNode) {
3232                 if (!checkIdentLValue((IdentNode)lhs)) {
3233                     return referenceError(lhs, null, false);
3234                 }
3235                 verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3236             }
3237 
3238             return incDecExpression(unaryToken, opType, lhs, false);
3239 
3240         default:
3241             break;
3242         }
3243 
3244         Expression expression = leftHandSideExpression();
3245 
3246         if (last != EOL) {
3247             switch (type) {
3248             case INCPREFIX:
3249             case DECPREFIX:
3250                 final TokenType opType = type;
3251                 final Expression lhs = expression;
3252                 // ++, -- without operand..
3253                 if (lhs == null) {
3254                     throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3255                 }
3256 
3257                 if (!(lhs instanceof AccessNode ||
3258                    lhs instanceof IndexNode ||
3259                    lhs instanceof IdentNode)) {
3260                     next();
3261                     return referenceError(lhs, null, env._early_lvalue_error);
3262                 }
3263                 if (lhs instanceof IdentNode) {
3264                     if (!checkIdentLValue((IdentNode)lhs)) {
3265                         next();
3266                         return referenceError(lhs, null, false);
3267                     }
3268                     verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3269                 }
3270                 expression = incDecExpression(token, type, expression, true);
3271                 next();
3272                 break;
3273             default:
3274                 break;
3275             }
3276         }
3277 
3278         if (expression == null) {
3279             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3280         }
3281 
3282         return expression;
3283     }
3284 
3285     /**
3286      * {@code
3287      * MultiplicativeExpression :
3288      *      UnaryExpression
3289      *      MultiplicativeExpression * UnaryExpression
3290      *      MultiplicativeExpression / UnaryExpression
3291      *      MultiplicativeExpression % UnaryExpression
3292      *
3293      * See 11.5
3294      *
3295      * AdditiveExpression :
3296      *      MultiplicativeExpression
3297      *      AdditiveExpression + MultiplicativeExpression
3298      *      AdditiveExpression - MultiplicativeExpression
3299      *
3300      * See 11.6
3301      *
3302      * ShiftExpression :
3303      *      AdditiveExpression
3304      *      ShiftExpression << AdditiveExpression
3305      *      ShiftExpression >> AdditiveExpression
3306      *      ShiftExpression >>> AdditiveExpression
3307      *
3308      * See 11.7
3309      *
3310      * RelationalExpression :
3311      *      ShiftExpression
3312      *      RelationalExpression < ShiftExpression
3313      *      RelationalExpression > ShiftExpression
3314      *      RelationalExpression <= ShiftExpression
3315      *      RelationalExpression >= ShiftExpression
3316      *      RelationalExpression instanceof ShiftExpression
3317      *      RelationalExpression in ShiftExpression // if !noIf
3318      *
3319      * See 11.8
3320      *
3321      *      RelationalExpression
3322      *      EqualityExpression == RelationalExpression
3323      *      EqualityExpression != RelationalExpression
3324      *      EqualityExpression === RelationalExpression
3325      *      EqualityExpression !== RelationalExpression
3326      *
3327      * See 11.9
3328      *
3329      * BitwiseANDExpression :
3330      *      EqualityExpression
3331      *      BitwiseANDExpression & EqualityExpression
3332      *
3333      * BitwiseXORExpression :
3334      *      BitwiseANDExpression
3335      *      BitwiseXORExpression ^ BitwiseANDExpression
3336      *
3337      * BitwiseORExpression :
3338      *      BitwiseXORExpression
3339      *      BitwiseORExpression | BitwiseXORExpression
3340      *
3341      * See 11.10
3342      *
3343      * LogicalANDExpression :
3344      *      BitwiseORExpression
3345      *      LogicalANDExpression && BitwiseORExpression
3346      *
3347      * LogicalORExpression :
3348      *      LogicalANDExpression
3349      *      LogicalORExpression || LogicalANDExpression
3350      *
3351      * See 11.11
3352      *
3353      * ConditionalExpression :
3354      *      LogicalORExpression
3355      *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
3356      *
3357      * See 11.12
3358      *
3359      * AssignmentExpression :
3360      *      ConditionalExpression
3361      *      LeftHandSideExpression AssignmentOperator AssignmentExpression
3362      *
3363      * AssignmentOperator :
3364      *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
3365      *
3366      * See 11.13
3367      *
3368      * Expression :
3369      *      AssignmentExpression
3370      *      Expression , AssignmentExpression
3371      *
3372      * See 11.14
3373      * }
3374      *
3375      * Parse expression.
3376      * @return Expression node.
3377      */
3378     protected Expression expression() {
3379         // This method is protected so that subclass can get details
3380         // at expression start point!
3381 
3382         // Include commas in expression parsing.
3383         return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
3384     }
3385 
3386     private JoinPredecessorExpression joinPredecessorExpression() {
3387         return new JoinPredecessorExpression(expression());
3388     }
3389 
3390     private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
3391         // Get the precedence of the next operator.
3392         int precedence = type.getPrecedence();
3393         Expression lhs = exprLhs;
3394 
3395         // While greater precedence.
3396         while (type.isOperator(noIn) && precedence >= minPrecedence) {
3397             // Capture the operator token.
3398             final long op = token;
3399 
3400             if (type == TERNARY) {
3401                 // Skip operator.
3402                 next();
3403 
3404                 // Pass expression. Middle expression of a conditional expression can be a "in"
3405                 // expression - even in the contexts where "in" is not permitted.
3406                 final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
3407 
3408                 expect(COLON);
3409 
3410                 // Fail expression.
3411                 final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3412 
3413                 // Build up node.
3414                 lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
3415             } else {
3416                 // Skip operator.
3417                 next();
3418 
3419                  // Get the next primary expression.
3420                 Expression rhs;
3421                 final boolean isAssign = Token.descType(op) == ASSIGN;
3422                 if(isAssign) {
3423                     defaultNames.push(lhs);
3424                 }
3425                 try {
3426                     rhs = unaryExpression();
3427                     // Get precedence of next operator.
3428                     int nextPrecedence = type.getPrecedence();
3429 
3430                     // Subtask greater precedence.
3431                     while (type.isOperator(noIn) &&
3432                            (nextPrecedence > precedence ||
3433                            nextPrecedence == precedence && !type.isLeftAssociative())) {
3434                         rhs = expression(rhs, nextPrecedence, noIn);
3435                         nextPrecedence = type.getPrecedence();
3436                     }
3437                 } finally {
3438                     if(isAssign) {
3439                         defaultNames.pop();
3440                     }
3441                 }
3442                 lhs = verifyAssignment(op, lhs, rhs);
3443             }
3444 
3445             precedence = type.getPrecedence();
3446         }
3447 
3448         return lhs;
3449     }
3450 
3451     protected Expression assignmentExpression(final boolean noIn) {
3452         // This method is protected so that subclass can get details
3453         // at assignment expression start point!
3454 
3455         // Exclude commas in expression parsing.
3456         return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3457     }
3458 
3459     /**
3460      * Parse an end of line.
3461      */
3462     private void endOfLine() {
3463         switch (type) {
3464         case SEMICOLON:
3465         case EOL:
3466             next();
3467             break;
3468         case RPAREN:
3469         case RBRACKET:
3470         case RBRACE:
3471         case EOF:
3472             break;
3473         default:
3474             if (last != EOL) {
3475                 expect(SEMICOLON);
3476             }
3477             break;
3478         }
3479     }
3480 
3481     /**
3482      * Parse untagged template literal as string concatenation.
3483      */
3484     private Expression templateLiteral() {
3485         assert type == TEMPLATE || type == TEMPLATE_HEAD;
3486         final boolean noSubstitutionTemplate = type == TEMPLATE;
3487         long lastLiteralToken = token;
3488         LiteralNode<?> literal = getLiteral();
3489         if (noSubstitutionTemplate) {
3490             return literal;
3491         }
3492 
3493         Expression concat = literal;
3494         TokenType lastLiteralType;
3495         do {
3496             final Expression expression = expression();
3497             if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
3498                 throw error(AbstractParser.message("unterminated.template.expression"), token);
3499             }
3500             concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression);
3501             lastLiteralType = type;
3502             lastLiteralToken = token;
3503             literal = getLiteral();
3504             concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal);
3505         } while (lastLiteralType == TEMPLATE_MIDDLE);
3506         return concat;
3507     }
3508 
3509     /**
3510      * Parse tagged template literal as argument list.
3511      * @return argument list for a tag function call (template object, ...substitutions)
3512      */
3513     private List<Expression> templateLiteralArgumentList() {
3514         assert type == TEMPLATE || type == TEMPLATE_HEAD;
3515         final ArrayList<Expression> argumentList = new ArrayList<>();
3516         final ArrayList<Expression> rawStrings = new ArrayList<>();
3517         final ArrayList<Expression> cookedStrings = new ArrayList<>();
3518         argumentList.add(null); // filled at the end
3519 
3520         final long templateToken = token;
3521         final boolean hasSubstitutions = type == TEMPLATE_HEAD;
3522         addTemplateLiteralString(rawStrings, cookedStrings);
3523 
3524         if (hasSubstitutions) {
3525             TokenType lastLiteralType;
3526             do {
3527                 final Expression expression = expression();
3528                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
3529                     throw error(AbstractParser.message("unterminated.template.expression"), token);
3530                 }
3531                 argumentList.add(expression);
3532 
3533                 lastLiteralType = type;
3534                 addTemplateLiteralString(rawStrings, cookedStrings);
3535             } while (lastLiteralType == TEMPLATE_MIDDLE);
3536         }
3537 
3538         final LiteralNode<Expression[]> rawStringArray = LiteralNode.newInstance(templateToken, finish, rawStrings);
3539         final LiteralNode<Expression[]> cookedStringArray = LiteralNode.newInstance(templateToken, finish, cookedStrings);
3540         final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray);
3541         argumentList.set(0, templateObject);
3542         return optimizeList(argumentList);
3543     }
3544 
3545     private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) {
3546         final long stringToken = token;
3547         final String rawString = lexer.valueOfRawString(stringToken);
3548         final String cookedString = (String) getValue();
3549         next();
3550         rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString));
3551         cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
3552     }
3553 
3554     @Override
3555     public String toString() {
3556         return "'JavaScript Parsing'";
3557     }
3558 
3559     private static void markEval(final ParserContext lc) {
3560         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
3561         boolean flaggedCurrentFn = false;
3562         while (iter.hasNext()) {
3563             final ParserContextFunctionNode fn = iter.next();
3564             if (!flaggedCurrentFn) {
3565                 fn.setFlag(FunctionNode.HAS_EVAL);
3566                 flaggedCurrentFn = true;
3567             } else {
3568                 fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
3569             }
3570             final ParserContextBlockNode body = lc.getFunctionBody(fn);
3571             // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
3572             // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
3573             // this method when the parser skips a nested function.
3574             body.setFlag(Block.NEEDS_SCOPE);
3575             fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
3576         }
3577     }
3578 
3579     private void prependStatement(final Statement statement) {
3580         lc.prependStatementToCurrentNode(statement);
3581     }
3582 
3583     private void appendStatement(final Statement statement) {
3584         lc.appendStatementToCurrentNode(statement);
3585     }
3586 }