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