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.EVAL;
  29 import static jdk.nashorn.internal.codegen.CompilerConstants.FUNCTION_PREFIX;
  30 import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
  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.DECPOSTFIX;
  37 import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
  38 import static jdk.nashorn.internal.parser.TokenType.ELSE;
  39 import static jdk.nashorn.internal.parser.TokenType.EOF;
  40 import static jdk.nashorn.internal.parser.TokenType.EOL;
  41 import static jdk.nashorn.internal.parser.TokenType.FINALLY;
  42 import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
  43 import static jdk.nashorn.internal.parser.TokenType.IDENT;
  44 import static jdk.nashorn.internal.parser.TokenType.IF;
  45 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
  46 import static jdk.nashorn.internal.parser.TokenType.LBRACE;
  47 import static jdk.nashorn.internal.parser.TokenType.LPAREN;
  48 import static jdk.nashorn.internal.parser.TokenType.RBRACE;
  49 import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
  50 import static jdk.nashorn.internal.parser.TokenType.RPAREN;
  51 import static jdk.nashorn.internal.parser.TokenType.SEMICOLON;
  52 import static jdk.nashorn.internal.parser.TokenType.TERNARY;
  53 import static jdk.nashorn.internal.parser.TokenType.WHILE;
  54 
  55 import java.util.ArrayList;
  56 import java.util.Collections;
  57 import java.util.HashMap;
  58 import java.util.HashSet;
  59 import java.util.Iterator;
  60 import java.util.List;
  61 import java.util.Map;

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