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             // Do not allow anonymous function statement if extensions
2673             // are now allowed. But if we are reparsing then anon function
2674             // statement is possible - because it was used as function
2675             // expression in surrounding code.
2676             if (env._no_syntax_extensions && reparsedFunction == null) {
2677                 expect(IDENT);
2678             }
2679         }
2680 
2681         // name is null, generate anonymous name
2682         boolean isAnonymous = false;
2683         if (name == null) {
2684             final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
2685             name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
2686             isAnonymous = true;
2687         }
2688 
2689         expect(LPAREN);
2690         final List<IdentNode> parameters = formalParameterList();
2691         expect(RPAREN);
2692 
2693         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters);
2694         lc.push(functionNode);
2695         Block functionBody = null;
2696         // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
2697         // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
2698         hideDefaultName();
2699         try{
2700             functionBody = functionBody(functionNode);
2701         } finally {
2702             defaultNames.pop();
2703             lc.pop(functionNode);
2704         }
2705 
2706         if (isStatement) {
2707             if (topLevel || useBlockScope()) {
2708                 functionNode.setFlag(FunctionNode.IS_DECLARED);
2709             } else if (isStrictMode) {
2710                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
2711             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
2712                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
2713             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
2714                 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
2715             }
2716             if (isArguments(name)) {
2717                lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
2718             }
2719         }
2720 
2721         if (isAnonymous) {
2722             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
2723         }
2724 
2725         final int arity = parameters.size();
2726 
2727         final boolean strict = functionNode.isStrict();
2728         if (arity > 1) {
2729             final HashSet<String> parametersSet = new HashSet<>(arity);
2730 
2731             for (int i = arity - 1; i >= 0; i--) {
2732                 final IdentNode parameter = parameters.get(i);
2733                 String parameterName = parameter.getName();
2734 
2735                 if (isArguments(parameterName)) {
2736                     functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2737                 }
2738 
2739                 if (parametersSet.contains(parameterName)) {
2740                     // redefinition of parameter name
2741                     if (strict) {
2742                         throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2743                     }
2744                     // rename in non-strict mode
2745                     parameterName = functionNode.uniqueName(parameterName);
2746                     final long parameterToken = parameter.getToken();
2747                     parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2748                 }
2749 
2750                 parametersSet.add(parameterName);
2751             }
2752         } else if (arity == 1) {
2753             if (isArguments(parameters.get(0))) {
2754                 functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2755             }
2756         }
2757 
2758         final FunctionNode function = createFunctionNode(
2759                 functionNode,
2760                 functionToken,
2761                 name,
2762                 parameters,
2763                 FunctionNode.Kind.NORMAL,
2764                 functionLine,
2765                 functionBody);
2766 
2767         if (isStatement) {
2768             // mark ES6 block functions as lexically scoped
2769             final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
2770             final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
2771             if (topLevel) {
2772                 functionDeclarations.add(varNode);
2773             } else if (useBlockScope()) {
2774                 prependStatement(varNode); // Hoist to beginning of current block
2775             } else {
2776                 appendStatement(varNode);
2777             }
2778         }
2779 
2780         return function;
2781     }
2782 
2783     private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
2784         final String defaultFunctionName = getDefaultFunctionName();
2785         if (isValidIdentifier(defaultFunctionName)) {
2786             if (isStatement) {
2787                 // The name will be used as the LHS of a symbol assignment. We add the anonymous function
2788                 // prefix to ensure that it can't clash with another variable.
2789                 return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
2790             }
2791             return defaultFunctionName;
2792         }
2793         return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2794     }
2795 
2796     private static boolean isValidIdentifier(final String name) {
2797         if(name == null || name.isEmpty()) {
2798             return false;
2799         }
2800         if(!Character.isJavaIdentifierStart(name.charAt(0))) {
2801             return false;
2802         }
2803         for(int i = 1; i < name.length(); ++i) {
2804             if(!Character.isJavaIdentifierPart(name.charAt(i))) {
2805                 return false;
2806             }
2807         }
2808         return true;
2809     }
2810 
2811     private String getDefaultFunctionName() {
2812         if(!defaultNames.isEmpty()) {
2813             final Object nameExpr = defaultNames.peek();
2814             if(nameExpr instanceof PropertyKey) {
2815                 markDefaultNameUsed();
2816                 return ((PropertyKey)nameExpr).getPropertyName();
2817             } else if(nameExpr instanceof AccessNode) {
2818                 markDefaultNameUsed();
2819                 return ((AccessNode)nameExpr).getProperty();
2820             }
2821         }
2822         return null;
2823     }
2824 
2825     private void markDefaultNameUsed() {
2826         defaultNames.pop();
2827         hideDefaultName();
2828     }
2829 
2830     private void hideDefaultName() {
2831         // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
2832         // from. Can't be null
2833         defaultNames.push("");
2834     }
2835 
2836     /**
2837      * FormalParameterList :
2838      *      Identifier
2839      *      FormalParameterList , Identifier
2840      *
2841      * See 13
2842      *
2843      * Parse function parameter list.
2844      * @return List of parameter nodes.
2845      */
2846     private List<IdentNode> formalParameterList() {
2847         return formalParameterList(RPAREN);
2848     }
2849 
2850     /**
2851      * Same as the other method of the same name - except that the end
2852      * token type expected is passed as argument to this method.
2853      *
2854      * FormalParameterList :
2855      *      Identifier
2856      *      FormalParameterList , Identifier
2857      *
2858      * See 13
2859      *
2860      * Parse function parameter list.
2861      * @return List of parameter nodes.
2862      */
2863     private List<IdentNode> formalParameterList(final TokenType endType) {
2864         // Prepare to gather parameters.
2865         final ArrayList<IdentNode> parameters = new ArrayList<>();
2866         // Track commas.
2867         boolean first = true;
2868 
2869         while (type != endType) {
2870             // Comma prior to every argument except the first.
2871             if (!first) {
2872                 expect(COMMARIGHT);
2873             } else {
2874                 first = false;
2875             }
2876 
2877             // Get and add parameter.
2878             final IdentNode ident = getIdent();
2879 
2880             // ECMA 13.1 strict mode restrictions
2881             verifyStrictIdent(ident, "function parameter");
2882 
2883             parameters.add(ident);
2884         }
2885 
2886         parameters.trimToSize();
2887         return parameters;
2888     }
2889 
2890     /**
2891      * FunctionBody :
2892      *      SourceElements?
2893      *
2894      * See 13
2895      *
2896      * Parse function body.
2897      * @return function node (body.)
2898      */
2899     private Block functionBody(final ParserContextFunctionNode functionNode) {
2900         long lastToken = 0L;
2901         ParserContextBlockNode body = null;
2902         final long bodyToken = token;
2903         Block functionBody;
2904         int bodyFinish = 0;
2905 
2906         final boolean parseBody;
2907         Object endParserState = null;
2908         try {
2909             // Create a new function block.
2910             body = newBlock();
2911             assert functionNode != null;
2912             final int functionId = functionNode.getId();
2913             parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
2914             // Nashorn extension: expression closures
2915             if (!env._no_syntax_extensions && type != LBRACE) {
2916                 /*
2917                  * Example:
2918                  *
2919                  * function square(x) x * x;
2920                  * print(square(3));
2921                  */
2922 
2923                 // just expression as function body
2924                 final Expression expr = assignmentExpression(true);
2925                 lastToken = previousToken;
2926                 functionNode.setLastToken(previousToken);
2927                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
2928                 // EOL uses length field to store the line number
2929                 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
2930                 // Only create the return node if we aren't skipping nested functions. Note that we aren't
2931                 // skipping parsing of these extended functions; they're considered to be small anyway. Also,
2932                 // they don't end with a single well known token, so it'd be very hard to get correctly (see
2933                 // the note below for reasoning on skipping happening before instead of after RBRACE for
2934                 // details).
2935                 if (parseBody) {
2936                     final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
2937                     appendStatement(returnNode);
2938                 }
2939             } else {
2940                 expectDontAdvance(LBRACE);
2941                 if (parseBody || !skipFunctionBody(functionNode)) {
2942                     next();
2943                     // Gather the function elements.
2944                     final List<Statement> prevFunctionDecls = functionDeclarations;
2945                     functionDeclarations = new ArrayList<>();
2946                     try {
2947                         sourceElements(false);
2948                         addFunctionDeclarations(functionNode);
2949                     } finally {
2950                         functionDeclarations = prevFunctionDecls;
2951                     }
2952 
2953                     lastToken = token;
2954                     if (parseBody) {
2955                         // Since the lexer can read ahead and lexify some number of tokens in advance and have
2956                         // them buffered in the TokenStream, we need to produce a lexer state as it was just
2957                         // before it lexified RBRACE, and not whatever is its current (quite possibly well read
2958                         // ahead) state.
2959                         endParserState = new ParserState(Token.descPosition(token), line, linePosition);
2960 
2961                         // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
2962                         // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
2963                         // state after it. The reason is that RBRACE is a well-known token that we can expect and
2964                         // will never involve us getting into a weird lexer state, and as such is a great reparse
2965                         // point. Typical example of a weird lexer state after RBRACE would be:
2966                         //     function this_is_skipped() { ... } "use strict";
2967                         // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
2968                         // of compensating for the possibility of a string literal (or similar) after RBRACE,
2969                         // we'll rather just restart parsing from this well-known, friendly token instead.
2970                     }
2971                 }
2972                 bodyFinish = finish;
2973                 functionNode.setLastToken(token);
2974                 expect(RBRACE);
2975             }
2976         } finally {
2977             restoreBlock(body);
2978         }
2979 
2980         // NOTE: we can only do alterations to the function node after restoreFunctionNode.
2981 
2982         if (parseBody) {
2983             functionNode.setEndParserState(endParserState);
2984         } else if (!body.getStatements().isEmpty()){
2985             // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
2986             // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
2987             // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
2988             // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
2989             // nested bodies early if we were supposed to skip 'em.
2990             body.setStatements(Collections.<Statement>emptyList());
2991         }
2992 
2993         if (reparsedFunction != null) {
2994             // We restore the flags stored in the function's ScriptFunctionData that we got when we first
2995             // eagerly parsed the code. We're doing it because some flags would be set based on the
2996             // content of the function, or even content of its nested functions, most of which are normally
2997             // skipped during an on-demand compilation.
2998             final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
2999             if (data != null) {
3000                 // Data can be null if when we originally parsed the file, we removed the function declaration
3001                 // as it was dead code.
3002                 functionNode.setFlag(data.getFunctionFlags());
3003                 // This compensates for missing markEval() in case the function contains an inner function
3004                 // that contains eval(), that now we didn't discover since we skipped the inner function.
3005                 if (functionNode.hasNestedEval()) {
3006                     assert functionNode.hasScopeBlock();
3007                     body.setFlag(Block.NEEDS_SCOPE);
3008                 }
3009             }
3010         }
3011         functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements());
3012         return functionBody;
3013     }
3014 
3015     private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
3016         if (reparsedFunction == null) {
3017             // Not reparsing, so don't skip any function body.
3018             return false;
3019         }
3020         // Skip to the RBRACE of this function, and continue parsing from there.
3021         final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
3022         if (data == null) {
3023             // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
3024             // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
3025             // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
3026             return false;
3027         }
3028         final ParserState parserState = (ParserState)data.getEndParserState();
3029         assert parserState != null;
3030 
3031         stream.reset();
3032         lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions);
3033         line = parserState.line;
3034         linePosition = parserState.linePosition;
3035         // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
3036         // the RBRACE.
3037         type = SEMICOLON;
3038         k = -1;
3039         next();
3040 
3041         return true;
3042     }
3043 
3044     /**
3045      * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
3046      * for resuming parsing after skipping a function body.
3047      */
3048     private static class ParserState implements Serializable {
3049         private final int position;
3050         private final int line;
3051         private final int linePosition;
3052 
3053         private static final long serialVersionUID = -2382565130754093694L;
3054 
3055         ParserState(final int position, final int line, final int linePosition) {
3056             this.position = position;
3057             this.line = line;
3058             this.linePosition = linePosition;
3059         }
3060 
3061         Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting) {
3062             final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, true);
3063             newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
3064             return newLexer;
3065         }
3066     }
3067 
3068     private void printAST(final FunctionNode functionNode) {
3069         if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
3070             env.getErr().println(new ASTWriter(functionNode));
3071         }
3072 
3073         if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
3074             env.getErr().println(new PrintVisitor(functionNode, true, false));
3075         }
3076     }
3077 
3078     private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
3079         VarNode lastDecl = null;
3080         for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
3081             Statement decl = functionDeclarations.get(i);
3082             if (lastDecl == null && decl instanceof VarNode) {
3083                 decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
3084                 functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
3085             }
3086             prependStatement(decl);
3087         }
3088     }
3089 
3090     private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
3091         if (earlyError) {
3092             throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
3093         }
3094         final ArrayList<Expression> args = new ArrayList<>();
3095         args.add(lhs);
3096         if (rhs == null) {
3097             args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
3098         } else {
3099             args.add(rhs);
3100         }
3101         args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
3102         return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
3103     }
3104 
3105     /*
3106      * parse LHS [a, b, ..., c].
3107      *
3108      * JavaScript 1.8.
3109      */
3110     //private Node destructureExpression() {
3111     //    return null;
3112     //}
3113 
3114     /**
3115      * PostfixExpression :
3116      *      LeftHandSideExpression
3117      *      LeftHandSideExpression ++ // [no LineTerminator here]
3118      *      LeftHandSideExpression -- // [no LineTerminator here]
3119      *
3120      * See 11.3
3121      *
3122      * UnaryExpression :
3123      *      PostfixExpression
3124      *      delete UnaryExpression
3125      *      Node UnaryExpression
3126      *      typeof UnaryExpression
3127      *      ++ UnaryExpression
3128      *      -- UnaryExpression
3129      *      + UnaryExpression
3130      *      - UnaryExpression
3131      *      ~ UnaryExpression
3132      *      ! UnaryExpression
3133      *
3134      * See 11.4
3135      *
3136      * Parse unary expression.
3137      * @return Expression node.
3138      */
3139     private Expression unaryExpression() {
3140         final int  unaryLine  = line;
3141         final long unaryToken = token;
3142 
3143         switch (type) {
3144         case DELETE: {
3145             next();
3146             final Expression expr = unaryExpression();
3147             if (expr instanceof BaseNode || expr instanceof IdentNode) {
3148                 return new UnaryNode(unaryToken, expr);
3149             }
3150             appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
3151             return LiteralNode.newInstance(unaryToken, finish, true);
3152         }
3153         case VOID:
3154         case TYPEOF:
3155         case ADD:
3156         case SUB:
3157         case BIT_NOT:
3158         case NOT:
3159             next();
3160             final Expression expr = unaryExpression();
3161             return new UnaryNode(unaryToken, expr);
3162 
3163         case INCPREFIX:
3164         case DECPREFIX:
3165             final TokenType opType = type;
3166             next();
3167 
3168             final Expression lhs = leftHandSideExpression();
3169             // ++, -- without operand..
3170             if (lhs == null) {
3171                 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3172             }
3173 
3174             if (!(lhs instanceof AccessNode ||
3175                   lhs instanceof IndexNode ||
3176                   lhs instanceof IdentNode)) {
3177                 return referenceError(lhs, null, env._early_lvalue_error);
3178             }
3179 
3180             if (lhs instanceof IdentNode) {
3181                 if (!checkIdentLValue((IdentNode)lhs)) {
3182                     return referenceError(lhs, null, false);
3183                 }
3184                 verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3185             }
3186 
3187             return incDecExpression(unaryToken, opType, lhs, false);
3188 
3189         default:
3190             break;
3191         }
3192 
3193         Expression expression = leftHandSideExpression();
3194 
3195         if (last != EOL) {
3196             switch (type) {
3197             case INCPREFIX:
3198             case DECPREFIX:
3199                 final TokenType opType = type;
3200                 final Expression lhs = expression;
3201                 // ++, -- without operand..
3202                 if (lhs == null) {
3203                     throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3204                 }
3205 
3206                 if (!(lhs instanceof AccessNode ||
3207                    lhs instanceof IndexNode ||
3208                    lhs instanceof IdentNode)) {
3209                     next();
3210                     return referenceError(lhs, null, env._early_lvalue_error);
3211                 }
3212                 if (lhs instanceof IdentNode) {
3213                     if (!checkIdentLValue((IdentNode)lhs)) {
3214                         next();
3215                         return referenceError(lhs, null, false);
3216                     }
3217                     verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3218                 }
3219                 expression = incDecExpression(token, type, expression, true);
3220                 next();
3221                 break;
3222             default:
3223                 break;
3224             }
3225         }
3226 
3227         if (expression == null) {
3228             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3229         }
3230 
3231         return expression;
3232     }
3233 
3234     /**
3235      * MultiplicativeExpression :
3236      *      UnaryExpression
3237      *      MultiplicativeExpression * UnaryExpression
3238      *      MultiplicativeExpression / UnaryExpression
3239      *      MultiplicativeExpression % UnaryExpression
3240      *
3241      * See 11.5
3242      *
3243      * AdditiveExpression :
3244      *      MultiplicativeExpression
3245      *      AdditiveExpression + MultiplicativeExpression
3246      *      AdditiveExpression - MultiplicativeExpression
3247      *
3248      * See 11.6
3249      *
3250      * ShiftExpression :
3251      *      AdditiveExpression
3252      *      ShiftExpression << AdditiveExpression
3253      *      ShiftExpression >> AdditiveExpression
3254      *      ShiftExpression >>> AdditiveExpression
3255      *
3256      * See 11.7
3257      *
3258      * RelationalExpression :
3259      *      ShiftExpression
3260      *      RelationalExpression < ShiftExpression
3261      *      RelationalExpression > ShiftExpression
3262      *      RelationalExpression <= ShiftExpression
3263      *      RelationalExpression >= ShiftExpression
3264      *      RelationalExpression instanceof ShiftExpression
3265      *      RelationalExpression in ShiftExpression // if !noIf
3266      *
3267      * See 11.8
3268      *
3269      *      RelationalExpression
3270      *      EqualityExpression == RelationalExpression
3271      *      EqualityExpression != RelationalExpression
3272      *      EqualityExpression === RelationalExpression
3273      *      EqualityExpression !== RelationalExpression
3274      *
3275      * See 11.9
3276      *
3277      * BitwiseANDExpression :
3278      *      EqualityExpression
3279      *      BitwiseANDExpression & EqualityExpression
3280      *
3281      * BitwiseXORExpression :
3282      *      BitwiseANDExpression
3283      *      BitwiseXORExpression ^ BitwiseANDExpression
3284      *
3285      * BitwiseORExpression :
3286      *      BitwiseXORExpression
3287      *      BitwiseORExpression | BitwiseXORExpression
3288      *
3289      * See 11.10
3290      *
3291      * LogicalANDExpression :
3292      *      BitwiseORExpression
3293      *      LogicalANDExpression && BitwiseORExpression
3294      *
3295      * LogicalORExpression :
3296      *      LogicalANDExpression
3297      *      LogicalORExpression || LogicalANDExpression
3298      *
3299      * See 11.11
3300      *
3301      * ConditionalExpression :
3302      *      LogicalORExpression
3303      *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
3304      *
3305      * See 11.12
3306      *
3307      * AssignmentExpression :
3308      *      ConditionalExpression
3309      *      LeftHandSideExpression AssignmentOperator AssignmentExpression
3310      *
3311      * AssignmentOperator :
3312      *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
3313      *
3314      * See 11.13
3315      *
3316      * Expression :
3317      *      AssignmentExpression
3318      *      Expression , AssignmentExpression
3319      *
3320      * See 11.14
3321      *
3322      * Parse expression.
3323      * @return Expression node.
3324      */
3325     private Expression expression() {
3326         // TODO - Destructuring array.
3327         // Include commas in expression parsing.
3328         return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
3329     }
3330 
3331     private JoinPredecessorExpression joinPredecessorExpression() {
3332         return new JoinPredecessorExpression(expression());
3333     }
3334 
3335     private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
3336         // Get the precedence of the next operator.
3337         int precedence = type.getPrecedence();
3338         Expression lhs = exprLhs;
3339 
3340         // While greater precedence.
3341         while (type.isOperator(noIn) && precedence >= minPrecedence) {
3342             // Capture the operator token.
3343             final long op = token;
3344 
3345             if (type == TERNARY) {
3346                 // Skip operator.
3347                 next();
3348 
3349                 // Pass expression. Middle expression of a conditional expression can be a "in"
3350                 // expression - even in the contexts where "in" is not permitted.
3351                 final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
3352 
3353                 expect(COLON);
3354 
3355                 // Fail expression.
3356                 final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3357 
3358                 // Build up node.
3359                 lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
3360             } else {
3361                 // Skip operator.
3362                 next();
3363 
3364                  // Get the next primary expression.
3365                 Expression rhs;
3366                 final boolean isAssign = Token.descType(op) == ASSIGN;
3367                 if(isAssign) {
3368                     defaultNames.push(lhs);
3369                 }
3370                 try {
3371                     rhs = unaryExpression();
3372                     // Get precedence of next operator.
3373                     int nextPrecedence = type.getPrecedence();
3374 
3375                     // Subtask greater precedence.
3376                     while (type.isOperator(noIn) &&
3377                            (nextPrecedence > precedence ||
3378                            nextPrecedence == precedence && !type.isLeftAssociative())) {
3379                         rhs = expression(rhs, nextPrecedence, noIn);
3380                         nextPrecedence = type.getPrecedence();
3381                     }
3382                 } finally {
3383                     if(isAssign) {
3384                         defaultNames.pop();
3385                     }
3386                 }
3387                 lhs = verifyAssignment(op, lhs, rhs);
3388             }
3389 
3390             precedence = type.getPrecedence();
3391         }
3392 
3393         return lhs;
3394     }
3395 
3396     private Expression assignmentExpression(final boolean noIn) {
3397         // TODO - Handle decompose.
3398         // Exclude commas in expression parsing.
3399         return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3400     }
3401 
3402     /**
3403      * Parse an end of line.
3404      */
3405     private void endOfLine() {
3406         switch (type) {
3407         case SEMICOLON:
3408         case EOL:
3409             next();
3410             break;
3411         case RPAREN:
3412         case RBRACKET:
3413         case RBRACE:
3414         case EOF:
3415             break;
3416         default:
3417             if (last != EOL) {
3418                 expect(SEMICOLON);
3419             }
3420             break;
3421         }
3422     }
3423 
3424     @Override
3425     public String toString() {
3426         return "'JavaScript Parsing'";
3427     }
3428 
3429     private static void markEval(final ParserContext lc) {
3430         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
3431         boolean flaggedCurrentFn = false;
3432         while (iter.hasNext()) {
3433             final ParserContextFunctionNode fn = iter.next();
3434             if (!flaggedCurrentFn) {
3435                 fn.setFlag(FunctionNode.HAS_EVAL);
3436                 flaggedCurrentFn = true;
3437             } else {
3438                 fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
3439             }
3440             final ParserContextBlockNode body = lc.getFunctionBody(fn);
3441             // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
3442             // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
3443             // this method when the parser skips a nested function.
3444             body.setFlag(Block.NEEDS_SCOPE);
3445             fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
3446         }
3447     }
3448 
3449     private void prependStatement(final Statement statement) {
3450         lc.prependStatementToCurrentNode(statement);
3451     }
3452 
3453     private void appendStatement(final Statement statement) {
3454         lc.appendStatementToCurrentNode(statement);
3455     }
3456 }