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