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