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