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