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