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