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