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