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