1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.parser;
  27 
  28 import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
  29 import static jdk.nashorn.internal.codegen.CompilerConstants.FUNCTION_PREFIX;
  30 import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
  31 import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
  32 import static jdk.nashorn.internal.parser.TokenType.CASE;
  33 import static jdk.nashorn.internal.parser.TokenType.CATCH;
  34 import static jdk.nashorn.internal.parser.TokenType.COLON;
  35 import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
  36 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
  37 import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
  38 import static jdk.nashorn.internal.parser.TokenType.ELSE;
  39 import static jdk.nashorn.internal.parser.TokenType.EOF;
  40 import static jdk.nashorn.internal.parser.TokenType.EOL;
  41 import static jdk.nashorn.internal.parser.TokenType.FINALLY;
  42 import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
  43 import static jdk.nashorn.internal.parser.TokenType.IDENT;
  44 import static jdk.nashorn.internal.parser.TokenType.IF;
  45 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
  46 import static jdk.nashorn.internal.parser.TokenType.LBRACE;
  47 import static jdk.nashorn.internal.parser.TokenType.LPAREN;
  48 import static jdk.nashorn.internal.parser.TokenType.RBRACE;
  49 import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
  50 import static jdk.nashorn.internal.parser.TokenType.RPAREN;
  51 import static jdk.nashorn.internal.parser.TokenType.SEMICOLON;
  52 import static jdk.nashorn.internal.parser.TokenType.TERNARY;
  53 import static jdk.nashorn.internal.parser.TokenType.WHILE;
  54 
  55 import java.util.ArrayList;
  56 import java.util.Collections;
  57 import java.util.HashMap;
  58 import java.util.HashSet;
  59 import java.util.Iterator;
  60 import java.util.List;
  61 import java.util.Map;
  62 import jdk.internal.dynalink.support.NameCodec;
  63 import jdk.nashorn.internal.codegen.CompilerConstants;
  64 import jdk.nashorn.internal.codegen.Namespace;
  65 import jdk.nashorn.internal.ir.AccessNode;
  66 import jdk.nashorn.internal.ir.BaseNode;
  67 import jdk.nashorn.internal.ir.BinaryNode;
  68 import jdk.nashorn.internal.ir.Block;
  69 import jdk.nashorn.internal.ir.BlockLexicalContext;
  70 import jdk.nashorn.internal.ir.BlockStatement;
  71 import jdk.nashorn.internal.ir.BreakNode;
  72 import jdk.nashorn.internal.ir.BreakableNode;
  73 import jdk.nashorn.internal.ir.CallNode;
  74 import jdk.nashorn.internal.ir.CaseNode;
  75 import jdk.nashorn.internal.ir.CatchNode;
  76 import jdk.nashorn.internal.ir.ContinueNode;
  77 import jdk.nashorn.internal.ir.EmptyNode;
  78 import jdk.nashorn.internal.ir.Expression;
  79 import jdk.nashorn.internal.ir.ExpressionStatement;
  80 import jdk.nashorn.internal.ir.ForNode;
  81 import jdk.nashorn.internal.ir.FunctionNode;
  82 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
  83 import jdk.nashorn.internal.ir.IdentNode;
  84 import jdk.nashorn.internal.ir.IfNode;
  85 import jdk.nashorn.internal.ir.IndexNode;
  86 import jdk.nashorn.internal.ir.LabelNode;
  87 import jdk.nashorn.internal.ir.LexicalContext;
  88 import jdk.nashorn.internal.ir.LiteralNode;
  89 import jdk.nashorn.internal.ir.LoopNode;
  90 import jdk.nashorn.internal.ir.Node;
  91 import jdk.nashorn.internal.ir.ObjectNode;
  92 import jdk.nashorn.internal.ir.PropertyKey;
  93 import jdk.nashorn.internal.ir.PropertyNode;
  94 import jdk.nashorn.internal.ir.ReturnNode;
  95 import jdk.nashorn.internal.ir.RuntimeNode;
  96 import jdk.nashorn.internal.ir.Statement;
  97 import jdk.nashorn.internal.ir.SwitchNode;
  98 import jdk.nashorn.internal.ir.TernaryNode;
  99 import jdk.nashorn.internal.ir.ThrowNode;
 100 import jdk.nashorn.internal.ir.TryNode;
 101 import jdk.nashorn.internal.ir.UnaryNode;
 102 import jdk.nashorn.internal.ir.VarNode;
 103 import jdk.nashorn.internal.ir.WhileNode;
 104 import jdk.nashorn.internal.ir.WithNode;
 105 import jdk.nashorn.internal.runtime.DebugLogger;
 106 import jdk.nashorn.internal.runtime.ErrorManager;
 107 import jdk.nashorn.internal.runtime.JSErrorType;
 108 import jdk.nashorn.internal.runtime.ParserException;
 109 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 110 import jdk.nashorn.internal.runtime.ScriptingFunctions;
 111 import jdk.nashorn.internal.runtime.Source;
 112 import jdk.nashorn.internal.runtime.Timing;
 113 
 114 /**
 115  * Builds the IR.
 116  */
 117 public class Parser extends AbstractParser {
 118     private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName();
 119 
 120     /** Current script environment. */
 121     private final ScriptEnvironment env;
 122 
 123     /** Is scripting mode. */
 124     private final boolean scripting;
 125 
 126     private List<Statement> functionDeclarations;
 127 
 128     private final BlockLexicalContext lc = new BlockLexicalContext();
 129 
 130     /** Namespace for function names where not explicitly given */
 131     private final Namespace namespace;
 132 
 133     private static final DebugLogger LOG = new DebugLogger("parser");
 134 
 135     /** to receive line information from Lexer when scanning multine literals. */
 136     protected final Lexer.LineInfoReceiver lineInfoReceiver;
 137 
 138     /**
 139      * Constructor
 140      *
 141      * @param env     script environment
 142      * @param source  source to parse
 143      * @param errors  error manager
 144      */
 145     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors) {
 146         this(env, source, errors, env._strict);
 147     }
 148 
 149     /**
 150      * Construct a parser.
 151      *
 152      * @param env     script environment
 153      * @param source  source to parse
 154      * @param errors  error manager
 155      * @param strict  parser created with strict mode enabled.
 156      */
 157     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict) {
 158         super(source, errors, strict);
 159         this.env       = env;
 160         this.namespace = new Namespace(env.getNamespace());
 161         this.scripting = env._scripting;
 162         if (this.scripting) {
 163             this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
 164                 @Override
 165                 public void lineInfo(final int receiverLine, final int receiverLinePosition) {
 166                     // update the parser maintained line information
 167                     Parser.this.line = receiverLine;
 168                     Parser.this.linePosition = receiverLinePosition;
 169                 }
 170             };
 171         } else {
 172             // non-scripting mode script can't have multi-line literals
 173             this.lineInfoReceiver = null;
 174         }
 175     }
 176 
 177     /**
 178      * Execute parse and return the resulting function node.
 179      * Errors will be thrown and the error manager will contain information
 180      * if parsing should fail
 181      *
 182      * This is the default parse call, which will name the function node
 183      * "runScript" {@link CompilerConstants#RUN_SCRIPT}
 184      *
 185      * @return function node resulting from successful parse
 186      */
 187     public FunctionNode parse() {
 188         return parse(RUN_SCRIPT.symbolName());
 189     }
 190 
 191     /**
 192      * Execute parse and return the resulting function node.
 193      * Errors will be thrown and the error manager will contain information
 194      * if parsing should fail
 195      *
 196      * @param scriptName name for the script, given to the parsed FunctionNode
 197      *
 198      * @return function node resulting from successful parse
 199      */
 200     public FunctionNode parse(final String scriptName) {
 201         final long t0 = Timing.isEnabled() ? System.currentTimeMillis() : 0L;
 202         LOG.info(this, " begin for '", scriptName, "'");
 203 
 204         try {
 205             stream = new TokenStream();
 206             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
 207 
 208             // Set up first token (skips opening EOL.)
 209             k = -1;
 210             next();
 211 
 212             // Begin parse.
 213             return program(scriptName);
 214         } catch (final Exception e) {
 215             handleParseException(e);
 216 
 217             return null;
 218         } finally {
 219             final String end = this + " end '" + scriptName + "'";
 220             if (Timing.isEnabled()) {
 221                 Timing.accumulateTime(toString(), System.currentTimeMillis() - t0);
 222                 LOG.info(end, "' in ", (System.currentTimeMillis() - t0), " ms");
 223             } else {
 224                 LOG.info(end);
 225             }
 226         }
 227     }
 228 
 229     /**
 230      * Parse and return the list of function parameter list. A comma
 231      * separated list of function parameter identifiers is expected to be parsed.
 232      * Errors will be thrown and the error manager will contain information
 233      * if parsing should fail. This method is used to check if parameter Strings
 234      * passed to "Function" constructor is a valid or not.
 235      *
 236      * @return the list of IdentNodes representing the formal parameter list
 237      */
 238     public List<IdentNode> parseFormalParameterList() {
 239         try {
 240             stream = new TokenStream();
 241             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
 242 
 243             // Set up first token (skips opening EOL.)
 244             k = -1;
 245             next();
 246 
 247             return formalParameterList(TokenType.EOF);
 248         } catch (final Exception e) {
 249             handleParseException(e);
 250             return null;
 251         }
 252     }
 253 
 254     /**
 255      * Execute parse and return the resulting function node.
 256      * Errors will be thrown and the error manager will contain information
 257      * if parsing should fail. This method is used to check if code String
 258      * passed to "Function" constructor is a valid function body or not.
 259      *
 260      * @return function node resulting from successful parse
 261      */
 262     public FunctionNode parseFunctionBody() {
 263         try {
 264             stream = new TokenStream();
 265             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
 266 
 267             // Set up first token (skips opening EOL.)
 268             k = -1;
 269             next();
 270 
 271             // Make a fake token for the function.
 272             final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
 273             // Set up the function to append elements.
 274 
 275             FunctionNode function = newFunctionNode(
 276                 functionToken,
 277                 new IdentNode(functionToken, Token.descPosition(functionToken), RUN_SCRIPT.symbolName()),
 278                 new ArrayList<IdentNode>(),
 279                 FunctionNode.Kind.NORMAL);
 280 
 281             functionDeclarations = new ArrayList<>();
 282             sourceElements();
 283             addFunctionDeclarations(function);
 284             functionDeclarations = null;
 285 
 286             expect(EOF);
 287 
 288             function.setFinish(source.getLength() - 1);
 289 
 290             function = restoreFunctionNode(function, token); //commit code
 291             function = function.setBody(lc, function.getBody().setNeedsScope(lc));
 292             return function;
 293         } catch (final Exception e) {
 294             handleParseException(e);
 295             return null;
 296         }
 297     }
 298 
 299     private void handleParseException(final Exception e) {
 300         // Extract message from exception.  The message will be in error
 301         // message format.
 302         String message = e.getMessage();
 303 
 304         // If empty message.
 305         if (message == null) {
 306             message = e.toString();
 307         }
 308 
 309         // Issue message.
 310         if (e instanceof ParserException) {
 311             errors.error((ParserException)e);
 312         } else {
 313             errors.error(message);
 314         }
 315 
 316         if (env._dump_on_error) {
 317             e.printStackTrace(env.getErr());
 318         }
 319     }
 320 
 321     /**
 322      * Skip to a good parsing recovery point.
 323      */
 324     private void recover(final Exception e) {
 325         if (e != null) {
 326             // Extract message from exception.  The message will be in error
 327             // message format.
 328             String message = e.getMessage();
 329 
 330             // If empty message.
 331             if (message == null) {
 332                 message = e.toString();
 333             }
 334 
 335             // Issue message.
 336             if (e instanceof ParserException) {
 337                 errors.error((ParserException)e);
 338             } else {
 339                 errors.error(message);
 340             }
 341 
 342             if (env._dump_on_error) {
 343                 e.printStackTrace(env.getErr());
 344             }
 345         }
 346 
 347         // Skip to a recovery point.
 348 loop:
 349         while (true) {
 350             switch (type) {
 351             case EOF:
 352                 // Can not go any further.
 353                 break loop;
 354             case EOL:
 355             case SEMICOLON:
 356             case RBRACE:
 357                 // Good recovery points.
 358                 next();
 359                 break loop;
 360             default:
 361                 // So we can recover after EOL.
 362                 nextOrEOL();
 363                 break;
 364             }
 365         }
 366     }
 367 
 368     /**
 369      * Set up a new block.
 370      *
 371      * @return New block.
 372      */
 373     private Block newBlock() {
 374         return lc.push(new Block(token, Token.descPosition(token)));
 375     }
 376 
 377     /**
 378      * Set up a new function block.
 379      *
 380      * @param ident Name of function.
 381      * @return New block.
 382      */
 383     private FunctionNode newFunctionNode(final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind) {
 384         // Build function name.
 385         final StringBuilder sb = new StringBuilder();
 386 
 387         final FunctionNode parentFunction = lc.getCurrentFunction();
 388         if (parentFunction != null && !parentFunction.isProgram()) {
 389             sb.append(parentFunction.getName()).append('$');
 390         }
 391 
 392         sb.append(ident != null ? ident.getName() : FUNCTION_PREFIX.symbolName());


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