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