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