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