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, Token.descPosition(Token.withDelimiter(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      * Directive value or null if statement is not a directive.
 715      *
 716      * @param stmt Statement to be checked
 717      * @return Directive value if the given statement is a directive
 718      */
 719     private String getDirective(final Node stmt) {
 720         if (stmt instanceof ExpressionStatement) {
 721             final Node expr = ((ExpressionStatement)stmt).getExpression();
 722             if (expr instanceof LiteralNode) {
 723                 final LiteralNode<?> lit = (LiteralNode<?>)expr;
 724                 final long litToken = lit.getToken();
 725                 final TokenType tt = Token.descType(litToken);
 726                 // A directive is either a string or an escape string
 727                 if (tt == TokenType.STRING || tt == TokenType.ESCSTRING) {
 728                     // Make sure that we don't unescape anything. Return as seen in source!
 729                     return source.getString(lit.getStart(), Token.descLength(litToken));
 730                 }
 731             }
 732         }
 733 
 734         return null;
 735     }
 736 
 737     /**
 738      * SourceElements :
 739      *      SourceElement
 740      *      SourceElements SourceElement
 741      *
 742      * See 14
 743      *
 744      * Parse the elements of the script or function.
 745      */
 746     private void sourceElements(final boolean shouldAllowPropertyFunction) {
 747         List<Node>    directiveStmts        = null;
 748         boolean       checkDirective        = true;
 749         boolean       allowPropertyFunction = shouldAllowPropertyFunction;
 750         final boolean oldStrictMode         = isStrictMode;
 751 
 752 
 753         try {
 754             // If is a script, then process until the end of the script.
 755             while (type != EOF) {
 756                 // Break if the end of a code block.
 757                 if (type == RBRACE) {
 758                     break;
 759                 }
 760 
 761                 try {
 762                     // Get the next element.
 763                     statement(true, allowPropertyFunction);
 764                     allowPropertyFunction = false;
 765 
 766                     // check for directive prologues
 767                     if (checkDirective) {
 768                         // skip any debug statement like line number to get actual first line
 769                         final Node lastStatement = lc.getLastStatement();
 770 
 771                         // get directive prologue, if any
 772                         final String directive = getDirective(lastStatement);
 773 
 774                         // If we have seen first non-directive statement,
 775                         // no more directive statements!!
 776                         checkDirective = directive != null;
 777 
 778                         if (checkDirective) {
 779                             if (!oldStrictMode) {
 780                                 if (directiveStmts == null) {
 781                                     directiveStmts = new ArrayList<>();
 782                                 }
 783                                 directiveStmts.add(lastStatement);
 784                             }
 785 
 786                             // handle use strict directive
 787                             if ("use strict".equals(directive)) {
 788                                 isStrictMode = true;
 789                                 final FunctionNode function = lc.getCurrentFunction();
 790                                 lc.setFlag(lc.getCurrentFunction(), FunctionNode.IS_STRICT);
 791 
 792                                 // We don't need to check these, if lexical environment is already strict
 793                                 if (!oldStrictMode && directiveStmts != null) {
 794                                     // check that directives preceding this one do not violate strictness
 795                                     for (final Node statement : directiveStmts) {
 796                                         // the get value will force unescape of preceeding
 797                                         // escaped string directives
 798                                         getValue(statement.getToken());
 799                                     }
 800 
 801                                     // verify that function name as well as parameter names
 802                                     // satisfy strict mode restrictions.
 803                                     verifyStrictIdent(function.getIdent(), "function name");
 804                                     for (final IdentNode param : function.getParameters()) {
 805                                         verifyStrictIdent(param, "function parameter");
 806                                     }
 807                                 }
 808                             }
 809                         }
 810                     }
 811                 } catch (final Exception e) {
 812                     //recover parsing
 813                     recover(e);
 814                 }
 815 
 816                 // No backtracking from here on.
 817                 stream.commit(k);
 818             }
 819         } finally {
 820             isStrictMode = oldStrictMode;
 821         }
 822     }
 823 
 824     /**
 825      * Statement :
 826      *      Block
 827      *      VariableStatement
 828      *      EmptyStatement
 829      *      ExpressionStatement
 830      *      IfStatement
 831      *      IterationStatement
 832      *      ContinueStatement
 833      *      BreakStatement
 834      *      ReturnStatement
 835      *      WithStatement
 836      *      LabelledStatement
 837      *      SwitchStatement
 838      *      ThrowStatement
 839      *      TryStatement
 840      *      DebuggerStatement
 841      *
 842      * see 12
 843      *
 844      * Parse any of the basic statement types.
 845      */
 846     private void statement() {
 847         statement(false, false);
 848     }
 849 
 850     /**
 851      * @param topLevel does this statement occur at the "top level" of a script or a function?
 852      */
 853     private void statement(final boolean topLevel, final boolean allowPropertyFunction) {
 854         if (type == FUNCTION) {
 855             // As per spec (ECMA section 12), function declarations as arbitrary statement
 856             // is not "portable". Implementation can issue a warning or disallow the same.
 857             functionExpression(true, topLevel);
 858             return;
 859         }
 860 
 861         switch (type) {
 862         case LBRACE:
 863             block();
 864             break;
 865         case VAR:
 866             variableStatement(true);
 867             break;
 868         case SEMICOLON:
 869             emptyStatement();
 870             break;
 871         case IF:
 872             ifStatement();
 873             break;
 874         case FOR:
 875             forStatement();
 876             break;
 877         case WHILE:
 878             whileStatement();
 879             break;
 880         case DO:
 881             doStatement();
 882             break;
 883         case CONTINUE:
 884             continueStatement();
 885             break;
 886         case BREAK:
 887             breakStatement();
 888             break;
 889         case RETURN:
 890             returnStatement();
 891             break;
 892         case YIELD:
 893             yieldStatement();
 894             break;
 895         case WITH:
 896             withStatement();
 897             break;
 898         case SWITCH:
 899             switchStatement();
 900             break;
 901         case THROW:
 902             throwStatement();
 903             break;
 904         case TRY:
 905             tryStatement();
 906             break;
 907         case DEBUGGER:
 908             debuggerStatement();
 909             break;
 910         case RPAREN:
 911         case RBRACKET:
 912         case EOF:
 913             expect(SEMICOLON);
 914             break;
 915         default:
 916             if (env._const_as_var && type == CONST) {
 917                 variableStatement(true);
 918                 break;
 919             }
 920 
 921             if (type == IDENT || isNonStrictModeIdent()) {
 922                 if (T(k + 1) == COLON) {
 923                     labelStatement();
 924                     return;
 925                 }
 926                 if(allowPropertyFunction) {
 927                     final String ident = (String)getValue();
 928                     final long propertyToken = token;
 929                     final int propertyLine = line;
 930                     if("get".equals(ident)) {
 931                         next();
 932                         addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
 933                         return;
 934                     } else if("set".equals(ident)) {
 935                         next();
 936                         addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
 937                         return;
 938                     }
 939                 }
 940             }
 941 
 942             expressionStatement();
 943             break;
 944         }
 945     }
 946 
 947     private void addPropertyFunctionStatement(final PropertyFunction propertyFunction) {
 948         final FunctionNode fn = propertyFunction.functionNode;
 949         functionDeclarations.add(new ExpressionStatement(fn.getLineNumber(), fn.getToken(), finish, fn));
 950     }
 951 
 952     /**
 953      * block :
 954      *      { StatementList? }
 955      *
 956      * see 12.1
 957      *
 958      * Parse a statement block.
 959      */
 960     private void block() {
 961         appendStatement(new BlockStatement(line, getBlock(true)));
 962     }
 963 
 964     /**
 965      * StatementList :
 966      *      Statement
 967      *      StatementList Statement
 968      *
 969      * See 12.1
 970      *
 971      * Parse a list of statements.
 972      */
 973     private void statementList() {
 974         // Accumulate statements until end of list. */
 975 loop:
 976         while (type != EOF) {
 977             switch (type) {
 978             case EOF:
 979             case CASE:
 980             case DEFAULT:
 981             case RBRACE:
 982                 break loop;
 983             default:
 984                 break;
 985             }
 986 
 987             // Get next statement.
 988             statement();
 989         }
 990     }
 991 
 992     /**
 993      * Make sure that in strict mode, the identifier name used is allowed.
 994      *
 995      * @param ident         Identifier that is verified
 996      * @param contextString String used in error message to give context to the user
 997      */
 998     private void verifyStrictIdent(final IdentNode ident, final String contextString) {
 999         if (isStrictMode) {
1000             switch (ident.getName()) {
1001             case "eval":
1002             case "arguments":
1003                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1004             default:
1005                 break;
1006             }
1007 
1008             if (ident.isFutureStrictName()) {
1009                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1010             }
1011         }
1012     }
1013 
1014     /**
1015      * VariableStatement :
1016      *      var VariableDeclarationList ;
1017      *
1018      * VariableDeclarationList :
1019      *      VariableDeclaration
1020      *      VariableDeclarationList , VariableDeclaration
1021      *
1022      * VariableDeclaration :
1023      *      Identifier Initializer?
1024      *
1025      * Initializer :
1026      *      = AssignmentExpression
1027      *
1028      * See 12.2
1029      *
1030      * Parse a VAR statement.
1031      * @param isStatement True if a statement (not used in a FOR.)
1032      */
1033     private List<VarNode> variableStatement(final boolean isStatement) {
1034         // VAR tested in caller.
1035         next();
1036 
1037         final List<VarNode> vars = new ArrayList<>();
1038 
1039         while (true) {
1040             // Get starting token.
1041             final int  varLine  = line;
1042             final long varToken = token;
1043             // Get name of var.
1044             final IdentNode name = getIdent();
1045             verifyStrictIdent(name, "variable name");
1046 
1047             // Assume no init.
1048             Expression init = null;
1049 
1050             // Look for initializer assignment.
1051             if (type == ASSIGN) {
1052                 next();
1053 
1054                 // Get initializer expression. Suppress IN if not statement.
1055                 defaultNames.push(name);
1056                 try {
1057                     init = assignmentExpression(!isStatement);
1058                 } finally {
1059                     defaultNames.pop();
1060                 }
1061             }
1062 
1063             // Allocate var node.
1064             final VarNode var = new VarNode(varLine, varToken, finish, name, init);
1065             vars.add(var);
1066             appendStatement(var);
1067 
1068             if (type != COMMARIGHT) {
1069                 break;
1070             }
1071             next();
1072         }
1073 
1074         // If is a statement then handle end of line.
1075         if (isStatement) {
1076             final boolean semicolon = type == SEMICOLON;
1077             endOfLine();
1078             if (semicolon) {
1079                 lc.getCurrentBlock().setFinish(finish);
1080             }
1081         }
1082 
1083         return vars;
1084     }
1085 
1086     /**
1087      * EmptyStatement :
1088      *      ;
1089      *
1090      * See 12.3
1091      *
1092      * Parse an empty statement.
1093      */
1094     private void emptyStatement() {
1095         if (env._empty_statements) {
1096             appendStatement(new EmptyNode(line, token, Token.descPosition(token) + Token.descLength(token)));
1097         }
1098 
1099         // SEMICOLON checked in caller.
1100         next();
1101     }
1102 
1103     /**
1104      * ExpressionStatement :
1105      *      Expression ; // [lookahead ~( or  function )]
1106      *
1107      * See 12.4
1108      *
1109      * Parse an expression used in a statement block.
1110      */
1111     private void expressionStatement() {
1112         // Lookahead checked in caller.
1113         final int  expressionLine  = line;
1114         final long expressionToken = token;
1115 
1116         // Get expression and add as statement.
1117         final Expression expression = expression();
1118 
1119         ExpressionStatement expressionStatement = null;
1120         if (expression != null) {
1121             expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
1122             appendStatement(expressionStatement);
1123         } else {
1124             expect(null);
1125         }
1126 
1127         endOfLine();
1128 
1129         if (expressionStatement != null) {
1130             expressionStatement.setFinish(finish);
1131             lc.getCurrentBlock().setFinish(finish);
1132         }
1133     }
1134 
1135     /**
1136      * IfStatement :
1137      *      if ( Expression ) Statement else Statement
1138      *      if ( Expression ) Statement
1139      *
1140      * See 12.5
1141      *
1142      * Parse an IF statement.
1143      */
1144     private void ifStatement() {
1145         // Capture IF token.
1146         final int  ifLine  = line;
1147         final long ifToken = token;
1148          // IF tested in caller.
1149         next();
1150 
1151         expect(LPAREN);
1152         final Expression test = expression();
1153         expect(RPAREN);
1154         final Block pass = getStatement();
1155 
1156         Block fail = null;
1157         if (type == ELSE) {
1158             next();
1159             fail = getStatement();
1160         }
1161 
1162         appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1163     }
1164 
1165     /**
1166      * ... IterationStatement:
1167      *           ...
1168      *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1169      *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1170      *           for ( LeftHandSideExpression in Expression ) Statement
1171      *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1172      *
1173      * See 12.6
1174      *
1175      * Parse a FOR statement.
1176      */
1177     private void forStatement() {
1178         // Create FOR node, capturing FOR token.
1179         ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, ForNode.IS_FOR);
1180 
1181         lc.push(forNode);
1182 
1183         try {
1184             // FOR tested in caller.
1185             next();
1186 
1187             // Nashorn extension: for each expression.
1188             // iterate property values rather than property names.
1189             if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1190                 forNode = forNode.setIsForEach(lc);
1191                 next();
1192             }
1193 
1194             expect(LPAREN);
1195 
1196             List<VarNode> vars = null;
1197 
1198             switch (type) {
1199             case VAR:
1200                 // Var statements captured in for outer block.
1201                 vars = variableStatement(false);
1202                 break;
1203             case SEMICOLON:
1204                 break;
1205             default:
1206                 if (env._const_as_var && type == CONST) {
1207                     // Var statements captured in for outer block.
1208                     vars = variableStatement(false);
1209                     break;
1210                 }
1211 
1212                 final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1213                 forNode = forNode.setInit(lc, expression);
1214                 break;
1215             }
1216 
1217             switch (type) {
1218             case SEMICOLON:
1219                 // for (init; test; modify)
1220 
1221                 // for each (init; test; modify) is invalid
1222                 if (forNode.isForEach()) {
1223                     throw error(AbstractParser.message("for.each.without.in"), token);
1224                 }
1225 
1226                 expect(SEMICOLON);
1227                 if (type != SEMICOLON) {
1228                     forNode = forNode.setTest(lc, joinPredecessorExpression());
1229                 }
1230                 expect(SEMICOLON);
1231                 if (type != RPAREN) {
1232                     forNode = forNode.setModify(lc, joinPredecessorExpression());
1233                 }
1234                 break;
1235 
1236             case IN:
1237                 forNode = forNode.setIsForIn(lc).setTest(lc, new JoinPredecessorExpression());
1238                 if (vars != null) {
1239                     // for (var i in obj)
1240                     if (vars.size() == 1) {
1241                         forNode = forNode.setInit(lc, new IdentNode(vars.get(0).getName()));
1242                     } else {
1243                         // for (var i, j in obj) is invalid
1244                         throw error(AbstractParser.message("many.vars.in.for.in.loop"), vars.get(1).getToken());
1245                     }
1246 
1247                 } else {
1248                     // for (expr in obj)
1249                     final Node init = forNode.getInit();
1250                     assert init != null : "for..in init expression can not be null here";
1251 
1252                     // check if initial expression is a valid L-value
1253                     if (!(init instanceof AccessNode ||
1254                           init instanceof IndexNode ||
1255                           init instanceof IdentNode)) {
1256                         throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
1257                     }
1258 
1259                     if (init instanceof IdentNode) {
1260                         if (!checkIdentLValue((IdentNode)init)) {
1261                             throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
1262                         }
1263                         verifyStrictIdent((IdentNode)init, "for-in iterator");
1264                     }
1265                 }
1266 
1267                 next();
1268 
1269                 // Get the collection expression.
1270                 forNode = forNode.setModify(lc, joinPredecessorExpression());
1271                 break;
1272 
1273             default:
1274                 expect(SEMICOLON);
1275                 break;
1276             }
1277 
1278             expect(RPAREN);
1279 
1280             // Set the for body.
1281             final Block body = getStatement();
1282             forNode = forNode.setBody(lc, body);
1283             forNode.setFinish(body.getFinish());
1284 
1285             appendStatement(forNode);
1286         } finally {
1287             lc.pop(forNode);
1288         }
1289      }
1290 
1291     /**
1292      * ... IterationStatement :
1293      *           ...
1294      *           Expression[NoIn]?; Expression? ; Expression?
1295      *           var VariableDeclarationList[NoIn]; Expression? ; Expression?
1296      *           LeftHandSideExpression in Expression
1297      *           var VariableDeclaration[NoIn] in Expression
1298      *
1299      * See 12.6
1300      *
1301      * Parse the control section of a FOR statement.  Also used for
1302      * comprehensions.
1303      * @param forNode Owning FOR.
1304      */
1305 
1306 
1307     /**
1308      * ...IterationStatement :
1309      *           ...
1310      *           while ( Expression ) Statement
1311      *           ...
1312      *
1313      * See 12.6
1314      *
1315      * Parse while statement.
1316      */
1317     private void whileStatement() {
1318         // Capture WHILE token.
1319         final long whileToken = token;
1320         // WHILE tested in caller.
1321         next();
1322 
1323         // Construct WHILE node.
1324         WhileNode whileNode = new WhileNode(line, whileToken, Token.descPosition(whileToken), false);
1325         lc.push(whileNode);
1326 
1327         try {
1328             expect(LPAREN);
1329             final int whileLine = line;
1330             final JoinPredecessorExpression test = joinPredecessorExpression();
1331             expect(RPAREN);
1332             final Block body = getStatement();
1333             appendStatement(whileNode =
1334                 new WhileNode(whileLine, whileToken, finish, false).
1335                     setTest(lc, test).
1336                     setBody(lc, body));
1337         } finally {
1338             lc.pop(whileNode);
1339         }
1340     }
1341 
1342     /**
1343      * ...IterationStatement :
1344      *           ...
1345      *           do Statement while( Expression ) ;
1346      *           ...
1347      *
1348      * See 12.6
1349      *
1350      * Parse DO WHILE statement.
1351      */
1352     private void doStatement() {
1353         // Capture DO token.
1354         final long doToken = token;
1355         // DO tested in the caller.
1356         next();
1357 
1358         WhileNode doWhileNode = new WhileNode(-1, doToken, Token.descPosition(doToken), true);
1359         lc.push(doWhileNode);
1360 
1361         try {
1362            // Get DO body.
1363             final Block body = getStatement();
1364 
1365             expect(WHILE);
1366             expect(LPAREN);
1367             final int doLine = line;
1368             final JoinPredecessorExpression test = joinPredecessorExpression();
1369             expect(RPAREN);
1370 
1371             if (type == SEMICOLON) {
1372                 endOfLine();
1373             }
1374             doWhileNode.setFinish(finish);
1375 
1376             //line number is last
1377             appendStatement(doWhileNode =
1378                 new WhileNode(doLine, doToken, finish, true).
1379                     setBody(lc, body).
1380                     setTest(lc, test));
1381         } finally {
1382             lc.pop(doWhileNode);
1383         }
1384     }
1385 
1386     /**
1387      * ContinueStatement :
1388      *      continue Identifier? ; // [no LineTerminator here]
1389      *
1390      * See 12.7
1391      *
1392      * Parse CONTINUE statement.
1393      */
1394     private void continueStatement() {
1395         // Capture CONTINUE token.
1396         final int  continueLine  = line;
1397         final long continueToken = token;
1398         // CONTINUE tested in caller.
1399         nextOrEOL();
1400 
1401         LabelNode labelNode = null;
1402 
1403         // SEMICOLON or label.
1404         switch (type) {
1405         case RBRACE:
1406         case SEMICOLON:
1407         case EOL:
1408         case EOF:
1409             break;
1410 
1411         default:
1412             final IdentNode ident = getIdent();
1413             labelNode = lc.findLabel(ident.getName());
1414 
1415             if (labelNode == null) {
1416                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1417             }
1418 
1419             break;
1420         }
1421 
1422         final String labelName = labelNode == null ? null : labelNode.getLabelName();
1423         final LoopNode targetNode = lc.getContinueTo(labelName);
1424 
1425         if (targetNode == null) {
1426             throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
1427         }
1428 
1429         endOfLine();
1430 
1431         // Construct and add CONTINUE node.
1432         appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
1433     }
1434 
1435     /**
1436      * BreakStatement :
1437      *      break Identifier? ; // [no LineTerminator here]
1438      *
1439      * See 12.8
1440      *
1441      */
1442     private void breakStatement() {
1443         // Capture BREAK token.
1444         final int  breakLine  = line;
1445         final long breakToken = token;
1446         // BREAK tested in caller.
1447         nextOrEOL();
1448 
1449         LabelNode labelNode = null;
1450 
1451         // SEMICOLON or label.
1452         switch (type) {
1453         case RBRACE:
1454         case SEMICOLON:
1455         case EOL:
1456         case EOF:
1457             break;
1458 
1459         default:
1460             final IdentNode ident = getIdent();
1461             labelNode = lc.findLabel(ident.getName());
1462 
1463             if (labelNode == null) {
1464                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1465             }
1466 
1467             break;
1468         }
1469 
1470         //either an explicit label - then get its node or just a "break" - get first breakable
1471         //targetNode is what we are breaking out from.
1472         final String labelName = labelNode == null ? null : labelNode.getLabelName();
1473         final BreakableNode targetNode = lc.getBreakable(labelName);
1474         if (targetNode == null) {
1475             throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
1476         }
1477 
1478         endOfLine();
1479 
1480         // Construct and add BREAK node.
1481         appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
1482     }
1483 
1484     /**
1485      * ReturnStatement :
1486      *      return Expression? ; // [no LineTerminator here]
1487      *
1488      * See 12.9
1489      *
1490      * Parse RETURN statement.
1491      */
1492     private void returnStatement() {
1493         // check for return outside function
1494         if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT) {
1495             throw error(AbstractParser.message("invalid.return"));
1496         }
1497 
1498         // Capture RETURN token.
1499         final int  returnLine  = line;
1500         final long returnToken = token;
1501         // RETURN tested in caller.
1502         nextOrEOL();
1503 
1504         Expression expression = null;
1505 
1506         // SEMICOLON or expression.
1507         switch (type) {
1508         case RBRACE:
1509         case SEMICOLON:
1510         case EOL:
1511         case EOF:
1512             break;
1513 
1514         default:
1515             expression = expression();
1516             break;
1517         }
1518 
1519         endOfLine();
1520 
1521         // Construct and add RETURN node.
1522         appendStatement(new ReturnNode(returnLine, returnToken, finish, expression));
1523     }
1524 
1525     /**
1526      * YieldStatement :
1527      *      yield Expression? ; // [no LineTerminator here]
1528      *
1529      * JavaScript 1.8
1530      *
1531      * Parse YIELD statement.
1532      */
1533     private void yieldStatement() {
1534         // Capture YIELD token.
1535         final int  yieldLine  = line;
1536         final long yieldToken = token;
1537         // YIELD tested in caller.
1538         nextOrEOL();
1539 
1540         Expression expression = null;
1541 
1542         // SEMICOLON or expression.
1543         switch (type) {
1544         case RBRACE:
1545         case SEMICOLON:
1546         case EOL:
1547         case EOF:
1548             break;
1549 
1550         default:
1551             expression = expression();
1552             break;
1553         }
1554 
1555         endOfLine();
1556 
1557         // Construct and add YIELD node.
1558         appendStatement(new ReturnNode(yieldLine, yieldToken, finish, expression));
1559     }
1560 
1561     /**
1562      * WithStatement :
1563      *      with ( Expression ) Statement
1564      *
1565      * See 12.10
1566      *
1567      * Parse WITH statement.
1568      */
1569     private void withStatement() {
1570         // Capture WITH token.
1571         final int  withLine  = line;
1572         final long withToken = token;
1573         // WITH tested in caller.
1574         next();
1575 
1576         // ECMA 12.10.1 strict mode restrictions
1577         if (isStrictMode) {
1578             throw error(AbstractParser.message("strict.no.with"), withToken);
1579         }
1580 
1581         // Get WITH expression.
1582         WithNode withNode = new WithNode(withLine, withToken, finish);
1583 
1584         try {
1585             lc.push(withNode);
1586             expect(LPAREN);
1587             withNode = withNode.setExpression(lc, expression());
1588             expect(RPAREN);
1589             withNode = withNode.setBody(lc, getStatement());
1590         } finally {
1591             lc.pop(withNode);
1592         }
1593 
1594         appendStatement(withNode);
1595     }
1596 
1597     /**
1598      * SwitchStatement :
1599      *      switch ( Expression ) CaseBlock
1600      *
1601      * CaseBlock :
1602      *      { CaseClauses? }
1603      *      { CaseClauses? DefaultClause CaseClauses }
1604      *
1605      * CaseClauses :
1606      *      CaseClause
1607      *      CaseClauses CaseClause
1608      *
1609      * CaseClause :
1610      *      case Expression : StatementList?
1611      *
1612      * DefaultClause :
1613      *      default : StatementList?
1614      *
1615      * See 12.11
1616      *
1617      * Parse SWITCH statement.
1618      */
1619     private void switchStatement() {
1620         final int  switchLine  = line;
1621         final long switchToken = token;
1622         // SWITCH tested in caller.
1623         next();
1624 
1625         // Create and add switch statement.
1626         SwitchNode switchNode = new SwitchNode(switchLine, switchToken, Token.descPosition(switchToken), null, new ArrayList<CaseNode>(), null);
1627         lc.push(switchNode);
1628 
1629         try {
1630             expect(LPAREN);
1631             switchNode = switchNode.setExpression(lc, expression());
1632             expect(RPAREN);
1633 
1634             expect(LBRACE);
1635 
1636             // Prepare to accumulate cases.
1637             final List<CaseNode> cases = new ArrayList<>();
1638             CaseNode defaultCase = null;
1639 
1640             while (type != RBRACE) {
1641                 // Prepare for next case.
1642                 Expression caseExpression = null;
1643                 final long caseToken = token;
1644 
1645                 switch (type) {
1646                 case CASE:
1647                     next();
1648                     caseExpression = expression();
1649                     break;
1650 
1651                 case DEFAULT:
1652                     if (defaultCase != null) {
1653                         throw error(AbstractParser.message("duplicate.default.in.switch"));
1654                     }
1655                     next();
1656                     break;
1657 
1658                 default:
1659                     // Force an error.
1660                     expect(CASE);
1661                     break;
1662                 }
1663 
1664                 expect(COLON);
1665 
1666                 // Get CASE body.
1667                 final Block statements = getBlock(false);
1668                 final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
1669                 statements.setFinish(finish);
1670 
1671                 if (caseExpression == null) {
1672                     defaultCase = caseNode;
1673                 }
1674 
1675                 cases.add(caseNode);
1676             }
1677 
1678             switchNode = switchNode.setCases(lc, cases, defaultCase);
1679             next();
1680             switchNode.setFinish(finish);
1681 
1682             appendStatement(switchNode);
1683         } finally {
1684             lc.pop(switchNode);
1685         }
1686     }
1687 
1688     /**
1689      * LabelledStatement :
1690      *      Identifier : Statement
1691      *
1692      * See 12.12
1693      *
1694      * Parse label statement.
1695      */
1696     private void labelStatement() {
1697         // Capture label token.
1698         final long labelToken = token;
1699         // Get label ident.
1700         final IdentNode ident = getIdent();
1701 
1702         expect(COLON);
1703 
1704         if (lc.findLabel(ident.getName()) != null) {
1705             throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
1706         }
1707 
1708         LabelNode labelNode = new LabelNode(line, labelToken, finish, ident.getName(), null);
1709         try {
1710             lc.push(labelNode);
1711             labelNode = labelNode.setBody(lc, getStatement());
1712             labelNode.setFinish(finish);
1713             appendStatement(labelNode);
1714         } finally {
1715             assert lc.peek() instanceof LabelNode;
1716             lc.pop(labelNode);
1717         }
1718     }
1719 
1720    /**
1721      * ThrowStatement :
1722      *      throw Expression ; // [no LineTerminator here]
1723      *
1724      * See 12.13
1725      *
1726      * Parse throw statement.
1727      */
1728     private void throwStatement() {
1729         // Capture THROW token.
1730         final int  throwLine  = line;
1731         final long throwToken = token;
1732         // THROW tested in caller.
1733         nextOrEOL();
1734 
1735         Expression expression = null;
1736 
1737         // SEMICOLON or expression.
1738         switch (type) {
1739         case RBRACE:
1740         case SEMICOLON:
1741         case EOL:
1742             break;
1743 
1744         default:
1745             expression = expression();
1746             break;
1747         }
1748 
1749         if (expression == null) {
1750             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
1751         }
1752 
1753         endOfLine();
1754 
1755         appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
1756     }
1757 
1758     /**
1759      * TryStatement :
1760      *      try Block Catch
1761      *      try Block Finally
1762      *      try Block Catch Finally
1763      *
1764      * Catch :
1765      *      catch( Identifier if Expression ) Block
1766      *      catch( Identifier ) Block
1767      *
1768      * Finally :
1769      *      finally Block
1770      *
1771      * See 12.14
1772      *
1773      * Parse TRY statement.
1774      */
1775     private void tryStatement() {
1776         // Capture TRY token.
1777         final int  tryLine  = line;
1778         final long tryToken = token;
1779         // TRY tested in caller.
1780         next();
1781 
1782         // Container block needed to act as target for labeled break statements
1783         final int startLine = line;
1784         Block outer = newBlock();
1785 
1786         // Create try.
1787 
1788         try {
1789             final Block       tryBody     = getBlock(true);
1790             final List<Block> catchBlocks = new ArrayList<>();
1791 
1792             while (type == CATCH) {
1793                 final int  catchLine  = line;
1794                 final long catchToken = token;
1795                 next();
1796                 expect(LPAREN);
1797                 final IdentNode exception = getIdent();
1798 
1799                 // ECMA 12.4.1 strict mode restrictions
1800                 verifyStrictIdent(exception, "catch argument");
1801 
1802                 // Nashorn extension: catch clause can have optional
1803                 // condition. So, a single try can have more than one
1804                 // catch clause each with it's own condition.
1805                 final Expression ifExpression;
1806                 if (!env._no_syntax_extensions && type == IF) {
1807                     next();
1808                     // Get the exception condition.
1809                     ifExpression = expression();
1810                 } else {
1811                     ifExpression = null;
1812                 }
1813 
1814                 expect(RPAREN);
1815 
1816                 Block catchBlock = newBlock();
1817                 try {
1818                     // Get CATCH body.
1819                     final Block catchBody = getBlock(true);
1820                     final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
1821                     appendStatement(catchNode);
1822                 } finally {
1823                     catchBlock = restoreBlock(catchBlock);
1824                     catchBlocks.add(catchBlock);
1825                 }
1826 
1827                 // If unconditional catch then should to be the end.
1828                 if (ifExpression == null) {
1829                     break;
1830                 }
1831             }
1832 
1833             // Prepare to capture finally statement.
1834             Block finallyStatements = null;
1835 
1836             if (type == FINALLY) {
1837                 next();
1838                 finallyStatements = getBlock(true);
1839             }
1840 
1841             // Need at least one catch or a finally.
1842             if (catchBlocks.isEmpty() && finallyStatements == null) {
1843                 throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
1844             }
1845 
1846             final TryNode tryNode = new TryNode(tryLine, tryToken, Token.descPosition(tryToken), tryBody, catchBlocks, finallyStatements);
1847             // Add try.
1848             assert lc.peek() == outer;
1849             appendStatement(tryNode);
1850 
1851             tryNode.setFinish(finish);
1852             outer.setFinish(finish);
1853 
1854         } finally {
1855             outer = restoreBlock(outer);
1856         }
1857 
1858         appendStatement(new BlockStatement(startLine, outer));
1859     }
1860 
1861     /**
1862      * DebuggerStatement :
1863      *      debugger ;
1864      *
1865      * See 12.15
1866      *
1867      * Parse debugger statement.
1868      */
1869     private void  debuggerStatement() {
1870         // Capture DEBUGGER token.
1871         final int  debuggerLine  = line;
1872         final long debuggerToken = token;
1873         // DEBUGGER tested in caller.
1874         next();
1875         endOfLine();
1876         appendStatement(new ExpressionStatement(debuggerLine, debuggerToken, finish, new RuntimeNode(debuggerToken, finish, RuntimeNode.Request.DEBUGGER, new ArrayList<Expression>())));
1877     }
1878 
1879     /**
1880      * PrimaryExpression :
1881      *      this
1882      *      Identifier
1883      *      Literal
1884      *      ArrayLiteral
1885      *      ObjectLiteral
1886      *      ( Expression )
1887      *
1888      *  See 11.1
1889      *
1890      * Parse primary expression.
1891      * @return Expression node.
1892      */
1893     @SuppressWarnings("fallthrough")
1894     private Expression primaryExpression() {
1895         // Capture first token.
1896         final int  primaryLine  = line;
1897         final long primaryToken = token;
1898 
1899         switch (type) {
1900         case THIS:
1901             final String name = type.getName();
1902             next();
1903             lc.setFlag(lc.getCurrentFunction(), FunctionNode.USES_THIS);
1904             return new IdentNode(primaryToken, finish, name);
1905         case IDENT:
1906             final IdentNode ident = getIdent();
1907             if (ident == null) {
1908                 break;
1909             }
1910             detectSpecialProperty(ident);
1911             return ident;
1912         case OCTAL:
1913             if (isStrictMode) {
1914                throw error(AbstractParser.message("strict.no.octal"), token);
1915             }
1916         case STRING:
1917         case ESCSTRING:
1918         case DECIMAL:
1919         case HEXADECIMAL:
1920         case FLOATING:
1921         case REGEX:
1922         case XML:
1923             return getLiteral();
1924         case EXECSTRING:
1925             return execString(primaryLine, primaryToken);
1926         case FALSE:
1927             next();
1928             return LiteralNode.newInstance(primaryToken, finish, false);
1929         case TRUE:
1930             next();
1931             return LiteralNode.newInstance(primaryToken, finish, true);
1932         case NULL:
1933             next();
1934             return LiteralNode.newInstance(primaryToken, finish);
1935         case LBRACKET:
1936             return arrayLiteral();
1937         case LBRACE:
1938             return objectLiteral();
1939         case LPAREN:
1940             next();
1941 
1942             final Expression expression = expression();
1943 
1944             expect(RPAREN);
1945 
1946             return expression;
1947 
1948         default:
1949             // In this context some operator tokens mark the start of a literal.
1950             if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
1951                 next();
1952                 return getLiteral();
1953             }
1954             if (isNonStrictModeIdent()) {
1955                 return getIdent();
1956             }
1957             break;
1958         }
1959 
1960         return null;
1961     }
1962 
1963     /**
1964      * Convert execString to a call to $EXEC.
1965      *
1966      * @param primaryToken Original string token.
1967      * @return callNode to $EXEC.
1968      */
1969     CallNode execString(final int primaryLine, final long primaryToken) {
1970         // Synthesize an ident to call $EXEC.
1971         final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
1972         // Skip over EXECSTRING.
1973         next();
1974         // Set up argument list for call.
1975         // Skip beginning of edit string expression.
1976         expect(LBRACE);
1977         // Add the following expression to arguments.
1978         final List<Expression> arguments = Collections.singletonList(expression());
1979         // Skip ending of edit string expression.
1980         expect(RBRACE);
1981 
1982         return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
1983     }
1984 
1985     /**
1986      * ArrayLiteral :
1987      *      [ Elision? ]
1988      *      [ ElementList ]
1989      *      [ ElementList , Elision? ]
1990      *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
1991      *
1992      * ElementList : Elision? AssignmentExpression
1993      *      ElementList , Elision? AssignmentExpression
1994      *
1995      * Elision :
1996      *      ,
1997      *      Elision ,
1998      *
1999      * See 12.1.4
2000      * JavaScript 1.8
2001      *
2002      * Parse array literal.
2003      * @return Expression node.
2004      */
2005     private LiteralNode<Expression[]> arrayLiteral() {
2006         // Capture LBRACKET token.
2007         final long arrayToken = token;
2008         // LBRACKET tested in caller.
2009         next();
2010 
2011         // Prepare to accummulating elements.
2012         final List<Expression> elements = new ArrayList<>();
2013         // Track elisions.
2014         boolean elision = true;
2015 loop:
2016         while (true) {
2017              switch (type) {
2018             case RBRACKET:
2019                 next();
2020 
2021                 break loop;
2022 
2023             case COMMARIGHT:
2024                 next();
2025 
2026                 // If no prior expression
2027                 if (elision) {
2028                     elements.add(null);
2029                 }
2030 
2031                 elision = true;
2032 
2033                 break;
2034 
2035             default:
2036                 if (!elision) {
2037                     throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2038                 }
2039                 // Add expression element.
2040                 final Expression expression = assignmentExpression(false);
2041 
2042                 if (expression != null) {
2043                     elements.add(expression);
2044                 } else {
2045                     expect(RBRACKET);
2046                 }
2047 
2048                 elision = false;
2049                 break;
2050             }
2051         }
2052 
2053         return LiteralNode.newInstance(arrayToken, finish, elements);
2054     }
2055 
2056     /**
2057      * ObjectLiteral :
2058      *      { }
2059      *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2060      *
2061      * PropertyNameAndValueList :
2062      *      PropertyAssignment
2063      *      PropertyNameAndValueList , PropertyAssignment
2064      *
2065      * See 11.1.5
2066      *
2067      * Parse an object literal.
2068      * @return Expression node.
2069      */
2070     private ObjectNode objectLiteral() {
2071         // Capture LBRACE token.
2072         final long objectToken = token;
2073         // LBRACE tested in caller.
2074         next();
2075 
2076         // Object context.
2077         // Prepare to accumulate elements.
2078         final List<PropertyNode> elements = new ArrayList<>();
2079         final Map<String, Integer> map = new HashMap<>();
2080 
2081         // Create a block for the object literal.
2082         boolean commaSeen = true;
2083 loop:
2084         while (true) {
2085             switch (type) {
2086                 case RBRACE:
2087                     next();
2088                     break loop;
2089 
2090                 case COMMARIGHT:
2091                     if (commaSeen) {
2092                         throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2093                     }
2094                     next();
2095                     commaSeen = true;
2096                     break;
2097 
2098                 default:
2099                     if (!commaSeen) {
2100                         throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2101                     }
2102 
2103                     commaSeen = false;
2104                     // Get and add the next property.
2105                     final PropertyNode property = propertyAssignment();
2106                     final String key = property.getKeyName();
2107                     final Integer existing = map.get(key);
2108 
2109                     if (existing == null) {
2110                         map.put(key, elements.size());
2111                         elements.add(property);
2112                         break;
2113                     }
2114 
2115                     final PropertyNode existingProperty = elements.get(existing);
2116 
2117                     // ECMA section 11.1.5 Object Initialiser
2118                     // point # 4 on property assignment production
2119                     final Expression   value  = property.getValue();
2120                     final FunctionNode getter = property.getGetter();
2121                     final FunctionNode setter = property.getSetter();
2122 
2123                     final Expression   prevValue  = existingProperty.getValue();
2124                     final FunctionNode prevGetter = existingProperty.getGetter();
2125                     final FunctionNode prevSetter = existingProperty.getSetter();
2126 
2127                     // ECMA 11.1.5 strict mode restrictions
2128                     if (isStrictMode && value != null && prevValue != null) {
2129                         throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2130                     }
2131 
2132                     final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
2133                     final boolean isAccessor     = getter != null     || setter != null;
2134 
2135                     // data property redefined as accessor property
2136                     if (prevValue != null && isAccessor) {
2137                         throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2138                     }
2139 
2140                     // accessor property redefined as data
2141                     if (isPrevAccessor && value != null) {
2142                         throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2143                     }
2144 
2145                     if (isAccessor && isPrevAccessor) {
2146                         if (getter != null && prevGetter != null ||
2147                                 setter != null && prevSetter != null) {
2148                             throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2149                         }
2150                     }
2151 
2152                     if (value != null) {
2153                         elements.add(property);
2154                     } else if (getter != null) {
2155                         elements.set(existing, existingProperty.setGetter(getter));
2156                     } else if (setter != null) {
2157                         elements.set(existing, existingProperty.setSetter(setter));
2158                     }
2159                     break;
2160             }
2161         }
2162 
2163         return new ObjectNode(objectToken, finish, elements);
2164     }
2165 
2166     /**
2167      * PropertyName :
2168      *      IdentifierName
2169      *      StringLiteral
2170      *      NumericLiteral
2171      *
2172      * See 11.1.5
2173      *
2174      * @return PropertyName node
2175      */
2176     @SuppressWarnings("fallthrough")
2177     private PropertyKey propertyName() {
2178         switch (type) {
2179         case IDENT:
2180             return getIdent().setIsPropertyName();
2181         case OCTAL:
2182             if (isStrictMode) {
2183                 throw error(AbstractParser.message("strict.no.octal"), token);
2184             }
2185         case STRING:
2186         case ESCSTRING:
2187         case DECIMAL:
2188         case HEXADECIMAL:
2189         case FLOATING:
2190             return getLiteral();
2191         default:
2192             return getIdentifierName().setIsPropertyName();
2193         }
2194     }
2195 
2196     /**
2197      * PropertyAssignment :
2198      *      PropertyName : AssignmentExpression
2199      *      get PropertyName ( ) { FunctionBody }
2200      *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
2201      *
2202      * PropertySetParameterList :
2203      *      Identifier
2204      *
2205      * PropertyName :
2206      *      IdentifierName
2207      *      StringLiteral
2208      *      NumericLiteral
2209      *
2210      * See 11.1.5
2211      *
2212      * Parse an object literal property.
2213      * @return Property or reference node.
2214      */
2215     private PropertyNode propertyAssignment() {
2216         // Capture firstToken.
2217         final long propertyToken = token;
2218         final int  functionLine  = line;
2219 
2220         PropertyKey propertyName;
2221 
2222         if (type == IDENT) {
2223             // Get IDENT.
2224             final String ident = (String)expectValue(IDENT);
2225 
2226             if (type != COLON) {
2227                 final long getSetToken = propertyToken;
2228 
2229                 switch (ident) {
2230                 case "get":
2231                     final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
2232                     return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null);
2233 
2234                 case "set":
2235                     final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
2236                     return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode);
2237                 default:
2238                     break;
2239                 }
2240             }
2241 
2242             propertyName =  new IdentNode(propertyToken, finish, ident).setIsPropertyName();
2243         } else {
2244             propertyName = propertyName();
2245         }
2246 
2247         expect(COLON);
2248 
2249         defaultNames.push(propertyName);
2250         try {
2251             return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
2252         } finally {
2253             defaultNames.pop();
2254         }
2255     }
2256 
2257     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
2258         final PropertyKey getIdent = propertyName();
2259         final String getterName = getIdent.getPropertyName();
2260         final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
2261         expect(LPAREN);
2262         expect(RPAREN);
2263         final FunctionNode functionNode = functionBody(getSetToken, getNameNode, new ArrayList<IdentNode>(), FunctionNode.Kind.GETTER, functionLine);
2264 
2265         return new PropertyFunction(getIdent, functionNode);
2266     }
2267 
2268     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
2269         final PropertyKey setIdent = propertyName();
2270         final String setterName = setIdent.getPropertyName();
2271         final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
2272         expect(LPAREN);
2273         // be sloppy and allow missing setter parameter even though
2274         // spec does not permit it!
2275         final IdentNode argIdent;
2276         if (type == IDENT || isNonStrictModeIdent()) {
2277             argIdent = getIdent();
2278             verifyStrictIdent(argIdent, "setter argument");
2279         } else {
2280             argIdent = null;
2281         }
2282         expect(RPAREN);
2283         final List<IdentNode> parameters = new ArrayList<>();
2284         if (argIdent != null) {
2285             parameters.add(argIdent);
2286         }
2287         final FunctionNode functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER, functionLine);
2288 
2289         return new PropertyFunction(setIdent, functionNode);
2290     }
2291 
2292     private static class PropertyFunction {
2293         final PropertyKey ident;
2294         final FunctionNode functionNode;
2295 
2296         PropertyFunction(final PropertyKey ident, final FunctionNode function) {
2297             this.ident = ident;
2298             this.functionNode = function;
2299         }
2300     }
2301 
2302     /**
2303      * LeftHandSideExpression :
2304      *      NewExpression
2305      *      CallExpression
2306      *
2307      * CallExpression :
2308      *      MemberExpression Arguments
2309      *      CallExpression Arguments
2310      *      CallExpression [ Expression ]
2311      *      CallExpression . IdentifierName
2312      *
2313      * See 11.2
2314      *
2315      * Parse left hand side expression.
2316      * @return Expression node.
2317      */
2318     private Expression leftHandSideExpression() {
2319         int  callLine  = line;
2320         long callToken = token;
2321 
2322         Expression lhs = memberExpression();
2323 
2324         if (type == LPAREN) {
2325             final List<Expression> arguments = optimizeList(argumentList());
2326 
2327             // Catch special functions.
2328             if (lhs instanceof IdentNode) {
2329                 detectSpecialFunction((IdentNode)lhs);
2330             }
2331 
2332             lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2333         }
2334 
2335 loop:
2336         while (true) {
2337             // Capture token.
2338             callLine  = line;
2339             callToken = token;
2340 
2341             switch (type) {
2342             case LPAREN:
2343                 // Get NEW or FUNCTION arguments.
2344                 final List<Expression> arguments = optimizeList(argumentList());
2345 
2346                 // Create call node.
2347                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2348 
2349                 break;
2350 
2351             case LBRACKET:
2352                 next();
2353 
2354                 // Get array index.
2355                 final Expression rhs = expression();
2356 
2357                 expect(RBRACKET);
2358 
2359                 // Create indexing node.
2360                 lhs = new IndexNode(callToken, finish, lhs, rhs);
2361 
2362                 break;
2363 
2364             case PERIOD:
2365                 next();
2366 
2367                 final IdentNode property = getIdentifierName();
2368 
2369                 // Create property access node.
2370                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
2371 
2372                 break;
2373 
2374             default:
2375                 break loop;
2376             }
2377         }
2378 
2379         return lhs;
2380     }
2381 
2382     /**
2383      * NewExpression :
2384      *      MemberExpression
2385      *      new NewExpression
2386      *
2387      * See 11.2
2388      *
2389      * Parse new expression.
2390      * @return Expression node.
2391      */
2392     private Expression newExpression() {
2393         final long newToken = token;
2394         // NEW is tested in caller.
2395         next();
2396 
2397         // Get function base.
2398         final int  callLine    = line;
2399         final Expression constructor = memberExpression();
2400         if (constructor == null) {
2401             return null;
2402         }
2403         // Get arguments.
2404         ArrayList<Expression> arguments;
2405 
2406         // Allow for missing arguments.
2407         if (type == LPAREN) {
2408             arguments = argumentList();
2409         } else {
2410             arguments = new ArrayList<>();
2411         }
2412 
2413         // Nashorn extension: This is to support the following interface implementation
2414         // syntax:
2415         //
2416         //     var r = new java.lang.Runnable() {
2417         //         run: function() { println("run"); }
2418         //     };
2419         //
2420         // The object literal following the "new Constructor()" expresssion
2421         // is passed as an additional (last) argument to the constructor.
2422         if (!env._no_syntax_extensions && type == LBRACE) {
2423             arguments.add(objectLiteral());
2424         }
2425 
2426         final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
2427 
2428         return new UnaryNode(newToken, callNode);
2429     }
2430 
2431     /**
2432      * MemberExpression :
2433      *      PrimaryExpression
2434      *      FunctionExpression
2435      *      MemberExpression [ Expression ]
2436      *      MemberExpression . IdentifierName
2437      *      new MemberExpression Arguments
2438      *
2439      * See 11.2
2440      *
2441      * Parse member expression.
2442      * @return Expression node.
2443      */
2444     private Expression memberExpression() {
2445         // Prepare to build operation.
2446         Expression lhs;
2447 
2448         switch (type) {
2449         case NEW:
2450             // Get new expression.
2451             lhs = newExpression();
2452             break;
2453 
2454         case FUNCTION:
2455             // Get function expression.
2456             lhs = functionExpression(false, false);
2457             break;
2458 
2459         default:
2460             // Get primary expression.
2461             lhs = primaryExpression();
2462             break;
2463         }
2464 
2465 loop:
2466         while (true) {
2467             // Capture token.
2468             final long callToken = token;
2469 
2470             switch (type) {
2471             case LBRACKET:
2472                 next();
2473 
2474                 // Get array index.
2475                 final Expression index = expression();
2476 
2477                 expect(RBRACKET);
2478 
2479                 // Create indexing node.
2480                 lhs = new IndexNode(callToken, finish, lhs, index);
2481 
2482                 break;
2483 
2484             case PERIOD:
2485                 if (lhs == null) {
2486                     throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2487                 }
2488 
2489                 next();
2490 
2491                 final IdentNode property = getIdentifierName();
2492 
2493                 // Create property access node.
2494                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
2495 
2496                 break;
2497 
2498             default:
2499                 break loop;
2500             }
2501         }
2502 
2503         return lhs;
2504     }
2505 
2506     /**
2507      * Arguments :
2508      *      ( )
2509      *      ( ArgumentList )
2510      *
2511      * ArgumentList :
2512      *      AssignmentExpression
2513      *      ArgumentList , AssignmentExpression
2514      *
2515      * See 11.2
2516      *
2517      * Parse function call arguments.
2518      * @return Argument list.
2519      */
2520     private ArrayList<Expression> argumentList() {
2521         // Prepare to accumulate list of arguments.
2522         final ArrayList<Expression> nodeList = new ArrayList<>();
2523         // LPAREN tested in caller.
2524         next();
2525 
2526         // Track commas.
2527         boolean first = true;
2528 
2529         while (type != RPAREN) {
2530             // Comma prior to every argument except the first.
2531             if (!first) {
2532                 expect(COMMARIGHT);
2533             } else {
2534                 first = false;
2535             }
2536 
2537             // Get argument expression.
2538             nodeList.add(assignmentExpression(false));
2539         }
2540 
2541         expect(RPAREN);
2542         return nodeList;
2543     }
2544 
2545     private static <T> List<T> optimizeList(final ArrayList<T> list) {
2546         switch(list.size()) {
2547             case 0: {
2548                 return Collections.emptyList();
2549             }
2550             case 1: {
2551                 return Collections.singletonList(list.get(0));
2552             }
2553             default: {
2554                 list.trimToSize();
2555                 return list;
2556             }
2557         }
2558     }
2559 
2560     /**
2561      * FunctionDeclaration :
2562      *      function Identifier ( FormalParameterList? ) { FunctionBody }
2563      *
2564      * FunctionExpression :
2565      *      function Identifier? ( FormalParameterList? ) { FunctionBody }
2566      *
2567      * See 13
2568      *
2569      * Parse function declaration.
2570      * @param isStatement True if for is a statement.
2571      *
2572      * @return Expression node.
2573      */
2574     private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
2575         final long functionToken = token;
2576         final int  functionLine  = line;
2577         // FUNCTION is tested in caller.
2578         next();
2579 
2580         IdentNode name = null;
2581 
2582         if (type == IDENT || isNonStrictModeIdent()) {
2583             name = getIdent();
2584             verifyStrictIdent(name, "function name");
2585         } else if (isStatement) {
2586             // Nashorn extension: anonymous function statements
2587             if (env._no_syntax_extensions) {
2588                 expect(IDENT);
2589             }
2590         }
2591 
2592         // name is null, generate anonymous name
2593         boolean isAnonymous = false;
2594         if (name == null) {
2595             final String tmpName = getDefaultValidFunctionName(functionLine);
2596             name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
2597             isAnonymous = true;
2598         }
2599 
2600         expect(LPAREN);
2601         final List<IdentNode> parameters = formalParameterList();
2602         expect(RPAREN);
2603 
2604         FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL, functionLine);
2605 
2606         if (isStatement) {
2607             if (topLevel) {
2608                 functionNode = functionNode.setFlag(lc, FunctionNode.IS_DECLARED);
2609             } else if (isStrictMode) {
2610                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
2611             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
2612                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
2613             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
2614                 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
2615             }
2616             if (isArguments(name)) {
2617                 lc.setFlag(lc.getCurrentFunction(), FunctionNode.DEFINES_ARGUMENTS);
2618             }
2619         }
2620 
2621         if (isAnonymous) {
2622             functionNode = functionNode.setFlag(lc, FunctionNode.IS_ANONYMOUS);
2623         }
2624 
2625         final int arity = parameters.size();
2626 
2627         final boolean strict = functionNode.isStrict();
2628         if (arity > 1) {
2629             final HashSet<String> parametersSet = new HashSet<>(arity);
2630 
2631             for (int i = arity - 1; i >= 0; i--) {
2632                 final IdentNode parameter = parameters.get(i);
2633                 String parameterName = parameter.getName();
2634 
2635                 if (isArguments(parameterName)) {
2636                     functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS);
2637                 }
2638 
2639                 if (parametersSet.contains(parameterName)) {
2640                     // redefinition of parameter name
2641                     if (strict) {
2642                         throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2643                     }
2644                     // rename in non-strict mode
2645                     parameterName = functionNode.uniqueName(parameterName);
2646                     final long parameterToken = parameter.getToken();
2647                     parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2648                 }
2649 
2650                 parametersSet.add(parameterName);
2651             }
2652         } else if (arity == 1) {
2653             if (isArguments(parameters.get(0))) {
2654                 functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS);
2655             }
2656         }
2657 
2658         if (isStatement) {
2659             final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, VarNode.IS_STATEMENT);
2660             if (topLevel) {
2661                 functionDeclarations.add(varNode);
2662             } else {
2663                 appendStatement(varNode);
2664             }
2665         }
2666 
2667         return functionNode;
2668     }
2669 
2670     private String getDefaultValidFunctionName(final int functionLine) {
2671         final String defaultFunctionName = getDefaultFunctionName();
2672         return isValidIdentifier(defaultFunctionName) ? defaultFunctionName : ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2673     }
2674 
2675     private static boolean isValidIdentifier(final String name) {
2676         if(name == null || name.isEmpty()) {
2677             return false;
2678         }
2679         if(!Character.isJavaIdentifierStart(name.charAt(0))) {
2680             return false;
2681         }
2682         for(int i = 1; i < name.length(); ++i) {
2683             if(!Character.isJavaIdentifierPart(name.charAt(i))) {
2684                 return false;
2685             }
2686         }
2687         return true;
2688     }
2689 
2690     private String getDefaultFunctionName() {
2691         if(!defaultNames.isEmpty()) {
2692             final Object nameExpr = defaultNames.peek();
2693             if(nameExpr instanceof PropertyKey) {
2694                 markDefaultNameUsed();
2695                 return ((PropertyKey)nameExpr).getPropertyName();
2696             } else if(nameExpr instanceof AccessNode) {
2697                 markDefaultNameUsed();
2698                 return ((AccessNode)nameExpr).getProperty();
2699             }
2700         }
2701         return null;
2702     }
2703 
2704     private void markDefaultNameUsed() {
2705         defaultNames.pop();
2706         // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
2707         // from. Can't be null
2708         defaultNames.push("");
2709     }
2710 
2711     /**
2712      * FormalParameterList :
2713      *      Identifier
2714      *      FormalParameterList , Identifier
2715      *
2716      * See 13
2717      *
2718      * Parse function parameter list.
2719      * @return List of parameter nodes.
2720      */
2721     private List<IdentNode> formalParameterList() {
2722         return formalParameterList(RPAREN);
2723     }
2724 
2725     /**
2726      * Same as the other method of the same name - except that the end
2727      * token type expected is passed as argument to this method.
2728      *
2729      * FormalParameterList :
2730      *      Identifier
2731      *      FormalParameterList , Identifier
2732      *
2733      * See 13
2734      *
2735      * Parse function parameter list.
2736      * @return List of parameter nodes.
2737      */
2738     private List<IdentNode> formalParameterList(final TokenType endType) {
2739         // Prepare to gather parameters.
2740         final ArrayList<IdentNode> parameters = new ArrayList<>();
2741         // Track commas.
2742         boolean first = true;
2743 
2744         while (type != endType) {
2745             // Comma prior to every argument except the first.
2746             if (!first) {
2747                 expect(COMMARIGHT);
2748             } else {
2749                 first = false;
2750             }
2751 
2752             // Get and add parameter.
2753             final IdentNode ident = getIdent();
2754 
2755             // ECMA 13.1 strict mode restrictions
2756             verifyStrictIdent(ident, "function parameter");
2757 
2758             parameters.add(ident);
2759         }
2760 
2761         parameters.trimToSize();
2762         return parameters;
2763     }
2764 
2765     /**
2766      * FunctionBody :
2767      *      SourceElements?
2768      *
2769      * See 13
2770      *
2771      * Parse function body.
2772      * @return function node (body.)
2773      */
2774     private FunctionNode functionBody(final long firstToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine) {
2775         FunctionNode functionNode = null;
2776         long lastToken = 0L;
2777 
2778         try {
2779             // Create a new function block.
2780             functionNode = newFunctionNode(firstToken, ident, parameters, kind, functionLine);
2781 
2782             // Nashorn extension: expression closures
2783             if (!env._no_syntax_extensions && type != LBRACE) {
2784                 /*
2785                  * Example:
2786                  *
2787                  * function square(x) x * x;
2788                  * print(square(3));
2789                  */
2790 
2791                 // just expression as function body
2792                 final Expression expr = assignmentExpression(true);
2793                 lastToken = previousToken;
2794                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
2795                 // EOL uses length field to store the line number
2796                 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
2797                 final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
2798                 appendStatement(returnNode);
2799                 functionNode.setFinish(lastFinish);
2800 
2801             } else {
2802                 expect(LBRACE);
2803 
2804                 // Gather the function elements.
2805                 final List<Statement> prevFunctionDecls = functionDeclarations;
2806                 functionDeclarations = new ArrayList<>();
2807                 try {
2808                     sourceElements(false);
2809                     addFunctionDeclarations(functionNode);
2810                 } finally {
2811                     functionDeclarations = prevFunctionDecls;
2812                 }
2813 
2814                 lastToken = token;
2815                 expect(RBRACE);
2816                 functionNode.setFinish(finish);
2817 
2818             }
2819         } finally {
2820             functionNode = restoreFunctionNode(functionNode, lastToken);
2821         }
2822         return functionNode;
2823     }
2824 
2825     private void addFunctionDeclarations(final FunctionNode functionNode) {
2826         assert lc.peek() == lc.getFunctionBody(functionNode);
2827         VarNode lastDecl = null;
2828         for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
2829             Statement decl = functionDeclarations.get(i);
2830             if (lastDecl == null && decl instanceof VarNode) {
2831                 decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
2832                 lc.setFlag(functionNode, FunctionNode.HAS_FUNCTION_DECLARATIONS);
2833             }
2834             prependStatement(decl);
2835         }
2836     }
2837 
2838     private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
2839         if (earlyError) {
2840             throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
2841         }
2842         final ArrayList<Expression> args = new ArrayList<>();
2843         args.add(lhs);
2844         if (rhs == null) {
2845             args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
2846         } else {
2847             args.add(rhs);
2848         }
2849         args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
2850         return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
2851     }
2852 
2853     /*
2854      * parse LHS [a, b, ..., c].
2855      *
2856      * JavaScript 1.8.
2857      */
2858     //private Node destructureExpression() {
2859     //    return null;
2860     //}
2861 
2862     /**
2863      * PostfixExpression :
2864      *      LeftHandSideExpression
2865      *      LeftHandSideExpression ++ // [no LineTerminator here]
2866      *      LeftHandSideExpression -- // [no LineTerminator here]
2867      *
2868      * See 11.3
2869      *
2870      * UnaryExpression :
2871      *      PostfixExpression
2872      *      delete UnaryExpression
2873      *      Node UnaryExpression
2874      *      typeof UnaryExpression
2875      *      ++ UnaryExpression
2876      *      -- UnaryExpression
2877      *      + UnaryExpression
2878      *      - UnaryExpression
2879      *      ~ UnaryExpression
2880      *      ! UnaryExpression
2881      *
2882      * See 11.4
2883      *
2884      * Parse unary expression.
2885      * @return Expression node.
2886      */
2887     private Expression unaryExpression() {
2888         final int  unaryLine  = line;
2889         final long unaryToken = token;
2890 
2891         switch (type) {
2892         case DELETE: {
2893             next();
2894             final Expression expr = unaryExpression();
2895             if (expr instanceof BaseNode || expr instanceof IdentNode) {
2896                 return new UnaryNode(unaryToken, expr);
2897             }
2898             appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
2899             return LiteralNode.newInstance(unaryToken, finish, true);
2900         }
2901         case VOID:
2902         case TYPEOF:
2903         case ADD:
2904         case SUB:
2905         case BIT_NOT:
2906         case NOT:
2907             next();
2908             final Expression expr = unaryExpression();
2909             return new UnaryNode(unaryToken, expr);
2910 
2911         case INCPREFIX:
2912         case DECPREFIX:
2913             final TokenType opType = type;
2914             next();
2915 
2916             final Expression lhs = leftHandSideExpression();
2917             // ++, -- without operand..
2918             if (lhs == null) {
2919                 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
2920             }
2921 
2922             if (!(lhs instanceof AccessNode ||
2923                   lhs instanceof IndexNode ||
2924                   lhs instanceof IdentNode)) {
2925                 return referenceError(lhs, null, env._early_lvalue_error);
2926             }
2927 
2928             if (lhs instanceof IdentNode) {
2929                 if (!checkIdentLValue((IdentNode)lhs)) {
2930                     return referenceError(lhs, null, false);
2931                 }
2932                 verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
2933             }
2934 
2935             return incDecExpression(unaryToken, opType, lhs, false);
2936 
2937         default:
2938             break;
2939         }
2940 
2941         Expression expression = leftHandSideExpression();
2942 
2943         if (last != EOL) {
2944             switch (type) {
2945             case INCPREFIX:
2946             case DECPREFIX:
2947                 final TokenType opType = type;
2948                 final Expression lhs = expression;
2949                 // ++, -- without operand..
2950                 if (lhs == null) {
2951                     throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
2952                 }
2953 
2954                 if (!(lhs instanceof AccessNode ||
2955                    lhs instanceof IndexNode ||
2956                    lhs instanceof IdentNode)) {
2957                     next();
2958                     return referenceError(lhs, null, env._early_lvalue_error);
2959                 }
2960                 if (lhs instanceof IdentNode) {
2961                     if (!checkIdentLValue((IdentNode)lhs)) {
2962                         next();
2963                         return referenceError(lhs, null, false);
2964                     }
2965                     verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
2966                 }
2967                 expression = incDecExpression(token, type, expression, true);
2968                 next();
2969                 break;
2970             default:
2971                 break;
2972             }
2973         }
2974 
2975         if (expression == null) {
2976             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2977         }
2978 
2979         return expression;
2980     }
2981 
2982     /**
2983      * MultiplicativeExpression :
2984      *      UnaryExpression
2985      *      MultiplicativeExpression * UnaryExpression
2986      *      MultiplicativeExpression / UnaryExpression
2987      *      MultiplicativeExpression % UnaryExpression
2988      *
2989      * See 11.5
2990      *
2991      * AdditiveExpression :
2992      *      MultiplicativeExpression
2993      *      AdditiveExpression + MultiplicativeExpression
2994      *      AdditiveExpression - MultiplicativeExpression
2995      *
2996      * See 11.6
2997      *
2998      * ShiftExpression :
2999      *      AdditiveExpression
3000      *      ShiftExpression << AdditiveExpression
3001      *      ShiftExpression >> AdditiveExpression
3002      *      ShiftExpression >>> AdditiveExpression
3003      *
3004      * See 11.7
3005      *
3006      * RelationalExpression :
3007      *      ShiftExpression
3008      *      RelationalExpression < ShiftExpression
3009      *      RelationalExpression > ShiftExpression
3010      *      RelationalExpression <= ShiftExpression
3011      *      RelationalExpression >= ShiftExpression
3012      *      RelationalExpression instanceof ShiftExpression
3013      *      RelationalExpression in ShiftExpression // if !noIf
3014      *
3015      * See 11.8
3016      *
3017      *      RelationalExpression
3018      *      EqualityExpression == RelationalExpression
3019      *      EqualityExpression != RelationalExpression
3020      *      EqualityExpression === RelationalExpression
3021      *      EqualityExpression !== RelationalExpression
3022      *
3023      * See 11.9
3024      *
3025      * BitwiseANDExpression :
3026      *      EqualityExpression
3027      *      BitwiseANDExpression & EqualityExpression
3028      *
3029      * BitwiseXORExpression :
3030      *      BitwiseANDExpression
3031      *      BitwiseXORExpression ^ BitwiseANDExpression
3032      *
3033      * BitwiseORExpression :
3034      *      BitwiseXORExpression
3035      *      BitwiseORExpression | BitwiseXORExpression
3036      *
3037      * See 11.10
3038      *
3039      * LogicalANDExpression :
3040      *      BitwiseORExpression
3041      *      LogicalANDExpression && BitwiseORExpression
3042      *
3043      * LogicalORExpression :
3044      *      LogicalANDExpression
3045      *      LogicalORExpression || LogicalANDExpression
3046      *
3047      * See 11.11
3048      *
3049      * ConditionalExpression :
3050      *      LogicalORExpression
3051      *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
3052      *
3053      * See 11.12
3054      *
3055      * AssignmentExpression :
3056      *      ConditionalExpression
3057      *      LeftHandSideExpression AssignmentOperator AssignmentExpression
3058      *
3059      * AssignmentOperator :
3060      *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
3061      *
3062      * See 11.13
3063      *
3064      * Expression :
3065      *      AssignmentExpression
3066      *      Expression , AssignmentExpression
3067      *
3068      * See 11.14
3069      *
3070      * Parse expression.
3071      * @return Expression node.
3072      */
3073     private Expression expression() {
3074         // TODO - Destructuring array.
3075         // Include commas in expression parsing.
3076         return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
3077     }
3078 
3079     private JoinPredecessorExpression joinPredecessorExpression() {
3080         return new JoinPredecessorExpression(expression());
3081     }
3082 
3083     private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
3084         // Get the precedence of the next operator.
3085         int precedence = type.getPrecedence();
3086         Expression lhs = exprLhs;
3087 
3088         // While greater precedence.
3089         while (type.isOperator(noIn) && precedence >= minPrecedence) {
3090             // Capture the operator token.
3091             final long op = token;
3092 
3093             if (type == TERNARY) {
3094                 // Skip operator.
3095                 next();
3096 
3097                 // Pass expression. Middle expression of a conditional expression can be a "in"
3098                 // expression - even in the contexts where "in" is not permitted.
3099                 final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
3100 
3101                 expect(COLON);
3102 
3103                 // Fail expression.
3104                 final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3105 
3106                 // Build up node.
3107                 lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
3108             } else {
3109                 // Skip operator.
3110                 next();
3111 
3112                  // Get the next primary expression.
3113                 Expression rhs;
3114                 final boolean isAssign = Token.descType(op) == ASSIGN;
3115                 if(isAssign) {
3116                     defaultNames.push(lhs);
3117                 }
3118                 try {
3119                     rhs = unaryExpression();
3120                     // Get precedence of next operator.
3121                     int nextPrecedence = type.getPrecedence();
3122 
3123                     // Subtask greater precedence.
3124                     while (type.isOperator(noIn) &&
3125                            (nextPrecedence > precedence ||
3126                            nextPrecedence == precedence && !type.isLeftAssociative())) {
3127                         rhs = expression(rhs, nextPrecedence, noIn);
3128                         nextPrecedence = type.getPrecedence();
3129                     }
3130                 } finally {
3131                     if(isAssign) {
3132                         defaultNames.pop();
3133                     }
3134                 }
3135                 lhs = verifyAssignment(op, lhs, rhs);
3136             }
3137 
3138             precedence = type.getPrecedence();
3139         }
3140 
3141         return lhs;
3142     }
3143 
3144     private Expression assignmentExpression(final boolean noIn) {
3145         // TODO - Handle decompose.
3146         // Exclude commas in expression parsing.
3147         return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3148     }
3149 
3150     /**
3151      * Parse an end of line.
3152      */
3153     private void endOfLine() {
3154         switch (type) {
3155         case SEMICOLON:
3156         case EOL:
3157             next();
3158             break;
3159         case RPAREN:
3160         case RBRACKET:
3161         case RBRACE:
3162         case EOF:
3163             break;
3164         default:
3165             if (last != EOL) {
3166                 expect(SEMICOLON);
3167             }
3168             break;
3169         }
3170     }
3171 
3172     @Override
3173     public String toString() {
3174         return "'JavaScript Parsing'";
3175     }
3176 
3177     private static void markEval(final LexicalContext lc) {
3178         final Iterator<FunctionNode> iter = lc.getFunctions();
3179         boolean flaggedCurrentFn = false;
3180         while (iter.hasNext()) {
3181             final FunctionNode fn = iter.next();
3182             if (!flaggedCurrentFn) {
3183                 lc.setFlag(fn, FunctionNode.HAS_EVAL);
3184                 flaggedCurrentFn = true;
3185             } else {
3186                 lc.setFlag(fn, FunctionNode.HAS_NESTED_EVAL);
3187             }
3188             lc.setBlockNeedsScope(lc.getFunctionBody(fn));
3189         }
3190     }
3191 
3192     private void prependStatement(final Statement statement) {
3193         lc.prependStatement(statement);
3194     }
3195 
3196     private void appendStatement(final Statement statement) {
3197         lc.appendStatement(statement);
3198     }
3199 }