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