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