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