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