1 /*
   2  * Copyright (c) 2010, 2015, 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.ANON_FUNCTION_PREFIX;
  29 import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
  30 import static jdk.nashorn.internal.codegen.CompilerConstants.PROGRAM;
  31 import static jdk.nashorn.internal.parser.TokenType.ARROW;
  32 import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
  33 import static jdk.nashorn.internal.parser.TokenType.CASE;
  34 import static jdk.nashorn.internal.parser.TokenType.CATCH;
  35 import static jdk.nashorn.internal.parser.TokenType.CLASS;
  36 import static jdk.nashorn.internal.parser.TokenType.COLON;
  37 import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
  38 import static jdk.nashorn.internal.parser.TokenType.COMMENT;
  39 import static jdk.nashorn.internal.parser.TokenType.CONST;
  40 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
  41 import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
  42 import static jdk.nashorn.internal.parser.TokenType.ELLIPSIS;
  43 import static jdk.nashorn.internal.parser.TokenType.ELSE;
  44 import static jdk.nashorn.internal.parser.TokenType.EOF;
  45 import static jdk.nashorn.internal.parser.TokenType.EOL;
  46 import static jdk.nashorn.internal.parser.TokenType.EQ_STRICT;
  47 import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
  48 import static jdk.nashorn.internal.parser.TokenType.EXPORT;
  49 import static jdk.nashorn.internal.parser.TokenType.EXTENDS;
  50 import static jdk.nashorn.internal.parser.TokenType.FINALLY;
  51 import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
  52 import static jdk.nashorn.internal.parser.TokenType.IDENT;
  53 import static jdk.nashorn.internal.parser.TokenType.IF;
  54 import static jdk.nashorn.internal.parser.TokenType.IMPORT;
  55 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
  56 import static jdk.nashorn.internal.parser.TokenType.LBRACE;
  57 import static jdk.nashorn.internal.parser.TokenType.LBRACKET;
  58 import static jdk.nashorn.internal.parser.TokenType.LET;
  59 import static jdk.nashorn.internal.parser.TokenType.LPAREN;
  60 import static jdk.nashorn.internal.parser.TokenType.MUL;
  61 import static jdk.nashorn.internal.parser.TokenType.PERIOD;
  62 import static jdk.nashorn.internal.parser.TokenType.RBRACE;
  63 import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
  64 import static jdk.nashorn.internal.parser.TokenType.RPAREN;
  65 import static jdk.nashorn.internal.parser.TokenType.SEMICOLON;
  66 import static jdk.nashorn.internal.parser.TokenType.SPREAD_ARRAY;
  67 import static jdk.nashorn.internal.parser.TokenType.STATIC;
  68 import static jdk.nashorn.internal.parser.TokenType.STRING;
  69 import static jdk.nashorn.internal.parser.TokenType.SUPER;
  70 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE;
  71 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_HEAD;
  72 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_MIDDLE;
  73 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_TAIL;
  74 import static jdk.nashorn.internal.parser.TokenType.TERNARY;
  75 import static jdk.nashorn.internal.parser.TokenType.VAR;
  76 import static jdk.nashorn.internal.parser.TokenType.VOID;
  77 import static jdk.nashorn.internal.parser.TokenType.WHILE;
  78 import static jdk.nashorn.internal.parser.TokenType.YIELD;
  79 import static jdk.nashorn.internal.parser.TokenType.YIELD_STAR;
  80 
  81 import java.io.Serializable;
  82 import java.util.ArrayDeque;
  83 import java.util.ArrayList;
  84 import java.util.Collections;
  85 import java.util.Deque;
  86 import java.util.HashMap;
  87 import java.util.HashSet;
  88 import java.util.Iterator;
  89 import java.util.List;
  90 import java.util.Map;
  91 import java.util.Objects;
  92 import java.util.function.Consumer;
  93 import jdk.nashorn.internal.codegen.CompilerConstants;
  94 import jdk.nashorn.internal.codegen.Namespace;
  95 import jdk.nashorn.internal.ir.AccessNode;
  96 import jdk.nashorn.internal.ir.BaseNode;
  97 import jdk.nashorn.internal.ir.BinaryNode;
  98 import jdk.nashorn.internal.ir.Block;
  99 import jdk.nashorn.internal.ir.BlockStatement;
 100 import jdk.nashorn.internal.ir.BreakNode;
 101 import jdk.nashorn.internal.ir.CallNode;
 102 import jdk.nashorn.internal.ir.CaseNode;
 103 import jdk.nashorn.internal.ir.CatchNode;
 104 import jdk.nashorn.internal.ir.ClassNode;
 105 import jdk.nashorn.internal.ir.ContinueNode;
 106 import jdk.nashorn.internal.ir.DebuggerNode;
 107 import jdk.nashorn.internal.ir.EmptyNode;
 108 import jdk.nashorn.internal.ir.ErrorNode;
 109 import jdk.nashorn.internal.ir.Expression;
 110 import jdk.nashorn.internal.ir.ExpressionList;
 111 import jdk.nashorn.internal.ir.ExpressionStatement;
 112 import jdk.nashorn.internal.ir.ForNode;
 113 import jdk.nashorn.internal.ir.FunctionNode;
 114 import jdk.nashorn.internal.ir.IdentNode;
 115 import jdk.nashorn.internal.ir.IfNode;
 116 import jdk.nashorn.internal.ir.IndexNode;
 117 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
 118 import jdk.nashorn.internal.ir.LabelNode;
 119 import jdk.nashorn.internal.ir.LexicalContext;
 120 import jdk.nashorn.internal.ir.LiteralNode;
 121 import jdk.nashorn.internal.ir.Module;
 122 import jdk.nashorn.internal.ir.Node;
 123 import jdk.nashorn.internal.ir.ObjectNode;
 124 import jdk.nashorn.internal.ir.PropertyKey;
 125 import jdk.nashorn.internal.ir.PropertyNode;
 126 import jdk.nashorn.internal.ir.ReturnNode;
 127 import jdk.nashorn.internal.ir.RuntimeNode;
 128 import jdk.nashorn.internal.ir.Statement;
 129 import jdk.nashorn.internal.ir.SwitchNode;
 130 import jdk.nashorn.internal.ir.TemplateLiteral;
 131 import jdk.nashorn.internal.ir.TernaryNode;
 132 import jdk.nashorn.internal.ir.ThrowNode;
 133 import jdk.nashorn.internal.ir.TryNode;
 134 import jdk.nashorn.internal.ir.UnaryNode;
 135 import jdk.nashorn.internal.ir.VarNode;
 136 import jdk.nashorn.internal.ir.WhileNode;
 137 import jdk.nashorn.internal.ir.WithNode;
 138 import jdk.nashorn.internal.ir.debug.ASTWriter;
 139 import jdk.nashorn.internal.ir.debug.PrintVisitor;
 140 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 141 import jdk.nashorn.internal.runtime.Context;
 142 import jdk.nashorn.internal.runtime.ErrorManager;
 143 import jdk.nashorn.internal.runtime.JSErrorType;
 144 import jdk.nashorn.internal.runtime.ParserException;
 145 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 146 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 147 import jdk.nashorn.internal.runtime.ScriptFunctionData;
 148 import jdk.nashorn.internal.runtime.ScriptingFunctions;
 149 import jdk.nashorn.internal.runtime.Source;
 150 import jdk.nashorn.internal.runtime.Timing;
 151 import jdk.nashorn.internal.runtime.linker.NameCodec;
 152 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 153 import jdk.nashorn.internal.runtime.logging.Loggable;
 154 import jdk.nashorn.internal.runtime.logging.Logger;
 155 
 156 /**
 157  * Builds the IR.
 158  */
 159 @Logger(name="parser")
 160 public class Parser extends AbstractParser implements Loggable {
 161     private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName();
 162     private static final String CONSTRUCTOR_NAME = "constructor";
 163     private static final String GET_NAME = "get";
 164     private static final String SET_NAME = "set";
 165 
 166     /** Current env. */
 167     private final ScriptEnvironment env;
 168 
 169     /** Is scripting mode. */
 170     private final boolean scripting;
 171 
 172     private List<Statement> functionDeclarations;
 173 
 174     private final ParserContext lc;
 175     private final Deque<Object> defaultNames;
 176 
 177     /** Namespace for function names where not explicitly given */
 178     private final Namespace namespace;
 179 
 180     private final DebugLogger log;
 181 
 182     /** to receive line information from Lexer when scanning multine literals. */
 183     protected final Lexer.LineInfoReceiver lineInfoReceiver;
 184 
 185     private RecompilableScriptFunctionData reparsedFunction;
 186 
 187     /**
 188      * Constructor
 189      *
 190      * @param env     script environment
 191      * @param source  source to parse
 192      * @param errors  error manager
 193      */
 194     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors) {
 195         this(env, source, errors, env._strict, null);
 196     }
 197 
 198     /**
 199      * Constructor
 200      *
 201      * @param env     script environment
 202      * @param source  source to parse
 203      * @param errors  error manager
 204      * @param strict  strict
 205      * @param log debug logger if one is needed
 206      */
 207     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) {
 208         this(env, source, errors, strict, 0, log);
 209     }
 210 
 211     /**
 212      * Construct a parser.
 213      *
 214      * @param env     script environment
 215      * @param source  source to parse
 216      * @param errors  error manager
 217      * @param strict  parser created with strict mode enabled.
 218      * @param lineOffset line offset to start counting lines from
 219      * @param log debug logger if one is needed
 220      */
 221     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) {
 222         super(source, errors, strict, lineOffset);
 223         this.lc = new ParserContext();
 224         this.defaultNames = new ArrayDeque<>();
 225         this.env = env;
 226         this.namespace = new Namespace(env.getNamespace());
 227         this.scripting = env._scripting;
 228         if (this.scripting) {
 229             this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
 230                 @Override
 231                 public void lineInfo(final int receiverLine, final int receiverLinePosition) {
 232                     // update the parser maintained line information
 233                     Parser.this.line = receiverLine;
 234                     Parser.this.linePosition = receiverLinePosition;
 235                 }
 236             };
 237         } else {
 238             // non-scripting mode script can't have multi-line literals
 239             this.lineInfoReceiver = null;
 240         }
 241 
 242         this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
 243     }
 244 
 245     @Override
 246     public DebugLogger getLogger() {
 247         return log;
 248     }
 249 
 250     @Override
 251     public DebugLogger initLogger(final Context context) {
 252         return context.getLogger(this.getClass());
 253     }
 254 
 255     /**
 256      * Sets the name for the first function. This is only used when reparsing anonymous functions to ensure they can
 257      * preserve their already assigned name, as that name doesn't appear in their source text.
 258      * @param name the name for the first parsed function.
 259      */
 260     public void setFunctionName(final String name) {
 261         defaultNames.push(createIdentNode(0, 0, name));
 262     }
 263 
 264     /**
 265      * Sets the {@link RecompilableScriptFunctionData} representing the function being reparsed (when this
 266      * parser instance is used to reparse a previously parsed function, as part of its on-demand compilation).
 267      * This will trigger various special behaviors, such as skipping nested function bodies.
 268      * @param reparsedFunction the function being reparsed.
 269      */
 270     public void setReparsedFunction(final RecompilableScriptFunctionData reparsedFunction) {
 271         this.reparsedFunction = reparsedFunction;
 272     }
 273 
 274     /**
 275      * Execute parse and return the resulting function node.
 276      * Errors will be thrown and the error manager will contain information
 277      * if parsing should fail
 278      *
 279      * This is the default parse call, which will name the function node
 280      * {code :program} {@link CompilerConstants#PROGRAM}
 281      *
 282      * @return function node resulting from successful parse
 283      */
 284     public FunctionNode parse() {
 285         return parse(PROGRAM.symbolName(), 0, source.getLength(), 0);
 286     }
 287 
 288     /**
 289      * Set up first token. Skips opening EOL.
 290      */
 291     private void scanFirstToken() {
 292         k = -1;
 293         next();
 294     }
 295 
 296     /**
 297      * Execute parse and return the resulting function node.
 298      * Errors will be thrown and the error manager will contain information
 299      * if parsing should fail
 300      *
 301      * This should be used to create one and only one function node
 302      *
 303      * @param scriptName name for the script, given to the parsed FunctionNode
 304      * @param startPos start position in source
 305      * @param len length of parse
 306      * @param reparseFlags flags provided by {@link RecompilableScriptFunctionData} as context for
 307      * the code being reparsed. This allows us to recognize special forms of functions such
 308      * as property getters and setters or instances of ES6 method shorthand in object literals.
 309      *
 310      * @return function node resulting from successful parse
 311      */
 312     public FunctionNode parse(final String scriptName, final int startPos, final int len, final int reparseFlags) {
 313         final boolean isTimingEnabled = env.isTimingEnabled();
 314         final long t0 = isTimingEnabled ? System.nanoTime() : 0L;
 315         log.info(this, " begin for '", scriptName, "'");
 316 
 317         try {
 318             stream = new TokenStream();
 319             lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
 320             lexer.line = lexer.pendingLine = lineOffset + 1;
 321             line = lineOffset;
 322 
 323             scanFirstToken();
 324             // Begin parse.
 325             return program(scriptName, reparseFlags);
 326         } catch (final Exception e) {
 327             handleParseException(e);
 328 
 329             return null;
 330         } finally {
 331             final String end = this + " end '" + scriptName + "'";
 332             if (isTimingEnabled) {
 333                 env._timing.accumulateTime(toString(), System.nanoTime() - t0);
 334                 log.info(end, "' in ", Timing.toMillisPrint(System.nanoTime() - t0), " ms");
 335             } else {
 336                 log.info(end);
 337             }
 338         }
 339     }
 340 
 341     /**
 342      * Parse and return the resulting module.
 343      * Errors will be thrown and the error manager will contain information
 344      * if parsing should fail
 345      *
 346      * @param moduleName name for the module, given to the parsed FunctionNode
 347      * @param startPos start position in source
 348      * @param len length of parse
 349      *
 350      * @return function node resulting from successful parse
 351      */
 352     public FunctionNode parseModule(final String moduleName, final int startPos, final int len) {
 353         try {
 354             stream = new TokenStream();
 355             lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
 356             lexer.line = lexer.pendingLine = lineOffset + 1;
 357             line = lineOffset;
 358 
 359             scanFirstToken();
 360             // Begin parse.
 361             return module(moduleName);
 362         } catch (final Exception e) {
 363             handleParseException(e);
 364 
 365             return null;
 366         }
 367     }
 368 
 369     /**
 370      * Entry point for parsing a module.
 371      *
 372      * @param moduleName the module name
 373      * @return the parsed module
 374      */
 375     public FunctionNode parseModule(final String moduleName) {
 376         return parseModule(moduleName, 0, source.getLength());
 377     }
 378 
 379     /**
 380      * Parse and return the list of function parameter list. A comma
 381      * separated list of function parameter identifiers is expected to be parsed.
 382      * Errors will be thrown and the error manager will contain information
 383      * if parsing should fail. This method is used to check if parameter Strings
 384      * passed to "Function" constructor is a valid or not.
 385      *
 386      * @return the list of IdentNodes representing the formal parameter list
 387      */
 388     public List<IdentNode> parseFormalParameterList() {
 389         try {
 390             stream = new TokenStream();
 391             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
 392 
 393             scanFirstToken();
 394 
 395             return formalParameterList(TokenType.EOF, false);
 396         } catch (final Exception e) {
 397             handleParseException(e);
 398             return null;
 399         }
 400     }
 401 
 402     /**
 403      * Execute parse and return the resulting function node.
 404      * Errors will be thrown and the error manager will contain information
 405      * if parsing should fail. This method is used to check if code String
 406      * passed to "Function" constructor is a valid function body or not.
 407      *
 408      * @return function node resulting from successful parse
 409      */
 410     public FunctionNode parseFunctionBody() {
 411         try {
 412             stream = new TokenStream();
 413             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
 414             final int functionLine = line;
 415 
 416             scanFirstToken();
 417 
 418             // Make a fake token for the function.
 419             final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
 420             // Set up the function to append elements.
 421 
 422             final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName());
 423             final ParserContextFunctionNode function = createParserContextFunctionNode(ident, functionToken, FunctionNode.Kind.NORMAL, functionLine, Collections.<IdentNode>emptyList());
 424             lc.push(function);
 425 
 426             final ParserContextBlockNode body = newBlock();
 427 
 428             functionDeclarations = new ArrayList<>();
 429             sourceElements(0);
 430             addFunctionDeclarations(function);
 431             functionDeclarations = null;
 432 
 433             restoreBlock(body);
 434             body.setFlag(Block.NEEDS_SCOPE);
 435 
 436             final Block functionBody = new Block(functionToken, source.getLength() - 1,
 437                 body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
 438             lc.pop(function);
 439 
 440             expect(EOF);
 441 
 442             final FunctionNode functionNode = createFunctionNode(
 443                     function,
 444                     functionToken,
 445                     ident,
 446                     Collections.<IdentNode>emptyList(),
 447                     FunctionNode.Kind.NORMAL,
 448                     functionLine,
 449                     functionBody);
 450             printAST(functionNode);
 451             return functionNode;
 452         } catch (final Exception e) {
 453             handleParseException(e);
 454             return null;
 455         }
 456     }
 457 
 458     private void handleParseException(final Exception e) {
 459         // Extract message from exception.  The message will be in error
 460         // message format.
 461         String message = e.getMessage();
 462 
 463         // If empty message.
 464         if (message == null) {
 465             message = e.toString();
 466         }
 467 
 468         // Issue message.
 469         if (e instanceof ParserException) {
 470             errors.error((ParserException)e);
 471         } else {
 472             errors.error(message);
 473         }
 474 
 475         if (env._dump_on_error) {
 476             e.printStackTrace(env.getErr());
 477         }
 478     }
 479 
 480     /**
 481      * Skip to a good parsing recovery point.
 482      */
 483     private void recover(final Exception e) {
 484         if (e != null) {
 485             // Extract message from exception.  The message will be in error
 486             // message format.
 487             String message = e.getMessage();
 488 
 489             // If empty message.
 490             if (message == null) {
 491                 message = e.toString();
 492             }
 493 
 494             // Issue message.
 495             if (e instanceof ParserException) {
 496                 errors.error((ParserException)e);
 497             } else {
 498                 errors.error(message);
 499             }
 500 
 501             if (env._dump_on_error) {
 502                 e.printStackTrace(env.getErr());
 503             }
 504         }
 505 
 506         // Skip to a recovery point.
 507         loop:
 508         while (true) {
 509             switch (type) {
 510             case EOF:
 511                 // Can not go any further.
 512                 break loop;
 513             case EOL:
 514             case SEMICOLON:
 515             case RBRACE:
 516                 // Good recovery points.
 517                 next();
 518                 break loop;
 519             default:
 520                 // So we can recover after EOL.
 521                 nextOrEOL();
 522                 break;
 523             }
 524         }
 525     }
 526 
 527     /**
 528      * Set up a new block.
 529      *
 530      * @return New block.
 531      */
 532     private ParserContextBlockNode newBlock() {
 533         return lc.push(new ParserContextBlockNode(token));
 534     }
 535 
 536     private ParserContextFunctionNode createParserContextFunctionNode(final IdentNode ident, final long functionToken, final FunctionNode.Kind kind, final int functionLine, final List<IdentNode> parameters) {
 537         // Build function name.
 538         final StringBuilder sb = new StringBuilder();
 539 
 540         final ParserContextFunctionNode parentFunction = lc.getCurrentFunction();
 541         if (parentFunction != null && !parentFunction.isProgram()) {
 542             sb.append(parentFunction.getName()).append(CompilerConstants.NESTED_FUNCTION_SEPARATOR.symbolName());
 543         }
 544 
 545         assert ident.getName() != null;
 546         sb.append(ident.getName());
 547 
 548         final String name = namespace.uniqueName(sb.toString());
 549         assert parentFunction != null || kind == FunctionNode.Kind.MODULE || name.equals(PROGRAM.symbolName()) : "name = " + name;
 550 
 551         int flags = 0;
 552         if (isStrictMode) {
 553             flags |= FunctionNode.IS_STRICT;
 554         }
 555         if (parentFunction == null) {
 556             flags |= FunctionNode.IS_PROGRAM;
 557         }
 558 
 559         final ParserContextFunctionNode functionNode = new ParserContextFunctionNode(functionToken, ident, name, namespace, functionLine, kind, parameters);
 560         functionNode.setFlag(flags);
 561         return functionNode;
 562     }
 563 
 564     private FunctionNode createFunctionNode(final ParserContextFunctionNode function, final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine, final Block body) {
 565         // assert body.isFunctionBody() || body.getFlag(Block.IS_PARAMETER_BLOCK) && ((BlockStatement) body.getLastStatement()).getBlock().isFunctionBody();
 566         // Start new block.
 567         final FunctionNode functionNode =
 568             new FunctionNode(
 569                 source,
 570                 functionLine,
 571                 body.getToken(),
 572                 Token.descPosition(body.getToken()),
 573                 startToken,
 574                 function.getLastToken(),
 575                 namespace,
 576                 ident,
 577                 function.getName(),
 578                 parameters,
 579                 function.getParameterExpressions(),
 580                 kind,
 581                 function.getFlags(),
 582                 body,
 583                 function.getEndParserState(),
 584                 function.getModule(),
 585                 function.getDebugFlags());
 586 
 587         printAST(functionNode);
 588 
 589         return functionNode;
 590     }
 591 
 592     /**
 593      * Restore the current block.
 594      */
 595     private ParserContextBlockNode restoreBlock(final ParserContextBlockNode block) {
 596         return lc.pop(block);
 597     }
 598 
 599     /**
 600      * Get the statements in a block.
 601      * @return Block statements.
 602      */
 603     private Block getBlock(final boolean needsBraces) {
 604         final long blockToken = token;
 605         final ParserContextBlockNode newBlock = newBlock();
 606         try {
 607             // Block opening brace.
 608             if (needsBraces) {
 609                 expect(LBRACE);
 610             }
 611             // Accumulate block statements.
 612             statementList();
 613 
 614         } finally {
 615             restoreBlock(newBlock);
 616         }
 617 
 618         // Block closing brace.
 619         if (needsBraces) {
 620             expect(RBRACE);
 621         }
 622 
 623         final int flags = newBlock.getFlags() | (needsBraces ? 0 : Block.IS_SYNTHETIC);
 624         return new Block(blockToken, finish, flags, newBlock.getStatements());
 625     }
 626 
 627     /**
 628      * Get all the statements generated by a single statement.
 629      * @return Statements.
 630      */
 631     private Block getStatement() {
 632         return getStatement(false);
 633     }
 634 
 635     private Block getStatement(final boolean labelledStatement) {
 636         if (type == LBRACE) {
 637             return getBlock(true);
 638         }
 639         // Set up new block. Captures first token.
 640         final ParserContextBlockNode newBlock = newBlock();
 641         try {
 642             statement(false, 0, true, labelledStatement);
 643         } finally {
 644             restoreBlock(newBlock);
 645         }
 646         return new Block(newBlock.getToken(), finish, newBlock.getFlags() | Block.IS_SYNTHETIC, newBlock.getStatements());
 647     }
 648 
 649     /**
 650      * Detect calls to special functions.
 651      * @param ident Called function.
 652      */
 653     private void detectSpecialFunction(final IdentNode ident) {
 654         final String name = ident.getName();
 655 
 656         if (EVAL.symbolName().equals(name)) {
 657             markEval(lc);
 658         } else if (SUPER.getName().equals(name)) {
 659             assert ident.isDirectSuper();
 660             markSuperCall(lc);
 661         }
 662     }
 663 
 664     /**
 665      * Detect use of special properties.
 666      * @param ident Referenced property.
 667      */
 668     private void detectSpecialProperty(final IdentNode ident) {
 669         if (isArguments(ident)) {
 670             // skip over arrow functions, e.g. function f() { return (() => arguments.length)(); }
 671             getCurrentNonArrowFunction().setFlag(FunctionNode.USES_ARGUMENTS);
 672         }
 673     }
 674 
 675     private boolean useBlockScope() {
 676         return env._es6;
 677     }
 678 
 679     private boolean isES6() {
 680         return env._es6;
 681     }
 682 
 683     private static boolean isArguments(final String name) {
 684         return ARGUMENTS_NAME.equals(name);
 685     }
 686 
 687     static boolean isArguments(final IdentNode ident) {
 688         return isArguments(ident.getName());
 689     }
 690 
 691     /**
 692      * Tells whether a IdentNode can be used as L-value of an assignment
 693      *
 694      * @param ident IdentNode to be checked
 695      * @return whether the ident can be used as L-value
 696      */
 697     private static boolean checkIdentLValue(final IdentNode ident) {
 698         return ident.tokenType().getKind() != TokenKind.KEYWORD;
 699     }
 700 
 701     /**
 702      * Verify an assignment expression.
 703      * @param op  Operation token.
 704      * @param lhs Left hand side expression.
 705      * @param rhs Right hand side expression.
 706      * @return Verified expression.
 707      */
 708     private Expression verifyAssignment(final long op, final Expression lhs, final Expression rhs) {
 709         final TokenType opType = Token.descType(op);
 710 
 711         switch (opType) {
 712         case ASSIGN:
 713         case ASSIGN_ADD:
 714         case ASSIGN_BIT_AND:
 715         case ASSIGN_BIT_OR:
 716         case ASSIGN_BIT_XOR:
 717         case ASSIGN_DIV:
 718         case ASSIGN_MOD:
 719         case ASSIGN_MUL:
 720         case ASSIGN_SAR:
 721         case ASSIGN_SHL:
 722         case ASSIGN_SHR:
 723         case ASSIGN_SUB:
 724             if (lhs instanceof IdentNode) {
 725                 if (!checkIdentLValue((IdentNode)lhs)) {
 726                     return referenceError(lhs, rhs, false);
 727                 }
 728                 verifyIdent((IdentNode)lhs, "assignment");
 729                 break;
 730             } else if (lhs instanceof AccessNode || lhs instanceof IndexNode) {
 731                 break;
 732             } else if (opType == ASSIGN && isDestructuringLhs(lhs)) {
 733                 verifyDestructuringAssignmentPattern(lhs, "assignment");
 734                 break;
 735             } else {
 736                 return referenceError(lhs, rhs, env._early_lvalue_error);
 737             }
 738         default:
 739             break;
 740         }
 741 
 742         // Build up node.
 743         if(BinaryNode.isLogical(opType)) {
 744             return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs));
 745         }
 746         return new BinaryNode(op, lhs, rhs);
 747     }
 748 
 749     private boolean isDestructuringLhs(final Expression lhs) {
 750         if (lhs instanceof ObjectNode || lhs instanceof LiteralNode.ArrayLiteralNode) {
 751             return isES6();
 752         }
 753         return false;
 754     }
 755 
 756     private void verifyDestructuringAssignmentPattern(final Expression pattern, final String contextString) {
 757         assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
 758         pattern.accept(new VerifyDestructuringPatternNodeVisitor(new LexicalContext()) {
 759             @Override
 760             protected void verifySpreadElement(final Expression lvalue) {
 761                 if (!checkValidLValue(lvalue, contextString)) {
 762                     throw error(AbstractParser.message("invalid.lvalue"), lvalue.getToken());
 763                 }
 764             }
 765 
 766             @Override
 767             public boolean enterIdentNode(final IdentNode identNode) {
 768                 verifyIdent(identNode, contextString);
 769                 if (!checkIdentLValue(identNode)) {
 770                     referenceError(identNode, null, true);
 771                     return false;
 772                 }
 773                 return false;
 774             }
 775 
 776             @Override
 777             public boolean enterAccessNode(final AccessNode accessNode) {
 778                 return false;
 779             }
 780 
 781             @Override
 782             public boolean enterIndexNode(final IndexNode indexNode) {
 783                 return false;
 784             }
 785 
 786             @Override
 787             protected boolean enterDefault(final Node node) {
 788                 throw error(String.format("unexpected node in AssignmentPattern: %s", node));
 789             }
 790         });
 791     }
 792 
 793     /**
 794      * Reduce increment/decrement to simpler operations.
 795      * @param firstToken First token.
 796      * @param tokenType  Operation token (INCPREFIX/DEC.)
 797      * @param expression Left hand side expression.
 798      * @param isPostfix  Prefix or postfix.
 799      * @return           Reduced expression.
 800      */
 801     private static UnaryNode incDecExpression(final long firstToken, final TokenType tokenType, final Expression expression, final boolean isPostfix) {
 802         if (isPostfix) {
 803             return new UnaryNode(Token.recast(firstToken, tokenType == DECPREFIX ? DECPOSTFIX : INCPOSTFIX), expression.getStart(), Token.descPosition(firstToken) + Token.descLength(firstToken), expression);
 804         }
 805 
 806         return new UnaryNode(firstToken, expression);
 807     }
 808 
 809     /**
 810      * -----------------------------------------------------------------------
 811      *
 812      * Grammar based on
 813      *
 814      *      ECMAScript Language Specification
 815      *      ECMA-262 5th Edition / December 2009
 816      *
 817      * -----------------------------------------------------------------------
 818      */
 819 
 820     /**
 821      * Program :
 822      *      SourceElements?
 823      *
 824      * See 14
 825      *
 826      * Parse the top level script.
 827      */
 828     private FunctionNode program(final String scriptName, final int reparseFlags) {
 829         // Make a pseudo-token for the script holding its start and length.
 830         final long functionToken = Token.toDesc(FUNCTION, Token.descPosition(Token.withDelimiter(token)), source.getLength());
 831         final int  functionLine  = line;
 832 
 833         final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), scriptName);
 834         final ParserContextFunctionNode script = createParserContextFunctionNode(
 835                 ident,
 836                 functionToken,
 837                 FunctionNode.Kind.SCRIPT,
 838                 functionLine,
 839                 Collections.<IdentNode>emptyList());
 840         lc.push(script);
 841         final ParserContextBlockNode body = newBlock();
 842 
 843         functionDeclarations = new ArrayList<>();
 844         sourceElements(reparseFlags);
 845         addFunctionDeclarations(script);
 846         functionDeclarations = null;
 847 
 848         restoreBlock(body);
 849         body.setFlag(Block.NEEDS_SCOPE);
 850         final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
 851         lc.pop(script);
 852         script.setLastToken(token);
 853 
 854         expect(EOF);
 855 
 856         return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.SCRIPT, functionLine, programBody);
 857     }
 858 
 859     /**
 860      * Directive value or null if statement is not a directive.
 861      *
 862      * @param stmt Statement to be checked
 863      * @return Directive value if the given statement is a directive
 864      */
 865     private String getDirective(final Node stmt) {
 866         if (stmt instanceof ExpressionStatement) {
 867             final Node expr = ((ExpressionStatement)stmt).getExpression();
 868             if (expr instanceof LiteralNode) {
 869                 final LiteralNode<?> lit = (LiteralNode<?>)expr;
 870                 final long litToken = lit.getToken();
 871                 final TokenType tt = Token.descType(litToken);
 872                 // A directive is either a string or an escape string
 873                 if (tt == TokenType.STRING || tt == TokenType.ESCSTRING) {
 874                     // Make sure that we don't unescape anything. Return as seen in source!
 875                     return source.getString(lit.getStart(), Token.descLength(litToken));
 876                 }
 877             }
 878         }
 879 
 880         return null;
 881     }
 882 
 883     /**
 884      * SourceElements :
 885      *      SourceElement
 886      *      SourceElements SourceElement
 887      *
 888      * See 14
 889      *
 890      * Parse the elements of the script or function.
 891      */
 892     private void sourceElements(final int reparseFlags) {
 893         List<Node>    directiveStmts        = null;
 894         boolean       checkDirective        = true;
 895         int           functionFlags          = reparseFlags;
 896         final boolean oldStrictMode         = isStrictMode;
 897 
 898 
 899         try {
 900             // If is a script, then process until the end of the script.
 901             while (type != EOF) {
 902                 // Break if the end of a code block.
 903                 if (type == RBRACE) {
 904                     break;
 905                 }
 906 
 907                 try {
 908                     // Get the next element.
 909                     statement(true, functionFlags, false, false);
 910                     functionFlags = 0;
 911 
 912                     // check for directive prologues
 913                     if (checkDirective) {
 914                         // skip any debug statement like line number to get actual first line
 915                         final Statement lastStatement = lc.getLastStatement();
 916 
 917                         // get directive prologue, if any
 918                         final String directive = getDirective(lastStatement);
 919 
 920                         // If we have seen first non-directive statement,
 921                         // no more directive statements!!
 922                         checkDirective = directive != null;
 923 
 924                         if (checkDirective) {
 925                             if (!oldStrictMode) {
 926                                 if (directiveStmts == null) {
 927                                     directiveStmts = new ArrayList<>();
 928                                 }
 929                                 directiveStmts.add(lastStatement);
 930                             }
 931 
 932                             // handle use strict directive
 933                             if ("use strict".equals(directive)) {
 934                                 isStrictMode = true;
 935                                 final ParserContextFunctionNode function = lc.getCurrentFunction();
 936                                 function.setFlag(FunctionNode.IS_STRICT);
 937 
 938                                 // We don't need to check these, if lexical environment is already strict
 939                                 if (!oldStrictMode && directiveStmts != null) {
 940                                     // check that directives preceding this one do not violate strictness
 941                                     for (final Node statement : directiveStmts) {
 942                                         // the get value will force unescape of preceding
 943                                         // escaped string directives
 944                                         getValue(statement.getToken());
 945                                     }
 946 
 947                                     // verify that function name as well as parameter names
 948                                     // satisfy strict mode restrictions.
 949                                     verifyIdent(function.getIdent(), "function name");
 950                                     for (final IdentNode param : function.getParameters()) {
 951                                         verifyIdent(param, "function parameter");
 952                                     }
 953                                 }
 954                             } else if (Context.DEBUG) {
 955                                 final int debugFlag = FunctionNode.getDirectiveFlag(directive);
 956                                 if (debugFlag != 0) {
 957                                     final ParserContextFunctionNode function = lc.getCurrentFunction();
 958                                     function.setDebugFlag(debugFlag);
 959                                 }
 960                             }
 961                         }
 962                     }
 963                 } catch (final Exception e) {
 964                     final int errorLine = line;
 965                     final long errorToken = token;
 966                     //recover parsing
 967                     recover(e);
 968                     final ErrorNode errorExpr = new ErrorNode(errorToken, finish);
 969                     final ExpressionStatement expressionStatement = new ExpressionStatement(errorLine, errorToken, finish, errorExpr);
 970                     appendStatement(expressionStatement);
 971                 }
 972 
 973                 // No backtracking from here on.
 974                 stream.commit(k);
 975             }
 976         } finally {
 977             isStrictMode = oldStrictMode;
 978         }
 979     }
 980 
 981     /**
 982      * Parse any of the basic statement types.
 983      *
 984      * Statement :
 985      *      BlockStatement
 986      *      VariableStatement
 987      *      EmptyStatement
 988      *      ExpressionStatement
 989      *      IfStatement
 990      *      BreakableStatement
 991      *      ContinueStatement
 992      *      BreakStatement
 993      *      ReturnStatement
 994      *      WithStatement
 995      *      LabelledStatement
 996      *      ThrowStatement
 997      *      TryStatement
 998      *      DebuggerStatement
 999      *
1000      * BreakableStatement :
1001      *      IterationStatement
1002      *      SwitchStatement
1003      *
1004      * BlockStatement :
1005      *      Block
1006      *
1007      * Block :
1008      *      { StatementList opt }
1009      *
1010      * StatementList :
1011      *      StatementListItem
1012      *      StatementList StatementListItem
1013      *
1014      * StatementItem :
1015      *      Statement
1016      *      Declaration
1017      *
1018      * Declaration :
1019      *     HoistableDeclaration
1020      *     ClassDeclaration
1021      *     LexicalDeclaration
1022      *
1023      * HoistableDeclaration :
1024      *     FunctionDeclaration
1025      *     GeneratorDeclaration
1026      */
1027     private void statement() {
1028         statement(false, 0, false, false);
1029     }
1030 
1031     /**
1032      * @param topLevel does this statement occur at the "top level" of a script or a function?
1033      * @param reparseFlags reparse flags to decide whether to allow property "get" and "set" functions or ES6 methods.
1034      * @param singleStatement are we in a single statement context?
1035      */
1036     private void statement(final boolean topLevel, final int reparseFlags, final boolean singleStatement, final boolean labelledStatement) {
1037         switch (type) {
1038         case LBRACE:
1039             block();
1040             break;
1041         case VAR:
1042             variableStatement(type);
1043             break;
1044         case SEMICOLON:
1045             emptyStatement();
1046             break;
1047         case IF:
1048             ifStatement();
1049             break;
1050         case FOR:
1051             forStatement();
1052             break;
1053         case WHILE:
1054             whileStatement();
1055             break;
1056         case DO:
1057             doStatement();
1058             break;
1059         case CONTINUE:
1060             continueStatement();
1061             break;
1062         case BREAK:
1063             breakStatement();
1064             break;
1065         case RETURN:
1066             returnStatement();
1067             break;
1068         case WITH:
1069             withStatement();
1070             break;
1071         case SWITCH:
1072             switchStatement();
1073             break;
1074         case THROW:
1075             throwStatement();
1076             break;
1077         case TRY:
1078             tryStatement();
1079             break;
1080         case DEBUGGER:
1081             debuggerStatement();
1082             break;
1083         case RPAREN:
1084         case RBRACKET:
1085         case EOF:
1086             expect(SEMICOLON);
1087             break;
1088         case FUNCTION:
1089             // As per spec (ECMA section 12), function declarations as arbitrary statement
1090             // is not "portable". Implementation can issue a warning or disallow the same.
1091             if (singleStatement) {
1092                 // ES6 B.3.2 Labelled Function Declarations
1093                 // It is a Syntax Error if any strict mode source code matches this rule:
1094                 // LabelledItem : FunctionDeclaration.
1095                 if (!labelledStatement || isStrictMode) {
1096                     throw error(AbstractParser.message("expected.stmt", "function declaration"), token);
1097                 }
1098             }
1099             functionExpression(true, topLevel || labelledStatement);
1100             return;
1101         default:
1102             if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(false) || type == CONST)) {
1103                 if (singleStatement) {
1104                     throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
1105                 }
1106                 variableStatement(type);
1107                 break;
1108             } else if (type == CLASS && isES6()) {
1109                 if (singleStatement) {
1110                     throw error(AbstractParser.message("expected.stmt", "class declaration"), token);
1111                 }
1112                 classDeclaration(false);
1113                 break;
1114             }
1115             if (env._const_as_var && type == CONST) {
1116                 variableStatement(TokenType.VAR);
1117                 break;
1118             }
1119 
1120             if (type == IDENT || isNonStrictModeIdent()) {
1121                 if (T(k + 1) == COLON) {
1122                     labelStatement();
1123                     return;
1124                 }
1125 
1126                 if ((reparseFlags & ScriptFunctionData.IS_PROPERTY_ACCESSOR) != 0) {
1127                     final String ident = (String) getValue();
1128                     final long propertyToken = token;
1129                     final int propertyLine = line;
1130                     if (GET_NAME.equals(ident)) {
1131                         next();
1132                         addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
1133                         return;
1134                     } else if (SET_NAME.equals(ident)) {
1135                         next();
1136                         addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
1137                         return;
1138                     }
1139                 }
1140             }
1141 
1142             if ((reparseFlags & ScriptFunctionData.IS_ES6_METHOD) != 0
1143                     && (type == IDENT || type == LBRACKET || isNonStrictModeIdent())) {
1144                 final String ident = (String)getValue();
1145                 final long propertyToken = token;
1146                 final int propertyLine = line;
1147                 final Expression propertyKey = propertyName();
1148 
1149                 // Code below will need refinement once we fully support ES6 class syntax
1150                 final int flags = CONSTRUCTOR_NAME.equals(ident) ? FunctionNode.ES6_IS_CLASS_CONSTRUCTOR : FunctionNode.ES6_IS_METHOD;
1151                 addPropertyFunctionStatement(propertyMethodFunction(propertyKey, propertyToken, propertyLine, false, flags, false));
1152                 return;
1153             }
1154 
1155             expressionStatement();
1156             break;
1157         }
1158     }
1159 
1160     private void addPropertyFunctionStatement(final PropertyFunction propertyFunction) {
1161         final FunctionNode fn = propertyFunction.functionNode;
1162         functionDeclarations.add(new ExpressionStatement(fn.getLineNumber(), fn.getToken(), finish, fn));
1163     }
1164 
1165     /**
1166      * ClassDeclaration[Yield, Default] :
1167      *   class BindingIdentifier[?Yield] ClassTail[?Yield]
1168      *   [+Default] class ClassTail[?Yield]
1169      */
1170     private ClassNode classDeclaration(final boolean isDefault) {
1171         final int classLineNumber = line;
1172 
1173         final ClassNode classExpression = classExpression(!isDefault);
1174 
1175         if (!isDefault) {
1176             final VarNode classVar = new VarNode(classLineNumber, classExpression.getToken(), classExpression.getIdent().getFinish(), classExpression.getIdent(), classExpression, VarNode.IS_CONST);
1177             appendStatement(classVar);
1178         }
1179         return classExpression;
1180     }
1181 
1182     /**
1183      * ClassExpression[Yield] :
1184      *   class BindingIdentifier[?Yield]opt ClassTail[?Yield]
1185      */
1186     private ClassNode classExpression(final boolean isStatement) {
1187         assert type == CLASS;
1188         final int classLineNumber = line;
1189         final long classToken = token;
1190         next();
1191 
1192         IdentNode className = null;
1193         if (isStatement || type == IDENT) {
1194             className = getIdent();
1195         }
1196 
1197         return classTail(classLineNumber, classToken, className, isStatement);
1198     }
1199 
1200     private static final class ClassElementKey {
1201         private final boolean isStatic;
1202         private final String propertyName;
1203 
1204         private ClassElementKey(final boolean isStatic, final String propertyName) {
1205             this.isStatic = isStatic;
1206             this.propertyName = propertyName;
1207         }
1208 
1209         @Override
1210         public int hashCode() {
1211             final int prime = 31;
1212             int result = 1;
1213             result = prime * result + (isStatic ? 1231 : 1237);
1214             result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode());
1215             return result;
1216         }
1217 
1218         @Override
1219         public boolean equals(final Object obj) {
1220             if (obj instanceof ClassElementKey) {
1221                 final ClassElementKey other = (ClassElementKey) obj;
1222                 return this.isStatic == other.isStatic && Objects.equals(this.propertyName, other.propertyName);
1223             }
1224             return false;
1225         }
1226     }
1227 
1228     /**
1229      * Parse ClassTail and ClassBody.
1230      *
1231      * ClassTail[Yield] :
1232      *   ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
1233      * ClassHeritage[Yield] :
1234      *   extends LeftHandSideExpression[?Yield]
1235      *
1236      * ClassBody[Yield] :
1237      *   ClassElementList[?Yield]
1238      * ClassElementList[Yield] :
1239      *   ClassElement[?Yield]
1240      *   ClassElementList[?Yield] ClassElement[?Yield]
1241      * ClassElement[Yield] :
1242      *   MethodDefinition[?Yield]
1243      *   static MethodDefinition[?Yield]
1244      *   ;
1245      */
1246     private ClassNode classTail(final int classLineNumber, final long classToken,
1247             final IdentNode className, final boolean isStatement) {
1248         final boolean oldStrictMode = isStrictMode;
1249         isStrictMode = true;
1250         try {
1251             Expression classHeritage = null;
1252             if (type == EXTENDS) {
1253                 next();
1254                 classHeritage = leftHandSideExpression();
1255             }
1256 
1257             expect(LBRACE);
1258 
1259             PropertyNode constructor = null;
1260             final ArrayList<PropertyNode> classElements = new ArrayList<>();
1261             final Map<ClassElementKey, Integer> keyToIndexMap = new HashMap<>();
1262             for (;;) {
1263                 if (type == SEMICOLON) {
1264                     next();
1265                     continue;
1266                 }
1267                 if (type == RBRACE) {
1268                     break;
1269                 }
1270                 final long classElementToken = token;
1271                 boolean isStatic = false;
1272                 if (type == STATIC) {
1273                     isStatic = true;
1274                     next();
1275                 }
1276                 boolean generator = false;
1277                 if (isES6() && type == MUL) {
1278                     generator = true;
1279                     next();
1280                 }
1281                 final PropertyNode classElement = methodDefinition(isStatic, classHeritage != null, generator);
1282                 if (classElement.isComputed()) {
1283                     classElements.add(classElement);
1284                 } else if (!classElement.isStatic() && classElement.getKeyName().equals(CONSTRUCTOR_NAME)) {
1285                     if (constructor == null) {
1286                         constructor = classElement;
1287                     } else {
1288                         throw error(AbstractParser.message("multiple.constructors"), classElementToken);
1289                     }
1290                 } else {
1291                     // Check for duplicate method definitions and combine accessor methods.
1292                     // In ES6, a duplicate is never an error regardless of strict mode (in consequence of computed property names).
1293 
1294                     final ClassElementKey key = new ClassElementKey(classElement.isStatic(), classElement.getKeyName());
1295                     final Integer existing = keyToIndexMap.get(key);
1296 
1297                     if (existing == null) {
1298                         keyToIndexMap.put(key, classElements.size());
1299                         classElements.add(classElement);
1300                     } else {
1301                         final PropertyNode existingProperty = classElements.get(existing);
1302 
1303                         final Expression   value  = classElement.getValue();
1304                         final FunctionNode getter = classElement.getGetter();
1305                         final FunctionNode setter = classElement.getSetter();
1306 
1307                         if (value != null || existingProperty.getValue() != null) {
1308                             keyToIndexMap.put(key, classElements.size());
1309                             classElements.add(classElement);
1310                         } else if (getter != null) {
1311                             assert existingProperty.getGetter() != null || existingProperty.getSetter() != null;
1312                             classElements.set(existing, existingProperty.setGetter(getter));
1313                         } else if (setter != null) {
1314                             assert existingProperty.getGetter() != null || existingProperty.getSetter() != null;
1315                             classElements.set(existing, existingProperty.setSetter(setter));
1316                         }
1317                     }
1318                 }
1319             }
1320 
1321             final long lastToken = token;
1322             expect(RBRACE);
1323 
1324             if (constructor == null) {
1325                 constructor = createDefaultClassConstructor(classLineNumber, classToken, lastToken, className, classHeritage != null);
1326             }
1327 
1328             classElements.trimToSize();
1329             return new ClassNode(classLineNumber, classToken, finish, className, classHeritage, constructor, classElements, isStatement);
1330         } finally {
1331             isStrictMode = oldStrictMode;
1332         }
1333     }
1334 
1335     private PropertyNode createDefaultClassConstructor(final int classLineNumber, final long classToken, final long lastToken, final IdentNode className, final boolean subclass) {
1336         final int ctorFinish = finish;
1337         final List<Statement> statements;
1338         final List<IdentNode> parameters;
1339         final long identToken = Token.recast(classToken, TokenType.IDENT);
1340         if (subclass) {
1341             final IdentNode superIdent = createIdentNode(identToken, ctorFinish, SUPER.getName()).setIsDirectSuper();
1342             final IdentNode argsIdent = createIdentNode(identToken, ctorFinish, "args").setIsRestParameter();
1343             final Expression spreadArgs = new UnaryNode(Token.recast(classToken, TokenType.SPREAD_ARGUMENT), argsIdent);
1344             final CallNode superCall = new CallNode(classLineNumber, classToken, ctorFinish, superIdent, Collections.singletonList(spreadArgs), false);
1345             statements = Collections.singletonList(new ExpressionStatement(classLineNumber, classToken, ctorFinish, superCall));
1346             parameters = Collections.singletonList(argsIdent);
1347         } else {
1348             statements = Collections.emptyList();
1349             parameters = Collections.emptyList();
1350         }
1351 
1352         final Block body = new Block(classToken, ctorFinish, Block.IS_BODY, statements);
1353         final IdentNode ctorName = className != null ? className : createIdentNode(identToken, ctorFinish, CONSTRUCTOR_NAME);
1354         final ParserContextFunctionNode function = createParserContextFunctionNode(ctorName, classToken, FunctionNode.Kind.NORMAL, classLineNumber, parameters);
1355         function.setLastToken(lastToken);
1356 
1357         function.setFlag(FunctionNode.ES6_IS_METHOD);
1358         function.setFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR);
1359         if (subclass) {
1360             function.setFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR);
1361             function.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
1362         }
1363         if (className == null) {
1364             function.setFlag(FunctionNode.IS_ANONYMOUS);
1365         }
1366 
1367         final PropertyNode constructor = new PropertyNode(classToken, ctorFinish, ctorName, createFunctionNode(
1368                         function,
1369                         classToken,
1370                         ctorName,
1371                         parameters,
1372                         FunctionNode.Kind.NORMAL,
1373                         classLineNumber,
1374                         body
1375                         ), null, null, false, false);
1376         return constructor;
1377     }
1378 
1379     private PropertyNode methodDefinition(final boolean isStatic, final boolean subclass, final boolean generator) {
1380         final long methodToken = token;
1381         final int methodLine = line;
1382         final boolean computed = type == LBRACKET;
1383         final boolean isIdent = type == IDENT;
1384         final Expression propertyName = propertyName();
1385         int flags = FunctionNode.ES6_IS_METHOD;
1386         if (!computed) {
1387             final String name = ((PropertyKey)propertyName).getPropertyName();
1388             if (!generator && isIdent && type != LPAREN && name.equals(GET_NAME)) {
1389                 final PropertyFunction methodDefinition = propertyGetterFunction(methodToken, methodLine, flags);
1390                 verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true);
1391                 return new PropertyNode(methodToken, finish, methodDefinition.key, null, methodDefinition.functionNode, null, isStatic, methodDefinition.computed);
1392             } else if (!generator && isIdent && type != LPAREN && name.equals(SET_NAME)) {
1393                 final PropertyFunction methodDefinition = propertySetterFunction(methodToken, methodLine, flags);
1394                 verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true);
1395                 return new PropertyNode(methodToken, finish, methodDefinition.key, null, null, methodDefinition.functionNode, isStatic, methodDefinition.computed);
1396             } else {
1397                 if (!isStatic && !generator && name.equals(CONSTRUCTOR_NAME)) {
1398                     flags |= FunctionNode.ES6_IS_CLASS_CONSTRUCTOR;
1399                     if (subclass) {
1400                         flags |= FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR;
1401                     }
1402                 }
1403                 verifyAllowedMethodName(propertyName, isStatic, computed, generator, false);
1404             }
1405         }
1406         final PropertyFunction methodDefinition = propertyMethodFunction(propertyName, methodToken, methodLine, generator, flags, computed);
1407         return new PropertyNode(methodToken, finish, methodDefinition.key, methodDefinition.functionNode, null, null, isStatic, computed);
1408     }
1409 
1410     /**
1411      * ES6 14.5.1 Static Semantics: Early Errors.
1412      */
1413     private void verifyAllowedMethodName(final Expression key, final boolean isStatic, final boolean computed, final boolean generator, final boolean accessor) {
1414         if (!computed) {
1415             if (!isStatic && generator && ((PropertyKey) key).getPropertyName().equals(CONSTRUCTOR_NAME)) {
1416                 throw error(AbstractParser.message("generator.constructor"), key.getToken());
1417             }
1418             if (!isStatic && accessor && ((PropertyKey) key).getPropertyName().equals(CONSTRUCTOR_NAME)) {
1419                 throw error(AbstractParser.message("accessor.constructor"), key.getToken());
1420             }
1421             if (isStatic && ((PropertyKey) key).getPropertyName().equals("prototype")) {
1422                 throw error(AbstractParser.message("static.prototype.method"), key.getToken());
1423             }
1424         }
1425     }
1426 
1427     /**
1428      * block :
1429      *      { StatementList? }
1430      *
1431      * see 12.1
1432      *
1433      * Parse a statement block.
1434      */
1435     private void block() {
1436         appendStatement(new BlockStatement(line, getBlock(true)));
1437     }
1438 
1439     /**
1440      * StatementList :
1441      *      Statement
1442      *      StatementList Statement
1443      *
1444      * See 12.1
1445      *
1446      * Parse a list of statements.
1447      */
1448     private void statementList() {
1449         // Accumulate statements until end of list. */
1450         loop:
1451         while (type != EOF) {
1452             switch (type) {
1453             case EOF:
1454             case CASE:
1455             case DEFAULT:
1456             case RBRACE:
1457                 break loop;
1458             default:
1459                 break;
1460             }
1461 
1462             // Get next statement.
1463             statement();
1464         }
1465     }
1466 
1467     /**
1468      * Make sure that the identifier name used is allowed.
1469      *
1470      * @param ident         Identifier that is verified
1471      * @param contextString String used in error message to give context to the user
1472      */
1473     private void verifyIdent(final IdentNode ident, final String contextString) {
1474         verifyStrictIdent(ident, contextString);
1475         if (isES6()) {
1476             final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length());
1477             if (tokenType != IDENT && tokenType.getKind() != TokenKind.FUTURESTRICT) {
1478                 throw error(expectMessage(IDENT));
1479             }
1480         }
1481     }
1482 
1483     /**
1484      * Make sure that in strict mode, the identifier name used is allowed.
1485      *
1486      * @param ident         Identifier that is verified
1487      * @param contextString String used in error message to give context to the user
1488      */
1489     private void verifyStrictIdent(final IdentNode ident, final String contextString) {
1490         if (isStrictMode) {
1491             switch (ident.getName()) {
1492             case "eval":
1493             case "arguments":
1494                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1495             default:
1496                 break;
1497             }
1498 
1499             if (ident.isFutureStrictName()) {
1500                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1501             }
1502         }
1503     }
1504 
1505     /*
1506      * VariableStatement :
1507      *      var VariableDeclarationList ;
1508      *
1509      * VariableDeclarationList :
1510      *      VariableDeclaration
1511      *      VariableDeclarationList , VariableDeclaration
1512      *
1513      * VariableDeclaration :
1514      *      Identifier Initializer?
1515      *
1516      * Initializer :
1517      *      = AssignmentExpression
1518      *
1519      * See 12.2
1520      *
1521      * Parse a VAR statement.
1522      * @param isStatement True if a statement (not used in a FOR.)
1523      */
1524     private void variableStatement(final TokenType varType) {
1525         variableDeclarationList(varType, true, -1);
1526     }
1527 
1528     private static final class ForVariableDeclarationListResult {
1529         /** First missing const or binding pattern initializer. */
1530         Expression missingAssignment;
1531         /** First declaration with an initializer. */
1532         long declarationWithInitializerToken;
1533         /** Destructuring assignments. */
1534         Expression init;
1535         Expression firstBinding;
1536         Expression secondBinding;
1537 
1538         void recordMissingAssignment(final Expression binding) {
1539             if (missingAssignment == null) {
1540                 missingAssignment = binding;
1541             }
1542         }
1543 
1544         void recordDeclarationWithInitializer(final long token) {
1545             if (declarationWithInitializerToken == 0L) {
1546                 declarationWithInitializerToken = token;
1547             }
1548         }
1549 
1550         void addBinding(final Expression binding) {
1551             if (firstBinding == null) {
1552                 firstBinding = binding;
1553             } else if (secondBinding == null)  {
1554                 secondBinding = binding;
1555             }
1556             // ignore the rest
1557         }
1558 
1559         void addAssignment(final Expression assignment) {
1560             if (init == null) {
1561                 init = assignment;
1562             } else {
1563                 init = new BinaryNode(Token.recast(init.getToken(), COMMARIGHT), init, assignment);
1564             }
1565         }
1566     }
1567 
1568     /**
1569      * @param isStatement {@code true} if a VariableStatement, {@code false} if a {@code for} loop VariableDeclarationList
1570      */
1571     private ForVariableDeclarationListResult variableDeclarationList(final TokenType varType, final boolean isStatement, final int sourceOrder) {
1572         // VAR tested in caller.
1573         assert varType == VAR || varType == LET || varType == CONST;
1574         final int varLine = line;
1575         final long varToken = token;
1576 
1577         next();
1578 
1579         int varFlags = 0;
1580         if (varType == LET) {
1581             varFlags |= VarNode.IS_LET;
1582         } else if (varType == CONST) {
1583             varFlags |= VarNode.IS_CONST;
1584         }
1585 
1586         final ForVariableDeclarationListResult forResult = isStatement ? null : new ForVariableDeclarationListResult();
1587         while (true) {
1588             // Get name of var.
1589             if (type == YIELD && inGeneratorFunction()) {
1590                 expect(IDENT);
1591             }
1592 
1593             final String contextString = "variable name";
1594             final Expression binding = bindingIdentifierOrPattern(contextString);
1595             final boolean isDestructuring = !(binding instanceof IdentNode);
1596             if (isDestructuring) {
1597                 final int finalVarFlags = varFlags;
1598                 verifyDestructuringBindingPattern(binding, new Consumer<IdentNode>() {
1599                     @Override
1600                     public void accept(final IdentNode identNode) {
1601                         verifyIdent(identNode, contextString);
1602                         if (!env._parse_only) {
1603                             // don't bother adding a variable if we are just parsing!
1604                             final VarNode var = new VarNode(varLine, varToken, sourceOrder, identNode.getFinish(), identNode.setIsDeclaredHere(), null, finalVarFlags);
1605                             appendStatement(var);
1606                         }
1607                     }
1608                 });
1609             }
1610 
1611             // Assume no init.
1612             Expression init = null;
1613 
1614             // Look for initializer assignment.
1615             if (type == ASSIGN) {
1616                 if (!isStatement) {
1617                     forResult.recordDeclarationWithInitializer(varToken);
1618                 }
1619                 next();
1620 
1621                 // Get initializer expression. Suppress IN if not statement.
1622                 if (!isDestructuring) {
1623                     defaultNames.push(binding);
1624                 }
1625                 try {
1626                     init = assignmentExpression(!isStatement);
1627                 } finally {
1628                     if (!isDestructuring) {
1629                         defaultNames.pop();
1630                     }
1631                 }
1632             } else if (isStatement) {
1633                 if (isDestructuring) {
1634                     throw error(AbstractParser.message("missing.destructuring.assignment"), token);
1635                 } else if (varType == CONST) {
1636                     throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)binding).getName()));
1637                 }
1638                 // else, if we are in a for loop, delay checking until we know the kind of loop
1639             }
1640 
1641             if (!isDestructuring) {
1642                 assert init != null || varType != CONST || !isStatement;
1643                 final IdentNode ident = (IdentNode)binding;
1644                 if (!isStatement && ident.getName().equals("let")) {
1645                     throw error(AbstractParser.message("let.binding.for")); //ES6 13.7.5.1
1646                 }
1647                 // Only set declaration flag on lexically scoped let/const as it adds runtime overhead.
1648                 final IdentNode name = varType == LET || varType == CONST ? ident.setIsDeclaredHere() : ident;
1649                 if (!isStatement) {
1650                     if (init == null && varType == CONST) {
1651                         forResult.recordMissingAssignment(name);
1652                     }
1653                     forResult.addBinding(new IdentNode(name));
1654                 }
1655                 final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name, init, varFlags);
1656                 appendStatement(var);
1657             } else {
1658                 assert init != null || !isStatement;
1659                 if (init != null) {
1660                     final Expression assignment = verifyAssignment(Token.recast(varToken, ASSIGN), binding, init);
1661                     if (isStatement) {
1662                         appendStatement(new ExpressionStatement(varLine, assignment.getToken(), finish, assignment, varType));
1663                     } else {
1664                         forResult.addAssignment(assignment);
1665                         forResult.addBinding(assignment);
1666                     }
1667                 } else if (!isStatement) {
1668                     forResult.recordMissingAssignment(binding);
1669                     forResult.addBinding(binding);
1670                 }
1671             }
1672 
1673             if (type != COMMARIGHT) {
1674                 break;
1675             }
1676             next();
1677         }
1678 
1679         // If is a statement then handle end of line.
1680         if (isStatement) {
1681             endOfLine();
1682         }
1683 
1684         return forResult;
1685     }
1686 
1687     private boolean isBindingIdentifier() {
1688         return type == IDENT || isNonStrictModeIdent();
1689     }
1690 
1691     private IdentNode bindingIdentifier(final String contextString) {
1692         final IdentNode name = getIdent();
1693         verifyIdent(name, contextString);
1694         return name;
1695     }
1696 
1697     private Expression bindingPattern() {
1698         if (type == LBRACKET) {
1699             return arrayLiteral();
1700         } else if (type == LBRACE) {
1701             return objectLiteral();
1702         } else {
1703             throw error(AbstractParser.message("expected.binding"));
1704         }
1705     }
1706 
1707     private Expression bindingIdentifierOrPattern(final String contextString) {
1708         if (isBindingIdentifier() || !isES6()) {
1709             return bindingIdentifier(contextString);
1710         } else {
1711             return bindingPattern();
1712         }
1713     }
1714 
1715     private abstract class VerifyDestructuringPatternNodeVisitor extends NodeVisitor<LexicalContext> {
1716         VerifyDestructuringPatternNodeVisitor(final LexicalContext lc) {
1717             super(lc);
1718         }
1719 
1720         @Override
1721         public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
1722             if (literalNode.isArray()) {
1723                 if (((LiteralNode.ArrayLiteralNode)literalNode).hasSpread() && ((LiteralNode.ArrayLiteralNode)literalNode).hasTrailingComma()) {
1724                     throw error("Rest element must be last", literalNode.getElementExpressions().get(literalNode.getElementExpressions().size() - 1).getToken());
1725                 }
1726                 boolean restElement = false;
1727                 for (final Expression element : literalNode.getElementExpressions()) {
1728                     if (element != null) {
1729                         if (restElement) {
1730                             throw error("Unexpected element after rest element", element.getToken());
1731                         }
1732                         if (element.isTokenType(SPREAD_ARRAY)) {
1733                             restElement = true;
1734                             final Expression lvalue = ((UnaryNode) element).getExpression();
1735                             verifySpreadElement(lvalue);
1736                         }
1737                         element.accept(this);
1738                     }
1739                 }
1740                 return false;
1741             } else {
1742                 return enterDefault(literalNode);
1743             }
1744         }
1745 
1746         protected abstract void verifySpreadElement(Expression lvalue);
1747 
1748         @Override
1749         public boolean enterObjectNode(final ObjectNode objectNode) {
1750             return true;
1751         }
1752 
1753         @Override
1754         public boolean enterPropertyNode(final PropertyNode propertyNode) {
1755             if (propertyNode.getValue() != null) {
1756                 propertyNode.getValue().accept(this);
1757                 return false;
1758             } else {
1759                 return enterDefault(propertyNode);
1760             }
1761         }
1762 
1763         @Override
1764         public boolean enterBinaryNode(final BinaryNode binaryNode) {
1765             if (binaryNode.isTokenType(ASSIGN)) {
1766                 binaryNode.lhs().accept(this);
1767                 // Initializer(rhs) can be any AssignmentExpression
1768                 return false;
1769             } else {
1770                 return enterDefault(binaryNode);
1771             }
1772         }
1773 
1774         @Override
1775         public boolean enterUnaryNode(final UnaryNode unaryNode) {
1776             if (unaryNode.isTokenType(SPREAD_ARRAY)) {
1777                 // rest element
1778                 return true;
1779             } else {
1780                 return enterDefault(unaryNode);
1781             }
1782         }
1783     }
1784 
1785     /**
1786      * Verify destructuring variable declaration binding pattern and extract bound variable declarations.
1787      */
1788     private void verifyDestructuringBindingPattern(final Expression pattern, final Consumer<IdentNode> identifierCallback) {
1789         assert (pattern instanceof BinaryNode && pattern.isTokenType(ASSIGN)) ||
1790                 pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
1791         pattern.accept(new VerifyDestructuringPatternNodeVisitor(new LexicalContext()) {
1792             @Override
1793             protected void verifySpreadElement(final Expression lvalue) {
1794                 if (lvalue instanceof IdentNode) {
1795                     // checked in identifierCallback
1796                 } else if (isDestructuringLhs(lvalue)) {
1797                     verifyDestructuringBindingPattern(lvalue, identifierCallback);
1798                 } else {
1799                     throw error("Expected a valid binding identifier", lvalue.getToken());
1800                 }
1801             }
1802 
1803             @Override
1804             public boolean enterIdentNode(final IdentNode identNode) {
1805                 identifierCallback.accept(identNode);
1806                 return false;
1807             }
1808 
1809             @Override
1810             protected boolean enterDefault(final Node node) {
1811                 throw error(String.format("unexpected node in BindingPattern: %s", node));
1812             }
1813         });
1814     }
1815 
1816     /**
1817      * EmptyStatement :
1818      *      ;
1819      *
1820      * See 12.3
1821      *
1822      * Parse an empty statement.
1823      */
1824     private void emptyStatement() {
1825         if (env._empty_statements) {
1826             appendStatement(new EmptyNode(line, token, Token.descPosition(token) + Token.descLength(token)));
1827         }
1828 
1829         // SEMICOLON checked in caller.
1830         next();
1831     }
1832 
1833     /**
1834      * ExpressionStatement :
1835      *      Expression ; // [lookahead ~({ or  function )]
1836      *
1837      * See 12.4
1838      *
1839      * Parse an expression used in a statement block.
1840      */
1841     private void expressionStatement() {
1842         // Lookahead checked in caller.
1843         final int  expressionLine  = line;
1844         final long expressionToken = token;
1845 
1846         // Get expression and add as statement.
1847         final Expression expression = expression();
1848 
1849         if (expression != null) {
1850             final ExpressionStatement expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
1851             appendStatement(expressionStatement);
1852         } else {
1853             expect(null);
1854         }
1855 
1856         endOfLine();
1857     }
1858 
1859     /**
1860      * IfStatement :
1861      *      if ( Expression ) Statement else Statement
1862      *      if ( Expression ) Statement
1863      *
1864      * See 12.5
1865      *
1866      * Parse an IF statement.
1867      */
1868     private void ifStatement() {
1869         // Capture IF token.
1870         final int  ifLine  = line;
1871         final long ifToken = token;
1872          // IF tested in caller.
1873         next();
1874 
1875         expect(LPAREN);
1876         final Expression test = expression();
1877         expect(RPAREN);
1878         final Block pass = getStatement();
1879 
1880         Block fail = null;
1881         if (type == ELSE) {
1882             next();
1883             fail = getStatement();
1884         }
1885 
1886         appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1887     }
1888 
1889     /**
1890      * ... IterationStatement:
1891      *           ...
1892      *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1893      *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1894      *           for ( LeftHandSideExpression in Expression ) Statement
1895      *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1896      *
1897      * See 12.6
1898      *
1899      * Parse a FOR statement.
1900      */
1901     @SuppressWarnings("fallthrough")
1902     private void forStatement() {
1903         final long forToken = token;
1904         final int forLine = line;
1905         // start position of this for statement. This is used
1906         // for sort order for variables declared in the initializer
1907         // part of this 'for' statement (if any).
1908         final int forStart = Token.descPosition(forToken);
1909         // When ES6 for-let is enabled we create a container block to capture the LET.
1910         final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1911 
1912         // Create FOR node, capturing FOR token.
1913         final ParserContextLoopNode forNode = new ParserContextLoopNode();
1914         lc.push(forNode);
1915         Block body = null;
1916         Expression init = null;
1917         JoinPredecessorExpression test = null;
1918         JoinPredecessorExpression modify = null;
1919         ForVariableDeclarationListResult varDeclList = null;
1920 
1921         int flags = 0;
1922         boolean isForOf = false;
1923 
1924         try {
1925             // FOR tested in caller.
1926             next();
1927 
1928             // Nashorn extension: for each expression.
1929             // iterate property values rather than property names.
1930             if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1931                 flags |= ForNode.IS_FOR_EACH;
1932                 next();
1933             }
1934 
1935             expect(LPAREN);
1936 
1937             TokenType varType = null;
1938             switch (type) {
1939             case VAR:
1940                 // Var declaration captured in for outer block.
1941                 varDeclList = variableDeclarationList(varType = type, false, forStart);
1942                 break;
1943             case SEMICOLON:
1944                 break;
1945             default:
1946                 if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(true) || type == CONST)) {
1947                     flags |= ForNode.PER_ITERATION_SCOPE;
1948                     // LET/CONST declaration captured in container block created above.
1949                     varDeclList = variableDeclarationList(varType = type, false, forStart);
1950                     break;
1951                 }
1952                 if (env._const_as_var && type == CONST) {
1953                     // Var declaration captured in for outer block.
1954                     varDeclList = variableDeclarationList(varType = TokenType.VAR, false, forStart);
1955                     break;
1956                 }
1957 
1958                 init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1959                 break;
1960             }
1961 
1962             switch (type) {
1963             case SEMICOLON:
1964                 // for (init; test; modify)
1965                 if (varDeclList != null) {
1966                     assert init == null;
1967                     init = varDeclList.init;
1968                     // late check for missing assignment, now we know it's a for (init; test; modify) loop
1969                     if (varDeclList.missingAssignment != null) {
1970                         if (varDeclList.missingAssignment instanceof IdentNode) {
1971                             throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)varDeclList.missingAssignment).getName()));
1972                         } else {
1973                             throw error(AbstractParser.message("missing.destructuring.assignment"), varDeclList.missingAssignment.getToken());
1974                         }
1975                     }
1976                 }
1977 
1978                 // for each (init; test; modify) is invalid
1979                 if ((flags & ForNode.IS_FOR_EACH) != 0) {
1980                     throw error(AbstractParser.message("for.each.without.in"), token);
1981                 }
1982 
1983                 expect(SEMICOLON);
1984                 if (type != SEMICOLON) {
1985                     test = joinPredecessorExpression();
1986                 }
1987                 expect(SEMICOLON);
1988                 if (type != RPAREN) {
1989                     modify = joinPredecessorExpression();
1990                 }
1991                 break;
1992 
1993             case IDENT:
1994                 if (env._es6 && "of".equals(getValue())) {
1995                     isForOf = true;
1996                     // fall through
1997                 } else {
1998                     expect(SEMICOLON); // fail with expected message
1999                     break;
2000                 }
2001             case IN:
2002                 flags |= isForOf ? ForNode.IS_FOR_OF : ForNode.IS_FOR_IN;
2003                 test = new JoinPredecessorExpression();
2004                 if (varDeclList != null) {
2005                     // for (var|let|const ForBinding in|of expression)
2006                     if (varDeclList.secondBinding != null) {
2007                         // for (var i, j in obj) is invalid
2008                         throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), varDeclList.secondBinding.getToken());
2009                     }
2010                     if (varDeclList.declarationWithInitializerToken != 0 && (isStrictMode || type != TokenType.IN || varType != VAR || varDeclList.init != null)) {
2011                         // ES5 legacy: for (var i = AssignmentExpressionNoIn in Expression)
2012                         // Invalid in ES6, but allow it in non-strict mode if no ES6 features used,
2013                         // i.e., error if strict, for-of, let/const, or destructuring
2014                         throw error(AbstractParser.message("for.in.loop.initializer", isForOf ? "of" : "in"), varDeclList.declarationWithInitializerToken);
2015                     }
2016                     init = varDeclList.firstBinding;
2017                     assert init instanceof IdentNode || isDestructuringLhs(init);
2018                 } else {
2019                     // for (expr in obj)
2020                     assert init != null : "for..in/of init expression can not be null here";
2021 
2022                     // check if initial expression is a valid L-value
2023                     if (!checkValidLValue(init, isForOf ? "for-of iterator" : "for-in iterator")) {
2024                         throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
2025                     }
2026                 }
2027 
2028                 next();
2029 
2030                 // For-of only allows AssignmentExpression.
2031                 modify = isForOf ? new JoinPredecessorExpression(assignmentExpression(false)) : joinPredecessorExpression();
2032                 break;
2033 
2034             default:
2035                 expect(SEMICOLON);
2036                 break;
2037             }
2038 
2039             expect(RPAREN);
2040 
2041             // Set the for body.
2042             body = getStatement();
2043         } finally {
2044             lc.pop(forNode);
2045 
2046             for (final Statement var : forNode.getStatements()) {
2047                 assert var instanceof VarNode;
2048                 appendStatement(var);
2049             }
2050             if (body != null) {
2051                 appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
2052             }
2053             if (outer != null) {
2054                 restoreBlock(outer);
2055                 if (body != null) {
2056                     appendStatement(new BlockStatement(forLine, new Block(
2057                                     outer.getToken(),
2058                                     body.getFinish(),
2059                                     outer.getStatements())));
2060                 }
2061             }
2062         }
2063     }
2064 
2065     private boolean checkValidLValue(final Expression init, final String contextString) {
2066         if (init instanceof IdentNode) {
2067             if (!checkIdentLValue((IdentNode)init)) {
2068                 return false;
2069             }
2070             verifyIdent((IdentNode)init, contextString);
2071             return true;
2072         } else if (init instanceof AccessNode || init instanceof IndexNode) {
2073             return true;
2074         } else if (isDestructuringLhs(init)) {
2075             verifyDestructuringAssignmentPattern(init, contextString);
2076             return true;
2077         } else {
2078             return false;
2079         }
2080     }
2081 
2082     @SuppressWarnings("fallthrough")
2083     private boolean lookaheadIsLetDeclaration(final boolean ofContextualKeyword) {
2084         assert type == LET;
2085         for (int i = 1;; i++) {
2086             final TokenType t = T(k + i);
2087             switch (t) {
2088             case EOL:
2089             case COMMENT:
2090                 continue;
2091             case IDENT:
2092                 if (ofContextualKeyword && isES6() && "of".equals(getValue(getToken(k + i)))) {
2093                     return false;
2094                 }
2095                 // fall through
2096             case LBRACKET:
2097             case LBRACE:
2098                 return true;
2099             default:
2100                 // accept future strict tokens in non-strict mode (including LET)
2101                 if (!isStrictMode && t.getKind() == TokenKind.FUTURESTRICT) {
2102                     return true;
2103                 }
2104                 return false;
2105             }
2106         }
2107     }
2108 
2109     /**
2110      * ...IterationStatement :
2111      *           ...
2112      *           while ( Expression ) Statement
2113      *           ...
2114      *
2115      * See 12.6
2116      *
2117      * Parse while statement.
2118      */
2119     private void whileStatement() {
2120         // Capture WHILE token.
2121         final long whileToken = token;
2122         final int whileLine = line;
2123         // WHILE tested in caller.
2124         next();
2125 
2126         final ParserContextLoopNode whileNode = new ParserContextLoopNode();
2127         lc.push(whileNode);
2128 
2129         JoinPredecessorExpression test = null;
2130         Block body = null;
2131 
2132         try {
2133             expect(LPAREN);
2134             test = joinPredecessorExpression();
2135             expect(RPAREN);
2136             body = getStatement();
2137         } finally {
2138             lc.pop(whileNode);
2139         }
2140 
2141         if (body != null) {
2142             appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
2143         }
2144     }
2145 
2146     /**
2147      * ...IterationStatement :
2148      *           ...
2149      *           do Statement while( Expression ) ;
2150      *           ...
2151      *
2152      * See 12.6
2153      *
2154      * Parse DO WHILE statement.
2155      */
2156     private void doStatement() {
2157         // Capture DO token.
2158         final long doToken = token;
2159         int doLine = 0;
2160         // DO tested in the caller.
2161         next();
2162 
2163         final ParserContextLoopNode doWhileNode = new ParserContextLoopNode();
2164         lc.push(doWhileNode);
2165 
2166         Block body = null;
2167         JoinPredecessorExpression test = null;
2168 
2169         try {
2170            // Get DO body.
2171             body = getStatement();
2172 
2173             expect(WHILE);
2174             expect(LPAREN);
2175             doLine = line;
2176             test = joinPredecessorExpression();
2177             expect(RPAREN);
2178 
2179             if (type == SEMICOLON) {
2180                 endOfLine();
2181             }
2182         } finally {
2183             lc.pop(doWhileNode);
2184         }
2185 
2186         appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
2187     }
2188 
2189     /**
2190      * ContinueStatement :
2191      *      continue Identifier? ; // [no LineTerminator here]
2192      *
2193      * See 12.7
2194      *
2195      * Parse CONTINUE statement.
2196      */
2197     private void continueStatement() {
2198         // Capture CONTINUE token.
2199         final int  continueLine  = line;
2200         final long continueToken = token;
2201         // CONTINUE tested in caller.
2202         nextOrEOL();
2203 
2204         ParserContextLabelNode labelNode = null;
2205 
2206         // SEMICOLON or label.
2207         switch (type) {
2208         case RBRACE:
2209         case SEMICOLON:
2210         case EOL:
2211         case EOF:
2212             break;
2213 
2214         default:
2215             final IdentNode ident = getIdent();
2216             labelNode = lc.findLabel(ident.getName());
2217 
2218             if (labelNode == null) {
2219                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
2220             }
2221 
2222             break;
2223         }
2224 
2225         final String labelName = labelNode == null ? null : labelNode.getLabelName();
2226         final ParserContextLoopNode targetNode = lc.getContinueTo(labelName);
2227 
2228         if (targetNode == null) {
2229             throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
2230         }
2231 
2232         endOfLine();
2233 
2234         // Construct and add CONTINUE node.
2235         appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
2236     }
2237 
2238     /**
2239      * BreakStatement :
2240      *      break Identifier? ; // [no LineTerminator here]
2241      *
2242      * See 12.8
2243      *
2244      */
2245     private void breakStatement() {
2246         // Capture BREAK token.
2247         final int  breakLine  = line;
2248         final long breakToken = token;
2249         // BREAK tested in caller.
2250         nextOrEOL();
2251 
2252         ParserContextLabelNode labelNode = null;
2253 
2254         // SEMICOLON or label.
2255         switch (type) {
2256         case RBRACE:
2257         case SEMICOLON:
2258         case EOL:
2259         case EOF:
2260             break;
2261 
2262         default:
2263             final IdentNode ident = getIdent();
2264             labelNode = lc.findLabel(ident.getName());
2265 
2266             if (labelNode == null) {
2267                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
2268             }
2269 
2270             break;
2271         }
2272 
2273         //either an explicit label - then get its node or just a "break" - get first breakable
2274         //targetNode is what we are breaking out from.
2275         final String labelName = labelNode == null ? null : labelNode.getLabelName();
2276         final ParserContextBreakableNode targetNode = lc.getBreakable(labelName);
2277         if (targetNode == null) {
2278             throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
2279         }
2280 
2281         endOfLine();
2282 
2283         // Construct and add BREAK node.
2284         appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
2285     }
2286 
2287     /**
2288      * ReturnStatement :
2289      *      return Expression? ; // [no LineTerminator here]
2290      *
2291      * See 12.9
2292      *
2293      * Parse RETURN statement.
2294      */
2295     private void returnStatement() {
2296         // check for return outside function
2297         if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT || lc.getCurrentFunction().getKind() == FunctionNode.Kind.MODULE) {
2298             throw error(AbstractParser.message("invalid.return"));
2299         }
2300 
2301         // Capture RETURN token.
2302         final int  returnLine  = line;
2303         final long returnToken = token;
2304         // RETURN tested in caller.
2305         nextOrEOL();
2306 
2307         Expression expression = null;
2308 
2309         // SEMICOLON or expression.
2310         switch (type) {
2311         case RBRACE:
2312         case SEMICOLON:
2313         case EOL:
2314         case EOF:
2315             break;
2316 
2317         default:
2318             expression = expression();
2319             break;
2320         }
2321 
2322         endOfLine();
2323 
2324         // Construct and add RETURN node.
2325         appendStatement(new ReturnNode(returnLine, returnToken, finish, expression));
2326     }
2327 
2328     /**
2329      * Parse YieldExpression.
2330      *
2331      * YieldExpression[In] :
2332      *   yield
2333      *   yield [no LineTerminator here] AssignmentExpression[?In, Yield]
2334      *   yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
2335      */
2336     @SuppressWarnings("fallthrough")
2337     private Expression yieldExpression(final boolean noIn) {
2338         assert inGeneratorFunction();
2339         // Capture YIELD token.
2340         long yieldToken = token;
2341         // YIELD tested in caller.
2342         assert type == YIELD;
2343         nextOrEOL();
2344 
2345         Expression expression = null;
2346 
2347         boolean yieldAsterisk = false;
2348         if (type == MUL) {
2349             yieldAsterisk = true;
2350             yieldToken = Token.recast(yieldToken, YIELD_STAR);
2351             next();
2352         }
2353 
2354         switch (type) {
2355         case RBRACE:
2356         case SEMICOLON:
2357         case EOL:
2358         case EOF:
2359         case COMMARIGHT:
2360         case RPAREN:
2361         case RBRACKET:
2362         case COLON:
2363             if (!yieldAsterisk) {
2364                 // treat (yield) as (yield void 0)
2365                 expression = newUndefinedLiteral(yieldToken, finish);
2366                 if (type == EOL) {
2367                     next();
2368                 }
2369                 break;
2370             } else {
2371                 // AssignmentExpression required, fall through
2372             }
2373 
2374         default:
2375             expression = assignmentExpression(noIn);
2376             break;
2377         }
2378 
2379         // Construct and add YIELD node.
2380         return new UnaryNode(yieldToken, expression);
2381     }
2382 
2383     private static UnaryNode newUndefinedLiteral(final long token, final int finish) {
2384         return new UnaryNode(Token.recast(token, VOID), LiteralNode.newInstance(token, finish, 0));
2385     }
2386 
2387     /**
2388      * WithStatement :
2389      *      with ( Expression ) Statement
2390      *
2391      * See 12.10
2392      *
2393      * Parse WITH statement.
2394      */
2395     private void withStatement() {
2396         // Capture WITH token.
2397         final int  withLine  = line;
2398         final long withToken = token;
2399         // WITH tested in caller.
2400         next();
2401 
2402         // ECMA 12.10.1 strict mode restrictions
2403         if (isStrictMode) {
2404             throw error(AbstractParser.message("strict.no.with"), withToken);
2405         }
2406 
2407         expect(LPAREN);
2408         final Expression expression = expression();
2409         expect(RPAREN);
2410         final Block body = getStatement();
2411 
2412         appendStatement(new WithNode(withLine, withToken, finish, expression, body));
2413     }
2414 
2415     /**
2416      * SwitchStatement :
2417      *      switch ( Expression ) CaseBlock
2418      *
2419      * CaseBlock :
2420      *      { CaseClauses? }
2421      *      { CaseClauses? DefaultClause CaseClauses }
2422      *
2423      * CaseClauses :
2424      *      CaseClause
2425      *      CaseClauses CaseClause
2426      *
2427      * CaseClause :
2428      *      case Expression : StatementList?
2429      *
2430      * DefaultClause :
2431      *      default : StatementList?
2432      *
2433      * See 12.11
2434      *
2435      * Parse SWITCH statement.
2436      */
2437     private void switchStatement() {
2438         final int  switchLine  = line;
2439         final long switchToken = token;
2440 
2441         // Block to capture variables declared inside the switch statement.
2442         final ParserContextBlockNode switchBlock = newBlock();
2443 
2444         // SWITCH tested in caller.
2445         next();
2446 
2447         // Create and add switch statement.
2448         final ParserContextSwitchNode switchNode = new ParserContextSwitchNode();
2449         lc.push(switchNode);
2450 
2451         CaseNode defaultCase = null;
2452         // Prepare to accumulate cases.
2453         final List<CaseNode> cases = new ArrayList<>();
2454 
2455         Expression expression = null;
2456 
2457         try {
2458             expect(LPAREN);
2459             expression = expression();
2460             expect(RPAREN);
2461 
2462             expect(LBRACE);
2463 
2464 
2465             while (type != RBRACE) {
2466                 // Prepare for next case.
2467                 Expression caseExpression = null;
2468                 final long caseToken = token;
2469 
2470                 switch (type) {
2471                 case CASE:
2472                     next();
2473                     caseExpression = expression();
2474                     break;
2475 
2476                 case DEFAULT:
2477                     if (defaultCase != null) {
2478                         throw error(AbstractParser.message("duplicate.default.in.switch"));
2479                     }
2480                     next();
2481                     break;
2482 
2483                 default:
2484                     // Force an error.
2485                     expect(CASE);
2486                     break;
2487                 }
2488 
2489                 expect(COLON);
2490 
2491                 // Get CASE body.
2492                 final Block statements = getBlock(false); // TODO: List<Statement> statements = caseStatementList();
2493                 final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
2494 
2495                 if (caseExpression == null) {
2496                     defaultCase = caseNode;
2497                 }
2498 
2499                 cases.add(caseNode);
2500             }
2501 
2502             next();
2503         } finally {
2504             lc.pop(switchNode);
2505             restoreBlock(switchBlock);
2506         }
2507 
2508         final SwitchNode switchStatement = new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase);
2509         appendStatement(new BlockStatement(switchLine, new Block(switchToken, finish, switchBlock.getFlags() | Block.IS_SYNTHETIC | Block.IS_SWITCH_BLOCK, switchStatement)));
2510     }
2511 
2512     /**
2513      * LabelledStatement :
2514      *      Identifier : Statement
2515      *
2516      * See 12.12
2517      *
2518      * Parse label statement.
2519      */
2520     private void labelStatement() {
2521         // Capture label token.
2522         final long labelToken = token;
2523         // Get label ident.
2524         final IdentNode ident = getIdent();
2525 
2526         expect(COLON);
2527 
2528         if (lc.findLabel(ident.getName()) != null) {
2529             throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
2530         }
2531 
2532         final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName());
2533         Block body = null;
2534         try {
2535             lc.push(labelNode);
2536             body = getStatement(true);
2537         } finally {
2538             assert lc.peek() instanceof ParserContextLabelNode;
2539             lc.pop(labelNode);
2540         }
2541 
2542         appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
2543     }
2544 
2545     /**
2546      * ThrowStatement :
2547      *      throw Expression ; // [no LineTerminator here]
2548      *
2549      * See 12.13
2550      *
2551      * Parse throw statement.
2552      */
2553     private void throwStatement() {
2554         // Capture THROW token.
2555         final int  throwLine  = line;
2556         final long throwToken = token;
2557         // THROW tested in caller.
2558         nextOrEOL();
2559 
2560         Expression expression = null;
2561 
2562         // SEMICOLON or expression.
2563         switch (type) {
2564         case RBRACE:
2565         case SEMICOLON:
2566         case EOL:
2567             break;
2568 
2569         default:
2570             expression = expression();
2571             break;
2572         }
2573 
2574         if (expression == null) {
2575             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2576         }
2577 
2578         endOfLine();
2579 
2580         appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
2581     }
2582 
2583     /**
2584      * TryStatement :
2585      *      try Block Catch
2586      *      try Block Finally
2587      *      try Block Catch Finally
2588      *
2589      * Catch :
2590      *      catch( Identifier if Expression ) Block
2591      *      catch( Identifier ) Block
2592      *
2593      * Finally :
2594      *      finally Block
2595      *
2596      * See 12.14
2597      *
2598      * Parse TRY statement.
2599      */
2600     private void tryStatement() {
2601         // Capture TRY token.
2602         final int  tryLine  = line;
2603         final long tryToken = token;
2604         // TRY tested in caller.
2605         next();
2606 
2607         // Container block needed to act as target for labeled break statements
2608         final int startLine = line;
2609         final ParserContextBlockNode outer = newBlock();
2610         // Create try.
2611 
2612         try {
2613             final Block       tryBody     = getBlock(true);
2614             final List<Block> catchBlocks = new ArrayList<>();
2615 
2616             while (type == CATCH) {
2617                 final int  catchLine  = line;
2618                 final long catchToken = token;
2619                 next();
2620                 expect(LPAREN);
2621 
2622                 // ES6 catch parameter can be a BindingIdentifier or a BindingPattern
2623                 // http://www.ecma-international.org/ecma-262/6.0/
2624                 final String contextString = "catch argument";
2625                 final Expression exception = bindingIdentifierOrPattern(contextString);
2626                 final boolean isDestructuring = !(exception instanceof IdentNode);
2627                 if (isDestructuring) {
2628                     verifyDestructuringBindingPattern(exception, new Consumer<IdentNode>() {
2629                         @Override
2630                         public void accept(final IdentNode identNode) {
2631                             verifyIdent(identNode, contextString);
2632                         }
2633                     });
2634                 } else {
2635                     // ECMA 12.4.1 strict mode restrictions
2636                     verifyStrictIdent((IdentNode) exception, "catch argument");
2637                 }
2638 
2639 
2640                 // Nashorn extension: catch clause can have optional
2641                 // condition. So, a single try can have more than one
2642                 // catch clause each with it's own condition.
2643                 final Expression ifExpression;
2644                 if (!env._no_syntax_extensions && type == IF) {
2645                     next();
2646                     // Get the exception condition.
2647                     ifExpression = expression();
2648                 } else {
2649                     ifExpression = null;
2650                 }
2651 
2652                 expect(RPAREN);
2653 
2654                 final ParserContextBlockNode catchBlock = newBlock();
2655                 try {
2656                     // Get CATCH body.
2657                     final Block catchBody = getBlock(true);
2658                     final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
2659                     appendStatement(catchNode);
2660                 } finally {
2661                     restoreBlock(catchBlock);
2662                     catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements()));
2663                 }
2664 
2665                 // If unconditional catch then should to be the end.
2666                 if (ifExpression == null) {
2667                     break;
2668                 }
2669             }
2670 
2671             // Prepare to capture finally statement.
2672             Block finallyStatements = null;
2673 
2674             if (type == FINALLY) {
2675                 next();
2676                 finallyStatements = getBlock(true);
2677             }
2678 
2679             // Need at least one catch or a finally.
2680             if (catchBlocks.isEmpty() && finallyStatements == null) {
2681                 throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
2682             }
2683 
2684             final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
2685             // Add try.
2686             assert lc.peek() == outer;
2687             appendStatement(tryNode);
2688         } finally {
2689             restoreBlock(outer);
2690         }
2691 
2692         appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements())));
2693     }
2694 
2695     /**
2696      * DebuggerStatement :
2697      *      debugger ;
2698      *
2699      * See 12.15
2700      *
2701      * Parse debugger statement.
2702      */
2703     private void  debuggerStatement() {
2704         // Capture DEBUGGER token.
2705         final int  debuggerLine  = line;
2706         final long debuggerToken = token;
2707         // DEBUGGER tested in caller.
2708         next();
2709         endOfLine();
2710         appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish));
2711     }
2712 
2713     /**
2714      * PrimaryExpression :
2715      *      this
2716      *      IdentifierReference
2717      *      Literal
2718      *      ArrayLiteral
2719      *      ObjectLiteral
2720      *      RegularExpressionLiteral
2721      *      TemplateLiteral
2722      *      CoverParenthesizedExpressionAndArrowParameterList
2723      *
2724      * CoverParenthesizedExpressionAndArrowParameterList :
2725      *      ( Expression )
2726      *      ( )
2727      *      ( ... BindingIdentifier )
2728      *      ( Expression , ... BindingIdentifier )
2729      *
2730      * Parse primary expression.
2731      * @return Expression node.
2732      */
2733     @SuppressWarnings("fallthrough")
2734     private Expression primaryExpression() {
2735         // Capture first token.
2736         final int  primaryLine  = line;
2737         final long primaryToken = token;
2738 
2739         switch (type) {
2740         case THIS:
2741             final String name = type.getName();
2742             next();
2743             markThis(lc);
2744             return new IdentNode(primaryToken, finish, name);
2745         case IDENT:
2746             final IdentNode ident = getIdent();
2747             if (ident == null) {
2748                 break;
2749             }
2750             detectSpecialProperty(ident);
2751             return ident;
2752         case OCTAL_LEGACY:
2753             if (isStrictMode) {
2754                throw error(AbstractParser.message("strict.no.octal"), token);
2755             }
2756         case STRING:
2757         case ESCSTRING:
2758         case DECIMAL:
2759         case HEXADECIMAL:
2760         case OCTAL:
2761         case BINARY_NUMBER:
2762         case FLOATING:
2763         case REGEX:
2764         case XML:
2765             return getLiteral();
2766         case EXECSTRING:
2767             return execString(primaryLine, primaryToken);
2768         case FALSE:
2769             next();
2770             return LiteralNode.newInstance(primaryToken, finish, false);
2771         case TRUE:
2772             next();
2773             return LiteralNode.newInstance(primaryToken, finish, true);
2774         case NULL:
2775             next();
2776             return LiteralNode.newInstance(primaryToken, finish);
2777         case LBRACKET:
2778             return arrayLiteral();
2779         case LBRACE:
2780             return objectLiteral();
2781         case LPAREN:
2782             next();
2783 
2784             if (isES6()) {
2785                 if (type == RPAREN) {
2786                     // ()
2787                     nextOrEOL();
2788                     expectDontAdvance(ARROW);
2789                     return new ExpressionList(primaryToken, finish, Collections.emptyList());
2790                 } else if (type == ELLIPSIS) {
2791                     // (...rest)
2792                     final IdentNode restParam = formalParameterList(false).get(0);
2793                     expectDontAdvance(RPAREN);
2794                     nextOrEOL();
2795                     expectDontAdvance(ARROW);
2796                     return new ExpressionList(primaryToken, finish, Collections.singletonList(restParam));
2797                 }
2798             }
2799 
2800             final Expression expression = expression();
2801 
2802             expect(RPAREN);
2803 
2804             return expression;
2805         case TEMPLATE:
2806         case TEMPLATE_HEAD:
2807             return templateLiteral();
2808 
2809         default:
2810             // In this context some operator tokens mark the start of a literal.
2811             if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
2812                 next();
2813                 return getLiteral();
2814             }
2815             if (isNonStrictModeIdent()) {
2816                 return getIdent();
2817             }
2818             break;
2819         }
2820 
2821         return null;
2822     }
2823 
2824     /**
2825      * Convert execString to a call to $EXEC.
2826      *
2827      * @param primaryToken Original string token.
2828      * @return callNode to $EXEC.
2829      */
2830     CallNode execString(final int primaryLine, final long primaryToken) {
2831         // Synthesize an ident to call $EXEC.
2832         final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
2833         // Skip over EXECSTRING.
2834         next();
2835         // Set up argument list for call.
2836         // Skip beginning of edit string expression.
2837         expect(LBRACE);
2838         // Add the following expression to arguments.
2839         final List<Expression> arguments = Collections.singletonList(expression());
2840         // Skip ending of edit string expression.
2841         expect(RBRACE);
2842 
2843         return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
2844     }
2845 
2846     /**
2847      * ArrayLiteral :
2848      *      [ Elision? ]
2849      *      [ ElementList ]
2850      *      [ ElementList , Elision? ]
2851      *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
2852      *
2853      * ElementList : Elision? AssignmentExpression
2854      *      ElementList , Elision? AssignmentExpression
2855      *
2856      * Elision :
2857      *      ,
2858      *      Elision ,
2859      *
2860      * See 12.1.4
2861      * JavaScript 1.8
2862      *
2863      * Parse array literal.
2864      * @return Expression node.
2865      */
2866     @SuppressWarnings("fallthrough")
2867     private LiteralNode<Expression[]> arrayLiteral() {
2868         // Capture LBRACKET token.
2869         final long arrayToken = token;
2870         // LBRACKET tested in caller.
2871         next();
2872 
2873         // Prepare to accumulate elements.
2874         final List<Expression> elements = new ArrayList<>();
2875         // Track elisions.
2876         boolean elision = true;
2877         boolean hasSpread = false;
2878         loop:
2879         while (true) {
2880             long spreadToken = 0;
2881             switch (type) {
2882             case RBRACKET:
2883                 next();
2884 
2885                 break loop;
2886 
2887             case COMMARIGHT:
2888                 next();
2889 
2890                 // If no prior expression
2891                 if (elision) {
2892                     elements.add(null);
2893                 }
2894 
2895                 elision = true;
2896 
2897                 break;
2898 
2899             case ELLIPSIS:
2900                 if (isES6()) {
2901                     hasSpread = true;
2902                     spreadToken = token;
2903                     next();
2904                 }
2905                 // fall through
2906 
2907             default:
2908                 if (!elision) {
2909                     throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2910                 }
2911 
2912                 // Add expression element.
2913                 Expression expression = assignmentExpression(false);
2914                 if (expression != null) {
2915                     if (spreadToken != 0) {
2916                         expression = new UnaryNode(Token.recast(spreadToken, SPREAD_ARRAY), expression);
2917                     }
2918                     elements.add(expression);
2919                 } else {
2920                     expect(RBRACKET);
2921                 }
2922 
2923                 elision = false;
2924                 break;
2925             }
2926         }
2927 
2928         return LiteralNode.newInstance(arrayToken, finish, elements, hasSpread, elision);
2929     }
2930 
2931     /**
2932      * ObjectLiteral :
2933      *      { }
2934      *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2935      *
2936      * PropertyNameAndValueList :
2937      *      PropertyAssignment
2938      *      PropertyNameAndValueList , PropertyAssignment
2939      *
2940      * See 11.1.5
2941      *
2942      * Parse an object literal.
2943      * @return Expression node.
2944      */
2945     private ObjectNode objectLiteral() {
2946         // Capture LBRACE token.
2947         final long objectToken = token;
2948         // LBRACE tested in caller.
2949         next();
2950 
2951         // Object context.
2952         // Prepare to accumulate elements.
2953         final List<PropertyNode> elements = new ArrayList<>();
2954         final Map<String, Integer> map = new HashMap<>();
2955 
2956         // Create a block for the object literal.
2957         boolean commaSeen = true;
2958         loop:
2959         while (true) {
2960             switch (type) {
2961                 case RBRACE:
2962                     next();
2963                     break loop;
2964 
2965                 case COMMARIGHT:
2966                     if (commaSeen) {
2967                         throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2968                     }
2969                     next();
2970                     commaSeen = true;
2971                     break;
2972 
2973                 default:
2974                     if (!commaSeen) {
2975                         throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2976                     }
2977 
2978                     commaSeen = false;
2979                     // Get and add the next property.
2980                     final PropertyNode property = propertyAssignment();
2981 
2982                     if (property.isComputed()) {
2983                         elements.add(property);
2984                         break;
2985                     }
2986 
2987                     final String key = property.getKeyName();
2988                     final Integer existing = map.get(key);
2989 
2990                     if (existing == null) {
2991                         map.put(key, elements.size());
2992                         elements.add(property);
2993                         break;
2994                     }
2995 
2996                     final PropertyNode existingProperty = elements.get(existing);
2997 
2998                     // ECMA section 11.1.5 Object Initialiser
2999                     // point # 4 on property assignment production
3000                     final Expression   value  = property.getValue();
3001                     final FunctionNode getter = property.getGetter();
3002                     final FunctionNode setter = property.getSetter();
3003 
3004                     final Expression   prevValue  = existingProperty.getValue();
3005                     final FunctionNode prevGetter = existingProperty.getGetter();
3006                     final FunctionNode prevSetter = existingProperty.getSetter();
3007 
3008                     if (!isES6()) {
3009                         checkPropertyRedefinition(property, value, getter, setter, prevValue, prevGetter, prevSetter);
3010                     } else {
3011                         if (property.getKey() instanceof IdentNode && ((IdentNode)property.getKey()).isProtoPropertyName() &&
3012                                         existingProperty.getKey() instanceof IdentNode && ((IdentNode)existingProperty.getKey()).isProtoPropertyName()) {
3013                             throw error(AbstractParser.message("multiple.proto.key"), property.getToken());
3014                         }
3015                     }
3016 
3017                     if (value != null || prevValue != null) {
3018                         map.put(key, elements.size());
3019                         elements.add(property);
3020                     } else if (getter != null) {
3021                         assert prevGetter != null || prevSetter != null;
3022                         elements.set(existing, existingProperty.setGetter(getter));
3023                     } else if (setter != null) {
3024                         assert prevGetter != null || prevSetter != null;
3025                         elements.set(existing, existingProperty.setSetter(setter));
3026                     }
3027                     break;
3028             }
3029         }
3030 
3031         return new ObjectNode(objectToken, finish, elements);
3032     }
3033 
3034     private void checkPropertyRedefinition(final PropertyNode property, final Expression value, final FunctionNode getter, final FunctionNode setter, final Expression prevValue, final FunctionNode prevGetter, final FunctionNode prevSetter) {
3035         // ECMA 11.1.5 strict mode restrictions
3036         if (isStrictMode && value != null && prevValue != null) {
3037             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3038         }
3039 
3040         final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
3041         final boolean isAccessor     = getter != null     || setter != null;
3042 
3043         // data property redefined as accessor property
3044         if (prevValue != null && isAccessor) {
3045             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3046         }
3047 
3048         // accessor property redefined as data
3049         if (isPrevAccessor && value != null) {
3050             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3051         }
3052 
3053         if (isAccessor && isPrevAccessor) {
3054             if (getter != null && prevGetter != null ||
3055                     setter != null && prevSetter != null) {
3056                 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3057             }
3058         }
3059     }
3060 
3061     /**
3062      * LiteralPropertyName :
3063      *      IdentifierName
3064      *      StringLiteral
3065      *      NumericLiteral
3066      *
3067      * @return PropertyName node
3068      */
3069     @SuppressWarnings("fallthrough")
3070     private PropertyKey literalPropertyName() {
3071         switch (type) {
3072         case IDENT:
3073             return getIdent().setIsPropertyName();
3074         case OCTAL_LEGACY:
3075             if (isStrictMode) {
3076                 throw error(AbstractParser.message("strict.no.octal"), token);
3077             }
3078         case STRING:
3079         case ESCSTRING:
3080         case DECIMAL:
3081         case HEXADECIMAL:
3082         case OCTAL:
3083         case BINARY_NUMBER:
3084         case FLOATING:
3085             return getLiteral();
3086         default:
3087             return getIdentifierName().setIsPropertyName();
3088         }
3089     }
3090 
3091     /**
3092      * ComputedPropertyName :
3093      *      AssignmentExpression
3094      *
3095      * @return PropertyName node
3096      */
3097     private Expression computedPropertyName() {
3098         expect(LBRACKET);
3099         final Expression expression = assignmentExpression(false);
3100         expect(RBRACKET);
3101         return expression;
3102     }
3103 
3104     /**
3105      * PropertyName :
3106      *      LiteralPropertyName
3107      *      ComputedPropertyName
3108      *
3109      * @return PropertyName node
3110      */
3111     private Expression propertyName() {
3112         if (type == LBRACKET && isES6()) {
3113             return computedPropertyName();
3114         } else {
3115             return (Expression)literalPropertyName();
3116         }
3117     }
3118 
3119     /**
3120      * PropertyAssignment :
3121      *      PropertyName : AssignmentExpression
3122      *      get PropertyName ( ) { FunctionBody }
3123      *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
3124      *
3125      * PropertySetParameterList :
3126      *      Identifier
3127      *
3128      * PropertyName :
3129      *      IdentifierName
3130      *      StringLiteral
3131      *      NumericLiteral
3132      *
3133      * See 11.1.5
3134      *
3135      * Parse an object literal property.
3136      * @return Property or reference node.
3137      */
3138     private PropertyNode propertyAssignment() {
3139         // Capture firstToken.
3140         final long propertyToken = token;
3141         final int  functionLine  = line;
3142 
3143         final Expression propertyName;
3144         final boolean isIdentifier;
3145 
3146         boolean generator = false;
3147         if (type == MUL && isES6()) {
3148             generator = true;
3149             next();
3150         }
3151 
3152         final boolean computed = type == LBRACKET;
3153         if (type == IDENT) {
3154             // Get IDENT.
3155             final String ident = (String)expectValue(IDENT);
3156 
3157             if (type != COLON && (type != LPAREN || !isES6())) {
3158                 final long getSetToken = propertyToken;
3159 
3160                 switch (ident) {
3161                 case GET_NAME:
3162                     final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
3163                     return new PropertyNode(propertyToken, finish, getter.key, null, getter.functionNode, null, false, getter.computed);
3164 
3165                 case SET_NAME:
3166                     final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
3167                     return new PropertyNode(propertyToken, finish, setter.key, null, null, setter.functionNode, false, setter.computed);
3168                 default:
3169                     break;
3170                 }
3171             }
3172 
3173             isIdentifier = true;
3174             IdentNode identNode = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
3175             if (type == COLON && ident.equals("__proto__")) {
3176                 identNode = identNode.setIsProtoPropertyName();
3177             }
3178             propertyName = identNode;
3179         } else {
3180             isIdentifier = isNonStrictModeIdent();
3181             propertyName = propertyName();
3182         }
3183 
3184         Expression propertyValue;
3185 
3186         if (generator) {
3187             expectDontAdvance(LPAREN);
3188         }
3189 
3190         if (type == LPAREN && isES6()) {
3191             propertyValue = propertyMethodFunction(propertyName, propertyToken, functionLine, generator, FunctionNode.ES6_IS_METHOD, computed).functionNode;
3192         } else if (isIdentifier && (type == COMMARIGHT || type == RBRACE || type == ASSIGN) && isES6()) {
3193             propertyValue = createIdentNode(propertyToken, finish, ((IdentNode) propertyName).getPropertyName());
3194             if (type == ASSIGN && isES6()) {
3195                 // TODO if not destructuring, this is a SyntaxError
3196                 final long assignToken = token;
3197                 next();
3198                 final Expression rhs = assignmentExpression(false);
3199                 propertyValue = verifyAssignment(assignToken, propertyValue, rhs);
3200             }
3201         } else {
3202             expect(COLON);
3203 
3204             defaultNames.push(propertyName);
3205             try {
3206                 propertyValue = assignmentExpression(false);
3207             } finally {
3208                 defaultNames.pop();
3209             }
3210         }
3211 
3212         return new PropertyNode(propertyToken, finish, propertyName, propertyValue, null, null, false, computed);
3213     }
3214 
3215     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
3216         return propertyGetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
3217     }
3218 
3219     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine, final int flags) {
3220         final boolean computed = type == LBRACKET;
3221         final Expression propertyName = propertyName();
3222         final String getterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
3223         final IdentNode getNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("get " + getterName));
3224         expect(LPAREN);
3225         expect(RPAREN);
3226 
3227         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
3228         functionNode.setFlag(flags);
3229         if (computed) {
3230             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3231         }
3232         lc.push(functionNode);
3233 
3234         Block functionBody;
3235 
3236 
3237         try {
3238             functionBody = functionBody(functionNode);
3239         } finally {
3240             lc.pop(functionNode);
3241         }
3242 
3243         final FunctionNode  function = createFunctionNode(
3244                 functionNode,
3245                 getSetToken,
3246                 getNameNode,
3247                 Collections.<IdentNode>emptyList(),
3248                 FunctionNode.Kind.GETTER,
3249                 functionLine,
3250                 functionBody);
3251 
3252         return new PropertyFunction(propertyName, function, computed);
3253     }
3254 
3255     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
3256         return propertySetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
3257     }
3258 
3259     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine, final int flags) {
3260         final boolean computed = type == LBRACKET;
3261         final Expression propertyName = propertyName();
3262         final String setterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
3263         final IdentNode setNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("set " + setterName));
3264         expect(LPAREN);
3265         // be sloppy and allow missing setter parameter even though
3266         // spec does not permit it!
3267         final IdentNode argIdent;
3268         if (isBindingIdentifier()) {
3269             argIdent = getIdent();
3270             verifyIdent(argIdent, "setter argument");
3271         } else {
3272             argIdent = null;
3273         }
3274         expect(RPAREN);
3275         final List<IdentNode> parameters = new ArrayList<>();
3276         if (argIdent != null) {
3277             parameters.add(argIdent);
3278         }
3279 
3280 
3281         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
3282         functionNode.setFlag(flags);
3283         if (computed) {
3284             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3285         }
3286         lc.push(functionNode);
3287 
3288         Block functionBody;
3289         try {
3290             functionBody = functionBody(functionNode);
3291         } finally {
3292             lc.pop(functionNode);
3293         }
3294 
3295 
3296         final FunctionNode  function = createFunctionNode(
3297                 functionNode,
3298                 getSetToken,
3299                 setNameNode,
3300                 parameters,
3301                 FunctionNode.Kind.SETTER,
3302                 functionLine,
3303                 functionBody);
3304 
3305         return new PropertyFunction(propertyName, function, computed);
3306     }
3307 
3308     private PropertyFunction propertyMethodFunction(final Expression key, final long methodToken, final int methodLine, final boolean generator, final int flags, final boolean computed) {
3309         final String methodName = key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : getDefaultValidFunctionName(methodLine, false);
3310         final IdentNode methodNameNode = createIdentNode(((Node)key).getToken(), finish, methodName);
3311 
3312         final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
3313         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(methodNameNode, methodToken, functionKind, methodLine, null);
3314         functionNode.setFlag(flags);
3315         if (computed) {
3316             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3317         }
3318         lc.push(functionNode);
3319 
3320         try {
3321             final ParserContextBlockNode parameterBlock = newBlock();
3322             final List<IdentNode> parameters;
3323             try {
3324                 expect(LPAREN);
3325                 parameters = formalParameterList(generator);
3326                 functionNode.setParameters(parameters);
3327                 expect(RPAREN);
3328             } finally {
3329                 restoreBlock(parameterBlock);
3330             }
3331 
3332             Block functionBody = functionBody(functionNode);
3333 
3334             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
3335 
3336             final FunctionNode  function = createFunctionNode(
3337                             functionNode,
3338                             methodToken,
3339                             methodNameNode,
3340                             parameters,
3341                             functionKind,
3342                             methodLine,
3343                             functionBody);
3344             return new PropertyFunction(key, function, computed);
3345         } finally {
3346             lc.pop(functionNode);
3347         }
3348     }
3349 
3350     private static class PropertyFunction {
3351         final Expression key;
3352         final FunctionNode functionNode;
3353         final boolean computed;
3354 
3355         PropertyFunction(final Expression key, final FunctionNode function, final boolean computed) {
3356             this.key = key;
3357             this.functionNode = function;
3358             this.computed = computed;
3359         }
3360     }
3361 
3362     /**
3363      * LeftHandSideExpression :
3364      *      NewExpression
3365      *      CallExpression
3366      *
3367      * CallExpression :
3368      *      MemberExpression Arguments
3369      *      SuperCall
3370      *      CallExpression Arguments
3371      *      CallExpression [ Expression ]
3372      *      CallExpression . IdentifierName
3373      *
3374      * SuperCall :
3375      *      super Arguments
3376      *
3377      * See 11.2
3378      *
3379      * Parse left hand side expression.
3380      * @return Expression node.
3381      */
3382     private Expression leftHandSideExpression() {
3383         int  callLine  = line;
3384         long callToken = token;
3385 
3386         Expression lhs = memberExpression();
3387 
3388         if (type == LPAREN) {
3389             final List<Expression> arguments = optimizeList(argumentList());
3390 
3391             // Catch special functions.
3392             if (lhs instanceof IdentNode) {
3393                 detectSpecialFunction((IdentNode)lhs);
3394             }
3395 
3396             lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3397         }
3398 
3399         loop:
3400         while (true) {
3401             // Capture token.
3402             callLine  = line;
3403             callToken = token;
3404 
3405             switch (type) {
3406             case LPAREN: {
3407                 // Get NEW or FUNCTION arguments.
3408                 final List<Expression> arguments = optimizeList(argumentList());
3409 
3410                 // Create call node.
3411                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3412 
3413                 break;
3414             }
3415             case LBRACKET: {
3416                 next();
3417 
3418                 // Get array index.
3419                 final Expression rhs = expression();
3420 
3421                 expect(RBRACKET);
3422 
3423                 // Create indexing node.
3424                 lhs = new IndexNode(callToken, finish, lhs, rhs);
3425 
3426                 break;
3427             }
3428             case PERIOD: {
3429                 next();
3430 
3431                 final IdentNode property = getIdentifierName();
3432 
3433                 // Create property access node.
3434                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
3435 
3436                 break;
3437             }
3438             case TEMPLATE:
3439             case TEMPLATE_HEAD: {
3440                 // tagged template literal
3441                 final List<Expression> arguments = templateLiteralArgumentList();
3442 
3443                 // Create call node.
3444                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3445 
3446                 break;
3447             }
3448             default:
3449                 break loop;
3450             }
3451         }
3452 
3453         return lhs;
3454     }
3455 
3456     /**
3457      * NewExpression :
3458      *      MemberExpression
3459      *      new NewExpression
3460      *
3461      * See 11.2
3462      *
3463      * Parse new expression.
3464      * @return Expression node.
3465      */
3466     private Expression newExpression() {
3467         final long newToken = token;
3468         // NEW is tested in caller.
3469         next();
3470 
3471         if (type == PERIOD && isES6()) {
3472             next();
3473             if (type == IDENT && "target".equals(getValue())) {
3474                 if (lc.getCurrentFunction().isProgram()) {
3475                     throw error(AbstractParser.message("new.target.in.function"), token);
3476                 }
3477                 next();
3478                 markNewTarget(lc);
3479                 return new IdentNode(newToken, finish, "new.target");
3480             } else {
3481                 throw error(AbstractParser.message("expected.target"), token);
3482             }
3483         }
3484 
3485         // Get function base.
3486         final int  callLine    = line;
3487         final Expression constructor = memberExpression();
3488         if (constructor == null) {
3489             return null;
3490         }
3491         // Get arguments.
3492         ArrayList<Expression> arguments;
3493 
3494         // Allow for missing arguments.
3495         if (type == LPAREN) {
3496             arguments = argumentList();
3497         } else {
3498             arguments = new ArrayList<>();
3499         }
3500 
3501         // Nashorn extension: This is to support the following interface implementation
3502         // syntax:
3503         //
3504         //     var r = new java.lang.Runnable() {
3505         //         run: function() { println("run"); }
3506         //     };
3507         //
3508         // The object literal following the "new Constructor()" expression
3509         // is passed as an additional (last) argument to the constructor.
3510         if (!env._no_syntax_extensions && type == LBRACE) {
3511             arguments.add(objectLiteral());
3512         }
3513 
3514         final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
3515 
3516         return new UnaryNode(newToken, callNode);
3517     }
3518 
3519     /**
3520      * MemberExpression :
3521      *      PrimaryExpression
3522      *        FunctionExpression
3523      *        ClassExpression
3524      *        GeneratorExpression
3525      *      MemberExpression [ Expression ]
3526      *      MemberExpression . IdentifierName
3527      *      MemberExpression TemplateLiteral
3528      *      SuperProperty
3529      *      MetaProperty
3530      *      new MemberExpression Arguments
3531      *
3532      * SuperProperty :
3533      *      super [ Expression ]
3534      *      super . IdentifierName
3535      *
3536      * MetaProperty :
3537      *      NewTarget
3538      *
3539      * Parse member expression.
3540      * @return Expression node.
3541      */
3542     @SuppressWarnings("fallthrough")
3543     private Expression memberExpression() {
3544         // Prepare to build operation.
3545         Expression lhs;
3546         boolean isSuper = false;
3547 
3548         switch (type) {
3549         case NEW:
3550             // Get new expression.
3551             lhs = newExpression();
3552             break;
3553 
3554         case FUNCTION:
3555             // Get function expression.
3556             lhs = functionExpression(false, false);
3557             break;
3558 
3559         case CLASS:
3560             if (isES6()) {
3561                 lhs = classExpression(false);
3562                 break;
3563             } else {
3564                 // fall through
3565             }
3566 
3567         case SUPER:
3568             if (isES6()) {
3569                 final ParserContextFunctionNode currentFunction = getCurrentNonArrowFunction();
3570                 if (currentFunction.isMethod()) {
3571                     final long identToken = Token.recast(token, IDENT);
3572                     next();
3573                     lhs = createIdentNode(identToken, finish, SUPER.getName());
3574 
3575                     switch (type) {
3576                         case LBRACKET:
3577                         case PERIOD:
3578                             getCurrentNonArrowFunction().setFlag(FunctionNode.ES6_USES_SUPER);
3579                             isSuper = true;
3580                             break;
3581                         case LPAREN:
3582                             if (currentFunction.isSubclassConstructor()) {
3583                                 lhs = ((IdentNode)lhs).setIsDirectSuper();
3584                                 break;
3585                             } else {
3586                                 // fall through to throw error
3587                             }
3588                         default:
3589                             throw error(AbstractParser.message("invalid.super"), identToken);
3590                     }
3591                     break;
3592                 } else {
3593                     // fall through
3594                 }
3595             } else {
3596                 // fall through
3597             }
3598 
3599         default:
3600             // Get primary expression.
3601             lhs = primaryExpression();
3602             break;
3603         }
3604 
3605         loop:
3606         while (true) {
3607             // Capture token.
3608             final long callToken = token;
3609 
3610             switch (type) {
3611             case LBRACKET: {
3612                 next();
3613 
3614                 // Get array index.
3615                 final Expression index = expression();
3616 
3617                 expect(RBRACKET);
3618 
3619                 // Create indexing node.
3620                 lhs = new IndexNode(callToken, finish, lhs, index);
3621 
3622                 if (isSuper) {
3623                     isSuper = false;
3624                     lhs = ((BaseNode) lhs).setIsSuper();
3625                 }
3626 
3627                 break;
3628             }
3629             case PERIOD: {
3630                 if (lhs == null) {
3631                     throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3632                 }
3633 
3634                 next();
3635 
3636                 final IdentNode property = getIdentifierName();
3637 
3638                 // Create property access node.
3639                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
3640 
3641                 if (isSuper) {
3642                     isSuper = false;
3643                     lhs = ((BaseNode) lhs).setIsSuper();
3644                 }
3645 
3646                 break;
3647             }
3648             case TEMPLATE:
3649             case TEMPLATE_HEAD: {
3650                 // tagged template literal
3651                 final int callLine = line;
3652                 final List<Expression> arguments = templateLiteralArgumentList();
3653 
3654                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3655 
3656                 break;
3657             }
3658             default:
3659                 break loop;
3660             }
3661         }
3662 
3663         return lhs;
3664     }
3665 
3666     /**
3667      * Arguments :
3668      *      ( )
3669      *      ( ArgumentList )
3670      *
3671      * ArgumentList :
3672      *      AssignmentExpression
3673      *      ... AssignmentExpression
3674      *      ArgumentList , AssignmentExpression
3675      *      ArgumentList , ... AssignmentExpression
3676      *
3677      * See 11.2
3678      *
3679      * Parse function call arguments.
3680      * @return Argument list.
3681      */
3682     private ArrayList<Expression> argumentList() {
3683         // Prepare to accumulate list of arguments.
3684         final ArrayList<Expression> nodeList = new ArrayList<>();
3685         // LPAREN tested in caller.
3686         next();
3687 
3688         // Track commas.
3689         boolean first = true;
3690 
3691         while (type != RPAREN) {
3692             // Comma prior to every argument except the first.
3693             if (!first) {
3694                 expect(COMMARIGHT);
3695             } else {
3696                 first = false;
3697             }
3698 
3699             long spreadToken = 0;
3700             if (type == ELLIPSIS && isES6()) {
3701                 spreadToken = token;
3702                 next();
3703             }
3704 
3705             // Get argument expression.
3706             Expression expression = assignmentExpression(false);
3707             if (spreadToken != 0) {
3708                 expression = new UnaryNode(Token.recast(spreadToken, TokenType.SPREAD_ARGUMENT), expression);
3709             }
3710             nodeList.add(expression);
3711         }
3712 
3713         expect(RPAREN);
3714         return nodeList;
3715     }
3716 
3717     private static <T> List<T> optimizeList(final ArrayList<T> list) {
3718         switch(list.size()) {
3719             case 0: {
3720                 return Collections.emptyList();
3721             }
3722             case 1: {
3723                 return Collections.singletonList(list.get(0));
3724             }
3725             default: {
3726                 list.trimToSize();
3727                 return list;
3728             }
3729         }
3730     }
3731 
3732     /**
3733      * FunctionDeclaration :
3734      *      function Identifier ( FormalParameterList? ) { FunctionBody }
3735      *
3736      * FunctionExpression :
3737      *      function Identifier? ( FormalParameterList? ) { FunctionBody }
3738      *
3739      * See 13
3740      *
3741      * Parse function declaration.
3742      * @param isStatement True if for is a statement.
3743      *
3744      * @return Expression node.
3745      */
3746     private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
3747         final long functionToken = token;
3748         final int  functionLine  = line;
3749         // FUNCTION is tested in caller.
3750         assert type == FUNCTION;
3751         next();
3752 
3753         boolean generator = false;
3754         if (type == MUL && isES6()) {
3755             generator = true;
3756             next();
3757         }
3758 
3759         IdentNode name = null;
3760 
3761         if (isBindingIdentifier()) {
3762             if (type == YIELD && ((!isStatement && generator) || (isStatement && inGeneratorFunction()))) {
3763                 // 12.1.1 Early SyntaxError if:
3764                 // GeneratorExpression with BindingIdentifier yield
3765                 // HoistableDeclaration with BindingIdentifier yield in generator function body
3766                 expect(IDENT);
3767             }
3768             name = getIdent();
3769             verifyStrictIdent(name, "function name");
3770         } else if (isStatement) {
3771             // Nashorn extension: anonymous function statements.
3772             // Do not allow anonymous function statement if extensions
3773             // are now allowed. But if we are reparsing then anon function
3774             // statement is possible - because it was used as function
3775             // expression in surrounding code.
3776             if (env._no_syntax_extensions && reparsedFunction == null) {
3777                 expect(IDENT);
3778             }
3779         }
3780 
3781         // name is null, generate anonymous name
3782         boolean isAnonymous = false;
3783         if (name == null) {
3784             final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
3785             name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
3786             isAnonymous = true;
3787         }
3788 
3789         final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
3790         List<IdentNode> parameters = Collections.emptyList();
3791         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, functionKind, functionLine, parameters);
3792         lc.push(functionNode);
3793 
3794         Block functionBody = null;
3795         // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
3796         // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
3797         hideDefaultName();
3798         try {
3799             final ParserContextBlockNode parameterBlock = newBlock();
3800             try {
3801                 expect(LPAREN);
3802                 parameters = formalParameterList(generator);
3803                 functionNode.setParameters(parameters);
3804                 expect(RPAREN);
3805             } finally {
3806                 restoreBlock(parameterBlock);
3807             }
3808 
3809             functionBody = functionBody(functionNode);
3810 
3811             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
3812         } finally {
3813             defaultNames.pop();
3814             lc.pop(functionNode);
3815         }
3816 
3817         if (isStatement) {
3818             if (topLevel || useBlockScope() || (!isStrictMode && env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ACCEPT)) {
3819                 functionNode.setFlag(FunctionNode.IS_DECLARED);
3820             } else if (isStrictMode) {
3821                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
3822             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
3823                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
3824             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
3825                 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
3826             }
3827             if (isArguments(name)) {
3828                lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
3829             }
3830         }
3831 
3832         if (isAnonymous) {
3833             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3834         }
3835 
3836         verifyParameterList(parameters, functionNode);
3837 
3838         final FunctionNode function = createFunctionNode(
3839                 functionNode,
3840                 functionToken,
3841                 name,
3842                 parameters,
3843                 functionKind,
3844                 functionLine,
3845                 functionBody);
3846 
3847         if (isStatement) {
3848             if (isAnonymous) {
3849                 appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function));
3850                 return function;
3851             }
3852 
3853             // mark ES6 block functions as lexically scoped
3854             final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
3855             final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
3856             if (topLevel) {
3857                 functionDeclarations.add(varNode);
3858             } else if (useBlockScope()) {
3859                 prependStatement(varNode); // Hoist to beginning of current block
3860             } else {
3861                 appendStatement(varNode);
3862             }
3863         }
3864 
3865         return function;
3866     }
3867 
3868     private void verifyParameterList(final List<IdentNode> parameters, final ParserContextFunctionNode functionNode) {
3869         final IdentNode duplicateParameter = functionNode.getDuplicateParameterBinding();
3870         if (duplicateParameter != null) {
3871             if (functionNode.isStrict() || functionNode.getKind() == FunctionNode.Kind.ARROW || !functionNode.isSimpleParameterList()) {
3872                 throw error(AbstractParser.message("strict.param.redefinition", duplicateParameter.getName()), duplicateParameter.getToken());
3873             }
3874 
3875             final int arity = parameters.size();
3876             final HashSet<String> parametersSet = new HashSet<>(arity);
3877 
3878             for (int i = arity - 1; i >= 0; i--) {
3879                 final IdentNode parameter = parameters.get(i);
3880                 String parameterName = parameter.getName();
3881 
3882                 if (parametersSet.contains(parameterName)) {
3883                     // redefinition of parameter name, rename in non-strict mode
3884                     parameterName = functionNode.uniqueName(parameterName);
3885                     final long parameterToken = parameter.getToken();
3886                     parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
3887                 }
3888                 parametersSet.add(parameterName);
3889             }
3890         }
3891     }
3892 
3893     private static Block maybeWrapBodyInParameterBlock(final Block functionBody, final ParserContextBlockNode parameterBlock) {
3894         assert functionBody.isFunctionBody();
3895         if (!parameterBlock.getStatements().isEmpty()) {
3896             parameterBlock.appendStatement(new BlockStatement(functionBody));
3897             return new Block(parameterBlock.getToken(), functionBody.getFinish(), (functionBody.getFlags() | Block.IS_PARAMETER_BLOCK) & ~Block.IS_BODY, parameterBlock.getStatements());
3898         }
3899         return functionBody;
3900     }
3901 
3902     private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
3903         final String defaultFunctionName = getDefaultFunctionName();
3904         if (isValidIdentifier(defaultFunctionName)) {
3905             if (isStatement) {
3906                 // The name will be used as the LHS of a symbol assignment. We add the anonymous function
3907                 // prefix to ensure that it can't clash with another variable.
3908                 return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
3909             }
3910             return defaultFunctionName;
3911         }
3912         return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
3913     }
3914 
3915     private static boolean isValidIdentifier(final String name) {
3916         if (name == null || name.isEmpty()) {
3917             return false;
3918         }
3919         if (!Character.isJavaIdentifierStart(name.charAt(0))) {
3920             return false;
3921         }
3922         for (int i = 1; i < name.length(); ++i) {
3923             if (!Character.isJavaIdentifierPart(name.charAt(i))) {
3924                 return false;
3925             }
3926         }
3927         return true;
3928     }
3929 
3930     private String getDefaultFunctionName() {
3931         if (!defaultNames.isEmpty()) {
3932             final Object nameExpr = defaultNames.peek();
3933             if (nameExpr instanceof PropertyKey) {
3934                 markDefaultNameUsed();
3935                 return ((PropertyKey)nameExpr).getPropertyName();
3936             } else if (nameExpr instanceof AccessNode) {
3937                 markDefaultNameUsed();
3938                 return ((AccessNode)nameExpr).getProperty();
3939             }
3940         }
3941         return null;
3942     }
3943 
3944     private void markDefaultNameUsed() {
3945         defaultNames.pop();
3946         hideDefaultName();
3947     }
3948 
3949     private void hideDefaultName() {
3950         // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
3951         // from. Can't be null
3952         defaultNames.push("");
3953     }
3954 
3955     /**
3956      * FormalParameterList :
3957      *      Identifier
3958      *      FormalParameterList , Identifier
3959      *
3960      * See 13
3961      *
3962      * Parse function parameter list.
3963      * @return List of parameter nodes.
3964      */
3965     private List<IdentNode> formalParameterList(final boolean yield) {
3966         return formalParameterList(RPAREN, yield);
3967     }
3968 
3969     /**
3970      * Same as the other method of the same name - except that the end
3971      * token type expected is passed as argument to this method.
3972      *
3973      * FormalParameterList :
3974      *      Identifier
3975      *      FormalParameterList , Identifier
3976      *
3977      * See 13
3978      *
3979      * Parse function parameter list.
3980      * @return List of parameter nodes.
3981      */
3982     private List<IdentNode> formalParameterList(final TokenType endType, final boolean yield) {
3983         // Prepare to gather parameters.
3984         final ArrayList<IdentNode> parameters = new ArrayList<>();
3985         // Track commas.
3986         boolean first = true;
3987 
3988         while (type != endType) {
3989             // Comma prior to every argument except the first.
3990             if (!first) {
3991                 expect(COMMARIGHT);
3992             } else {
3993                 first = false;
3994             }
3995 
3996             boolean restParameter = false;
3997             if (type == ELLIPSIS && isES6()) {
3998                 next();
3999                 restParameter = true;
4000             }
4001 
4002             if (type == YIELD && yield) {
4003                 expect(IDENT);
4004             }
4005 
4006             final long paramToken = token;
4007             final int paramLine = line;
4008             final String contextString = "function parameter";
4009             IdentNode ident;
4010             if (isBindingIdentifier() || restParameter || !isES6()) {
4011                 ident = bindingIdentifier(contextString);
4012 
4013                 if (restParameter) {
4014                     ident = ident.setIsRestParameter();
4015                     // rest parameter must be last
4016                     expectDontAdvance(endType);
4017                     parameters.add(ident);
4018                     break;
4019                 } else if (type == ASSIGN && isES6()) {
4020                     next();
4021                     ident = ident.setIsDefaultParameter();
4022 
4023                     if (type == YIELD && yield) {
4024                         // error: yield in default expression
4025                         expect(IDENT);
4026                     }
4027 
4028                     // default parameter
4029                     final Expression initializer = assignmentExpression(false);
4030 
4031                     final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4032                     if (currentFunction != null) {
4033                         if (env._parse_only) {
4034                             // keep what is seen in source "as is" and save it as parameter expression
4035                             final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, initializer);
4036                             currentFunction.addParameterExpression(ident, assignment);
4037                         } else {
4038                             // desugar to: param = (param === undefined) ? initializer : param;
4039                             // possible alternative: if (param === undefined) param = initializer;
4040                             final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4041                             final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4042                             final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
4043                             lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4044                         }
4045                     }
4046                 }
4047 
4048                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4049                 if (currentFunction != null) {
4050                     currentFunction.addParameterBinding(ident);
4051                     if (ident.isRestParameter() || ident.isDefaultParameter()) {
4052                         currentFunction.setSimpleParameterList(false);
4053                     }
4054                 }
4055             } else {
4056                 final Expression pattern = bindingPattern();
4057                 // Introduce synthetic temporary parameter to capture the object to be destructured.
4058                 ident = createIdentNode(paramToken, pattern.getFinish(), String.format("arguments[%d]", parameters.size())).setIsDestructuredParameter();
4059                 verifyDestructuringParameterBindingPattern(pattern, paramToken, paramLine, contextString);
4060 
4061                 Expression value = ident;
4062                 if (type == ASSIGN) {
4063                     next();
4064                     ident = ident.setIsDefaultParameter();
4065 
4066                     // binding pattern with initializer. desugar to: (param === undefined) ? initializer : param
4067                     final Expression initializer = assignmentExpression(false);
4068 
4069                     if (env._parse_only) {
4070                         // we don't want the synthetic identifier in parse only mode
4071                         value = initializer;
4072                     } else {
4073                         // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list)
4074                         final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4075                         value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4076                     }
4077                 }
4078 
4079                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4080                 if (currentFunction != null) {
4081                     // destructuring assignment
4082                     final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), pattern, value);
4083                     if (env._parse_only) {
4084                         // in parse-only mode, represent source tree "as is"
4085                         if (ident.isDefaultParameter()) {
4086                             currentFunction.addParameterExpression(ident, assignment);
4087                         } else {
4088                             currentFunction.addParameterExpression(ident, pattern);
4089                         }
4090                     } else {
4091                         lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4092                     }
4093                 }
4094             }
4095             parameters.add(ident);
4096         }
4097 
4098         parameters.trimToSize();
4099         return parameters;
4100     }
4101 
4102     private void verifyDestructuringParameterBindingPattern(final Expression pattern, final long paramToken, final int paramLine, final String contextString) {
4103         verifyDestructuringBindingPattern(pattern, new Consumer<IdentNode>() {
4104             public void accept(final IdentNode identNode) {
4105                 verifyIdent(identNode, contextString);
4106 
4107                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4108                 if (currentFunction != null) {
4109                     // declare function-scope variables for destructuring bindings
4110                     if (!env._parse_only) {
4111                         lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null));
4112                     }
4113                     // detect duplicate bounds names in parameter list
4114                     currentFunction.addParameterBinding(identNode);
4115                     currentFunction.setSimpleParameterList(false);
4116                 }
4117             }
4118         });
4119     }
4120 
4121     /**
4122      * FunctionBody :
4123      *      SourceElements?
4124      *
4125      * See 13
4126      *
4127      * Parse function body.
4128      * @return function node (body.)
4129      */
4130     private Block functionBody(final ParserContextFunctionNode functionNode) {
4131         long lastToken = 0L;
4132         ParserContextBlockNode body = null;
4133         final long bodyToken = token;
4134         Block functionBody;
4135         int bodyFinish = 0;
4136 
4137         final boolean parseBody;
4138         Object endParserState = null;
4139         try {
4140             // Create a new function block.
4141             body = newBlock();
4142             if (env._debug_scopes) {
4143                 // debug scope options forces everything to be in scope
4144                 markEval(lc);
4145             }
4146             assert functionNode != null;
4147             final int functionId = functionNode.getId();
4148             parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
4149             // Nashorn extension: expression closures
4150             if ((!env._no_syntax_extensions || functionNode.getKind() == FunctionNode.Kind.ARROW) && type != LBRACE) {
4151                 /*
4152                  * Example:
4153                  *
4154                  * function square(x) x * x;
4155                  * print(square(3));
4156                  */
4157 
4158                 // just expression as function body
4159                 final Expression expr = assignmentExpression(false);
4160                 lastToken = previousToken;
4161                 functionNode.setLastToken(previousToken);
4162                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
4163                 // EOL uses length field to store the line number
4164                 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
4165                 // Only create the return node if we aren't skipping nested functions. Note that we aren't
4166                 // skipping parsing of these extended functions; they're considered to be small anyway. Also,
4167                 // they don't end with a single well known token, so it'd be very hard to get correctly (see
4168                 // the note below for reasoning on skipping happening before instead of after RBRACE for
4169                 // details).
4170                 if (parseBody) {
4171                     functionNode.setFlag(FunctionNode.HAS_EXPRESSION_BODY);
4172                     final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
4173                     appendStatement(returnNode);
4174                 }
4175                 // bodyFinish = finish;
4176             } else {
4177                 expectDontAdvance(LBRACE);
4178                 if (parseBody || !skipFunctionBody(functionNode)) {
4179                     next();
4180                     // Gather the function elements.
4181                     final List<Statement> prevFunctionDecls = functionDeclarations;
4182                     functionDeclarations = new ArrayList<>();
4183                     try {
4184                         sourceElements(0);
4185                         addFunctionDeclarations(functionNode);
4186                     } finally {
4187                         functionDeclarations = prevFunctionDecls;
4188                     }
4189 
4190                     lastToken = token;
4191                     if (parseBody) {
4192                         // Since the lexer can read ahead and lexify some number of tokens in advance and have
4193                         // them buffered in the TokenStream, we need to produce a lexer state as it was just
4194                         // before it lexified RBRACE, and not whatever is its current (quite possibly well read
4195                         // ahead) state.
4196                         endParserState = new ParserState(Token.descPosition(token), line, linePosition);
4197 
4198                         // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
4199                         // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
4200                         // state after it. The reason is that RBRACE is a well-known token that we can expect and
4201                         // will never involve us getting into a weird lexer state, and as such is a great reparse
4202                         // point. Typical example of a weird lexer state after RBRACE would be:
4203                         //     function this_is_skipped() { ... } "use strict";
4204                         // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
4205                         // of compensating for the possibility of a string literal (or similar) after RBRACE,
4206                         // we'll rather just restart parsing from this well-known, friendly token instead.
4207                     }
4208                 }
4209                 bodyFinish = finish;
4210                 functionNode.setLastToken(token);
4211                 expect(RBRACE);
4212             }
4213         } finally {
4214             restoreBlock(body);
4215         }
4216 
4217         // NOTE: we can only do alterations to the function node after restoreFunctionNode.
4218 
4219         if (parseBody) {
4220             functionNode.setEndParserState(endParserState);
4221         } else if (!body.getStatements().isEmpty()){
4222             // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
4223             // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
4224             // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
4225             // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
4226             // nested bodies early if we were supposed to skip 'em.
4227             body.setStatements(Collections.<Statement>emptyList());
4228         }
4229 
4230         if (reparsedFunction != null) {
4231             // We restore the flags stored in the function's ScriptFunctionData that we got when we first
4232             // eagerly parsed the code. We're doing it because some flags would be set based on the
4233             // content of the function, or even content of its nested functions, most of which are normally
4234             // skipped during an on-demand compilation.
4235             final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
4236             if (data != null) {
4237                 // Data can be null if when we originally parsed the file, we removed the function declaration
4238                 // as it was dead code.
4239                 functionNode.setFlag(data.getFunctionFlags());
4240                 // This compensates for missing markEval() in case the function contains an inner function
4241                 // that contains eval(), that now we didn't discover since we skipped the inner function.
4242                 if (functionNode.hasNestedEval()) {
4243                     assert functionNode.hasScopeBlock();
4244                     body.setFlag(Block.NEEDS_SCOPE);
4245                 }
4246             }
4247         }
4248         functionBody = new Block(bodyToken, bodyFinish, body.getFlags() | Block.IS_BODY, body.getStatements());
4249         return functionBody;
4250     }
4251 
4252     private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
4253         if (reparsedFunction == null) {
4254             // Not reparsing, so don't skip any function body.
4255             return false;
4256         }
4257         // Skip to the RBRACE of this function, and continue parsing from there.
4258         final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
4259         if (data == null) {
4260             // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
4261             // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
4262             // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
4263             return false;
4264         }
4265         final ParserState parserState = (ParserState)data.getEndParserState();
4266         assert parserState != null;
4267 
4268         if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) {
4269             // RBRACE is already in the token stream, so fast forward to it
4270             for (; k < stream.last(); k++) {
4271                 final long nextToken = stream.get(k + 1);
4272                 if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) {
4273                     token = stream.get(k);
4274                     type = Token.descType(token);
4275                     next();
4276                     assert type == RBRACE && start == parserState.position;
4277                     return true;
4278                 }
4279             }
4280         }
4281 
4282         stream.reset();
4283         lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
4284         line = parserState.line;
4285         linePosition = parserState.linePosition;
4286         // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
4287         // the RBRACE.
4288         type = SEMICOLON;
4289         scanFirstToken();
4290 
4291         return true;
4292     }
4293 
4294     /**
4295      * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
4296      * for resuming parsing after skipping a function body.
4297      */
4298     private static class ParserState implements Serializable {
4299         private final int position;
4300         private final int line;
4301         private final int linePosition;
4302 
4303         private static final long serialVersionUID = -2382565130754093694L;
4304 
4305         ParserState(final int position, final int line, final int linePosition) {
4306             this.position = position;
4307             this.line = line;
4308             this.linePosition = linePosition;
4309         }
4310 
4311         Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
4312             final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
4313             newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
4314             return newLexer;
4315         }
4316     }
4317 
4318     private void printAST(final FunctionNode functionNode) {
4319         if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) {
4320             env.getErr().println(new ASTWriter(functionNode));
4321         }
4322 
4323         if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) {
4324             env.getErr().println(new PrintVisitor(functionNode, true, false));
4325         }
4326     }
4327 
4328     private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
4329         VarNode lastDecl = null;
4330         for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
4331             Statement decl = functionDeclarations.get(i);
4332             if (lastDecl == null && decl instanceof VarNode) {
4333                 decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
4334                 functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
4335             }
4336             prependStatement(decl);
4337         }
4338     }
4339 
4340     private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
4341         if (env._parse_only || earlyError) {
4342             throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
4343         }
4344         final ArrayList<Expression> args = new ArrayList<>();
4345         args.add(lhs);
4346         if (rhs == null) {
4347             args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
4348         } else {
4349             args.add(rhs);
4350         }
4351         args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
4352         return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
4353     }
4354 
4355     /**
4356      * PostfixExpression :
4357      *      LeftHandSideExpression
4358      *      LeftHandSideExpression ++ // [no LineTerminator here]
4359      *      LeftHandSideExpression -- // [no LineTerminator here]
4360      *
4361      * See 11.3
4362      *
4363      * UnaryExpression :
4364      *      PostfixExpression
4365      *      delete UnaryExpression
4366      *      void UnaryExpression
4367      *      typeof UnaryExpression
4368      *      ++ UnaryExpression
4369      *      -- UnaryExpression
4370      *      + UnaryExpression
4371      *      - UnaryExpression
4372      *      ~ UnaryExpression
4373      *      ! UnaryExpression
4374      *
4375      * See 11.4
4376      *
4377      * Parse unary expression.
4378      * @return Expression node.
4379      */
4380     private Expression unaryExpression() {
4381         final int  unaryLine  = line;
4382         final long unaryToken = token;
4383 
4384         switch (type) {
4385         case DELETE: {
4386             next();
4387             final Expression expr = unaryExpression();
4388             if (expr instanceof BaseNode || expr instanceof IdentNode) {
4389                 return new UnaryNode(unaryToken, expr);
4390             }
4391             appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
4392             return LiteralNode.newInstance(unaryToken, finish, true);
4393         }
4394         case VOID:
4395         case TYPEOF:
4396         case ADD:
4397         case SUB:
4398         case BIT_NOT:
4399         case NOT:
4400             next();
4401             final Expression expr = unaryExpression();
4402             return new UnaryNode(unaryToken, expr);
4403 
4404         case INCPREFIX:
4405         case DECPREFIX:
4406             final TokenType opType = type;
4407             next();
4408 
4409             final Expression lhs = leftHandSideExpression();
4410             // ++, -- without operand..
4411             if (lhs == null) {
4412                 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
4413             }
4414 
4415             return verifyIncDecExpression(unaryToken, opType, lhs, false);
4416 
4417         default:
4418             break;
4419         }
4420 
4421         final Expression expression = leftHandSideExpression();
4422 
4423         if (last != EOL) {
4424             switch (type) {
4425             case INCPREFIX:
4426             case DECPREFIX:
4427                 final long opToken = token;
4428                 final TokenType opType = type;
4429                 final Expression lhs = expression;
4430                 // ++, -- without operand..
4431                 if (lhs == null) {
4432                     throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
4433                 }
4434                 next();
4435 
4436                 return verifyIncDecExpression(opToken, opType, lhs, true);
4437             default:
4438                 break;
4439             }
4440         }
4441 
4442         if (expression == null) {
4443             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
4444         }
4445 
4446         return expression;
4447     }
4448 
4449     private Expression verifyIncDecExpression(final long unaryToken, final TokenType opType, final Expression lhs, final boolean isPostfix) {
4450         assert lhs != null;
4451 
4452         if (!(lhs instanceof AccessNode ||
4453               lhs instanceof IndexNode ||
4454               lhs instanceof IdentNode)) {
4455             return referenceError(lhs, null, env._early_lvalue_error);
4456         }
4457 
4458         if (lhs instanceof IdentNode) {
4459             if (!checkIdentLValue((IdentNode)lhs)) {
4460                 return referenceError(lhs, null, false);
4461             }
4462             verifyIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
4463         }
4464 
4465         return incDecExpression(unaryToken, opType, lhs, isPostfix);
4466     }
4467 
4468     /**
4469      * {@code
4470      * MultiplicativeExpression :
4471      *      UnaryExpression
4472      *      MultiplicativeExpression * UnaryExpression
4473      *      MultiplicativeExpression / UnaryExpression
4474      *      MultiplicativeExpression % UnaryExpression
4475      *
4476      * See 11.5
4477      *
4478      * AdditiveExpression :
4479      *      MultiplicativeExpression
4480      *      AdditiveExpression + MultiplicativeExpression
4481      *      AdditiveExpression - MultiplicativeExpression
4482      *
4483      * See 11.6
4484      *
4485      * ShiftExpression :
4486      *      AdditiveExpression
4487      *      ShiftExpression << AdditiveExpression
4488      *      ShiftExpression >> AdditiveExpression
4489      *      ShiftExpression >>> AdditiveExpression
4490      *
4491      * See 11.7
4492      *
4493      * RelationalExpression :
4494      *      ShiftExpression
4495      *      RelationalExpression < ShiftExpression
4496      *      RelationalExpression > ShiftExpression
4497      *      RelationalExpression <= ShiftExpression
4498      *      RelationalExpression >= ShiftExpression
4499      *      RelationalExpression instanceof ShiftExpression
4500      *      RelationalExpression in ShiftExpression // if !noIf
4501      *
4502      * See 11.8
4503      *
4504      *      RelationalExpression
4505      *      EqualityExpression == RelationalExpression
4506      *      EqualityExpression != RelationalExpression
4507      *      EqualityExpression === RelationalExpression
4508      *      EqualityExpression !== RelationalExpression
4509      *
4510      * See 11.9
4511      *
4512      * BitwiseANDExpression :
4513      *      EqualityExpression
4514      *      BitwiseANDExpression & EqualityExpression
4515      *
4516      * BitwiseXORExpression :
4517      *      BitwiseANDExpression
4518      *      BitwiseXORExpression ^ BitwiseANDExpression
4519      *
4520      * BitwiseORExpression :
4521      *      BitwiseXORExpression
4522      *      BitwiseORExpression | BitwiseXORExpression
4523      *
4524      * See 11.10
4525      *
4526      * LogicalANDExpression :
4527      *      BitwiseORExpression
4528      *      LogicalANDExpression && BitwiseORExpression
4529      *
4530      * LogicalORExpression :
4531      *      LogicalANDExpression
4532      *      LogicalORExpression || LogicalANDExpression
4533      *
4534      * See 11.11
4535      *
4536      * ConditionalExpression :
4537      *      LogicalORExpression
4538      *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
4539      *
4540      * See 11.12
4541      *
4542      * AssignmentExpression :
4543      *      ConditionalExpression
4544      *      LeftHandSideExpression AssignmentOperator AssignmentExpression
4545      *
4546      * AssignmentOperator :
4547      *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
4548      *
4549      * See 11.13
4550      *
4551      * Expression :
4552      *      AssignmentExpression
4553      *      Expression , AssignmentExpression
4554      *
4555      * See 11.14
4556      * }
4557      *
4558      * Parse expression.
4559      * @return Expression node.
4560      */
4561     protected Expression expression() {
4562         // This method is protected so that subclass can get details
4563         // at expression start point!
4564 
4565         // Include commas in expression parsing.
4566         return expression(false);
4567     }
4568 
4569     private Expression expression(final boolean noIn) {
4570         Expression assignmentExpression = assignmentExpression(noIn);
4571         while (type == COMMARIGHT) {
4572             final long commaToken = token;
4573             next();
4574 
4575             boolean rhsRestParameter = false;
4576             if (type == ELLIPSIS && isES6()) {
4577                 // (a, b, ...rest) is not a valid expression, unless we're parsing the parameter list of an arrow function (we need to throw the right error).
4578                 // But since the rest parameter is always last, at least we know that the expression has to end here and be followed by RPAREN and ARROW, so peek ahead.
4579                 if (isRestParameterEndOfArrowFunctionParameterList()) {
4580                     next();
4581                     rhsRestParameter = true;
4582                 }
4583             }
4584 
4585             Expression rhs = assignmentExpression(noIn);
4586 
4587             if (rhsRestParameter) {
4588                 rhs = ((IdentNode)rhs).setIsRestParameter();
4589                 // Our only valid move is to end Expression here and continue with ArrowFunction.
4590                 // We've already checked that this is the parameter list of an arrow function (see above).
4591                 // RPAREN is next, so we'll finish the binary expression and drop out of the loop.
4592                 assert type == RPAREN;
4593             }
4594 
4595             assignmentExpression = new BinaryNode(commaToken, assignmentExpression, rhs);
4596         }
4597         return assignmentExpression;
4598     }
4599 
4600     private Expression expression(final int minPrecedence, final boolean noIn) {
4601         return expression(unaryExpression(), minPrecedence, noIn);
4602     }
4603 
4604     private JoinPredecessorExpression joinPredecessorExpression() {
4605         return new JoinPredecessorExpression(expression());
4606     }
4607 
4608     private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
4609         // Get the precedence of the next operator.
4610         int precedence = type.getPrecedence();
4611         Expression lhs = exprLhs;
4612 
4613         // While greater precedence.
4614         while (type.isOperator(noIn) && precedence >= minPrecedence) {
4615             // Capture the operator token.
4616             final long op = token;
4617 
4618             if (type == TERNARY) {
4619                 // Skip operator.
4620                 next();
4621 
4622                 // Pass expression. Middle expression of a conditional expression can be a "in"
4623                 // expression - even in the contexts where "in" is not permitted.
4624                 final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
4625 
4626                 expect(COLON);
4627 
4628                 // Fail expression.
4629                 final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
4630 
4631                 // Build up node.
4632                 lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
4633             } else {
4634                 // Skip operator.
4635                 next();
4636 
4637                  // Get the next primary expression.
4638                 Expression rhs;
4639                 final boolean isAssign = Token.descType(op) == ASSIGN;
4640                 if(isAssign) {
4641                     defaultNames.push(lhs);
4642                 }
4643                 try {
4644                     rhs = unaryExpression();
4645                     // Get precedence of next operator.
4646                     int nextPrecedence = type.getPrecedence();
4647 
4648                     // Subtask greater precedence.
4649                     while (type.isOperator(noIn) &&
4650                            (nextPrecedence > precedence ||
4651                            nextPrecedence == precedence && !type.isLeftAssociative())) {
4652                         rhs = expression(rhs, nextPrecedence, noIn);
4653                         nextPrecedence = type.getPrecedence();
4654                     }
4655                 } finally {
4656                     if(isAssign) {
4657                         defaultNames.pop();
4658                     }
4659                 }
4660                 lhs = verifyAssignment(op, lhs, rhs);
4661             }
4662 
4663             precedence = type.getPrecedence();
4664         }
4665 
4666         return lhs;
4667     }
4668 
4669     /**
4670      * AssignmentExpression.
4671      *
4672      * AssignmentExpression[In, Yield] :
4673      *   ConditionalExpression[?In, ?Yield]
4674      *   [+Yield] YieldExpression[?In]
4675      *   ArrowFunction[?In, ?Yield]
4676      *   LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield]
4677      *   LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield]
4678      *
4679      * @param noIn {@code true} if IN operator should be ignored.
4680      * @return the assignment expression
4681      */
4682     protected Expression assignmentExpression(final boolean noIn) {
4683         // This method is protected so that subclass can get details
4684         // at assignment expression start point!
4685 
4686         if (type == YIELD && inGeneratorFunction() && isES6()) {
4687             return yieldExpression(noIn);
4688         }
4689 
4690         final long startToken = token;
4691         final int startLine = line;
4692         final Expression exprLhs = conditionalExpression(noIn);
4693 
4694         if (type == ARROW && isES6()) {
4695             if (checkNoLineTerminator()) {
4696                 final Expression paramListExpr;
4697                 if (exprLhs instanceof ExpressionList) {
4698                     paramListExpr = (((ExpressionList)exprLhs).getExpressions().isEmpty() ? null : ((ExpressionList)exprLhs).getExpressions().get(0));
4699                 } else {
4700                     paramListExpr = exprLhs;
4701                 }
4702                 return arrowFunction(startToken, startLine, paramListExpr);
4703             }
4704         }
4705         assert !(exprLhs instanceof ExpressionList);
4706 
4707         if (isAssignmentOperator(type)) {
4708             final boolean isAssign = type == ASSIGN;
4709             if (isAssign) {
4710                 defaultNames.push(exprLhs);
4711             }
4712             try {
4713                 final long assignToken = token;
4714                 next();
4715                 final Expression exprRhs = assignmentExpression(noIn);
4716                 return verifyAssignment(assignToken, exprLhs, exprRhs);
4717             } finally {
4718                 if (isAssign) {
4719                     defaultNames.pop();
4720                 }
4721             }
4722         } else {
4723             return exprLhs;
4724         }
4725     }
4726 
4727     /**
4728      * Is type one of {@code = *= /= %= += -= <<= >>= >>>= &= ^= |=}?
4729      */
4730     private static boolean isAssignmentOperator(final TokenType type) {
4731         switch (type) {
4732         case ASSIGN:
4733         case ASSIGN_ADD:
4734         case ASSIGN_BIT_AND:
4735         case ASSIGN_BIT_OR:
4736         case ASSIGN_BIT_XOR:
4737         case ASSIGN_DIV:
4738         case ASSIGN_MOD:
4739         case ASSIGN_MUL:
4740         case ASSIGN_SAR:
4741         case ASSIGN_SHL:
4742         case ASSIGN_SHR:
4743         case ASSIGN_SUB:
4744             return true;
4745         }
4746         return false;
4747     }
4748 
4749     /**
4750      * ConditionalExpression.
4751      */
4752     private Expression conditionalExpression(final boolean noIn) {
4753         return expression(TERNARY.getPrecedence(), noIn);
4754     }
4755 
4756     /**
4757      * ArrowFunction.
4758      *
4759      * @param startToken start token of the ArrowParameters expression
4760      * @param functionLine start line of the arrow function
4761      * @param paramListExpr ArrowParameters expression or {@code null} for {@code ()} (empty list)
4762      */
4763     private Expression arrowFunction(final long startToken, final int functionLine, final Expression paramListExpr) {
4764         // caller needs to check that there's no LineTerminator between parameter list and arrow
4765         assert type != ARROW || checkNoLineTerminator();
4766         expect(ARROW);
4767 
4768         final long functionToken = Token.recast(startToken, ARROW);
4769         final IdentNode name = new IdentNode(functionToken, Token.descPosition(functionToken), NameCodec.encode("=>:") + functionLine);
4770         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.ARROW, functionLine, null);
4771         functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
4772 
4773         lc.push(functionNode);
4774         try {
4775             final ParserContextBlockNode parameterBlock = newBlock();
4776             final List<IdentNode> parameters;
4777             try {
4778                 parameters = convertArrowFunctionParameterList(paramListExpr, functionLine);
4779                 functionNode.setParameters(parameters);
4780 
4781                 if (!functionNode.isSimpleParameterList()) {
4782                     markEvalInArrowParameterList(parameterBlock);
4783                 }
4784             } finally {
4785                 restoreBlock(parameterBlock);
4786             }
4787             Block functionBody = functionBody(functionNode);
4788 
4789             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
4790 
4791             verifyParameterList(parameters, functionNode);
4792 
4793             final FunctionNode function = createFunctionNode(
4794                             functionNode,
4795                             functionToken,
4796                             name,
4797                             parameters,
4798                             FunctionNode.Kind.ARROW,
4799                             functionLine,
4800                             functionBody);
4801             return function;
4802         } finally {
4803             lc.pop(functionNode);
4804         }
4805     }
4806 
4807     private void markEvalInArrowParameterList(final ParserContextBlockNode parameterBlock) {
4808         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
4809         final ParserContextFunctionNode current = iter.next();
4810         final ParserContextFunctionNode parent = iter.next();
4811 
4812         if (parent.getFlag(FunctionNode.HAS_EVAL) != 0) {
4813             // we might have flagged has-eval in the parent function during parsing the parameter list,
4814             // if the parameter list contains eval; must tag arrow function as has-eval.
4815             for (final Statement st : parameterBlock.getStatements()) {
4816                 st.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
4817                     @Override
4818                     public boolean enterCallNode(final CallNode callNode) {
4819                         if (callNode.getFunction() instanceof IdentNode && ((IdentNode) callNode.getFunction()).getName().equals("eval")) {
4820                             current.setFlag(FunctionNode.HAS_EVAL);
4821                         }
4822                         return true;
4823                     }
4824                 });
4825             }
4826             // TODO: function containing the arrow function should not be flagged has-eval
4827         }
4828     }
4829 
4830     private List<IdentNode> convertArrowFunctionParameterList(final Expression paramListExpr, final int functionLine) {
4831         final List<IdentNode> parameters;
4832         if (paramListExpr == null) {
4833             // empty parameter list, i.e. () =>
4834             parameters = Collections.emptyList();
4835         } else if (paramListExpr instanceof IdentNode || paramListExpr.isTokenType(ASSIGN) || isDestructuringLhs(paramListExpr)) {
4836             parameters = Collections.singletonList(verifyArrowParameter(paramListExpr, 0, functionLine));
4837         } else if (paramListExpr instanceof BinaryNode && Token.descType(paramListExpr.getToken()) == COMMARIGHT) {
4838             parameters = new ArrayList<>();
4839             Expression car = paramListExpr;
4840             do {
4841                 final Expression cdr = ((BinaryNode) car).rhs();
4842                 parameters.add(0, verifyArrowParameter(cdr, parameters.size(), functionLine));
4843                 car = ((BinaryNode) car).lhs();
4844             } while (car instanceof BinaryNode && Token.descType(car.getToken()) == COMMARIGHT);
4845             parameters.add(0, verifyArrowParameter(car, parameters.size(), functionLine));
4846         } else {
4847             throw error(AbstractParser.message("expected.arrow.parameter"), paramListExpr.getToken());
4848         }
4849         return parameters;
4850     }
4851 
4852     private IdentNode verifyArrowParameter(final Expression param, final int index, final int paramLine) {
4853         final String contextString = "function parameter";
4854         if (param instanceof IdentNode) {
4855             final IdentNode ident = (IdentNode)param;
4856             verifyStrictIdent(ident, contextString);
4857             final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4858             if (currentFunction != null) {
4859                 currentFunction.addParameterBinding(ident);
4860             }
4861             return ident;
4862         }
4863 
4864         if (param.isTokenType(ASSIGN)) {
4865             final Expression lhs = ((BinaryNode) param).lhs();
4866             final long paramToken = lhs.getToken();
4867             final Expression initializer = ((BinaryNode) param).rhs();
4868             if (lhs instanceof IdentNode) {
4869                 // default parameter
4870                 final IdentNode ident = (IdentNode) lhs;
4871 
4872                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4873                 if (currentFunction != null) {
4874                     if (env._parse_only) {
4875                         currentFunction.addParameterExpression(ident, param);
4876                     } else {
4877                         final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4878                         final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4879                         final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
4880                         lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4881                     }
4882 
4883                     currentFunction.addParameterBinding(ident);
4884                     currentFunction.setSimpleParameterList(false);
4885                 }
4886                 return ident;
4887             } else if (isDestructuringLhs(lhs)) {
4888                 // binding pattern with initializer
4889                 // Introduce synthetic temporary parameter to capture the object to be destructured.
4890                 final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter().setIsDefaultParameter();
4891                 verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
4892 
4893                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4894                 if (currentFunction != null) {
4895                     if (env._parse_only) {
4896                         currentFunction.addParameterExpression(ident, param);
4897                     } else {
4898                         final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4899                         final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4900                         final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value);
4901                         lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4902                     }
4903                 }
4904                 return ident;
4905             }
4906         } else if (isDestructuringLhs(param)) {
4907             // binding pattern
4908             final long paramToken = param.getToken();
4909 
4910             // Introduce synthetic temporary parameter to capture the object to be destructured.
4911             final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter();
4912             verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
4913 
4914             final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4915             if (currentFunction != null) {
4916                 if (env._parse_only) {
4917                     currentFunction.addParameterExpression(ident, param);
4918                 } else {
4919                     final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident);
4920                     lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4921                 }
4922             }
4923             return ident;
4924         }
4925         throw error(AbstractParser.message("invalid.arrow.parameter"), param.getToken());
4926     }
4927 
4928     private boolean checkNoLineTerminator() {
4929         assert type == ARROW;
4930         if (last == RPAREN) {
4931             return true;
4932         } else if (last == IDENT) {
4933             return true;
4934         }
4935         for (int i = k - 1; i >= 0; i--) {
4936             final TokenType t = T(i);
4937             switch (t) {
4938             case RPAREN:
4939             case IDENT:
4940                 return true;
4941             case EOL:
4942                 return false;
4943             case COMMENT:
4944                 continue;
4945             default:
4946                 if (t.getKind() == TokenKind.FUTURESTRICT) {
4947                     return true;
4948                 }
4949                 return false;
4950             }
4951         }
4952         return false;
4953     }
4954 
4955     /**
4956      * Peek ahead to see if what follows after the ellipsis is a rest parameter
4957      * at the end of an arrow function parameter list.
4958      */
4959     private boolean isRestParameterEndOfArrowFunctionParameterList() {
4960         assert type == ELLIPSIS;
4961         // find IDENT, RPAREN, ARROW, in that order, skipping over EOL (where allowed) and COMMENT
4962         int i = 1;
4963         for (;;) {
4964             final TokenType t = T(k + i++);
4965             if (t == IDENT) {
4966                 break;
4967             } else if (t == EOL || t == COMMENT) {
4968                 continue;
4969             } else {
4970                 return false;
4971             }
4972         }
4973         for (;;) {
4974             final TokenType t = T(k + i++);
4975             if (t == RPAREN) {
4976                 break;
4977             } else if (t == EOL || t == COMMENT) {
4978                 continue;
4979             } else {
4980                 return false;
4981             }
4982         }
4983         for (;;) {
4984             final TokenType t = T(k + i++);
4985             if (t == ARROW) {
4986                 break;
4987             } else if (t == COMMENT) {
4988                 continue;
4989             } else {
4990                 return false;
4991             }
4992         }
4993         return true;
4994     }
4995 
4996     /**
4997      * Parse an end of line.
4998      */
4999     private void endOfLine() {
5000         switch (type) {
5001         case SEMICOLON:
5002         case EOL:
5003             next();
5004             break;
5005         case RPAREN:
5006         case RBRACKET:
5007         case RBRACE:
5008         case EOF:
5009             break;
5010         default:
5011             if (last != EOL) {
5012                 expect(SEMICOLON);
5013             }
5014             break;
5015         }
5016     }
5017 
5018     /**
5019      * Parse untagged template literal as string concatenation.
5020      */
5021     private Expression templateLiteral() {
5022         assert type == TEMPLATE || type == TEMPLATE_HEAD;
5023         final boolean noSubstitutionTemplate = type == TEMPLATE;
5024         long lastLiteralToken = token;
5025         LiteralNode<?> literal = getLiteral();
5026         if (noSubstitutionTemplate) {
5027             return literal;
5028         }
5029 
5030         if (env._parse_only) {
5031             final List<Expression> exprs = new ArrayList<>();
5032             exprs.add(literal);
5033             TokenType lastLiteralType;
5034             do {
5035                 final Expression expression = expression();
5036                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5037                     throw error(AbstractParser.message("unterminated.template.expression"), token);
5038                 }
5039                 exprs.add(expression);
5040                 lastLiteralType = type;
5041                 literal = getLiteral();
5042                 exprs.add(literal);
5043             } while (lastLiteralType == TEMPLATE_MIDDLE);
5044             return new TemplateLiteral(exprs);
5045         } else {
5046             Expression concat = literal;
5047             TokenType lastLiteralType;
5048             do {
5049                 final Expression expression = expression();
5050                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5051                     throw error(AbstractParser.message("unterminated.template.expression"), token);
5052                 }
5053                 concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression);
5054                 lastLiteralType = type;
5055                 lastLiteralToken = token;
5056                 literal = getLiteral();
5057                 concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal);
5058             } while (lastLiteralType == TEMPLATE_MIDDLE);
5059             return concat;
5060         }
5061     }
5062 
5063     /**
5064      * Parse tagged template literal as argument list.
5065      * @return argument list for a tag function call (template object, ...substitutions)
5066      */
5067     private List<Expression> templateLiteralArgumentList() {
5068         assert type == TEMPLATE || type == TEMPLATE_HEAD;
5069         final ArrayList<Expression> argumentList = new ArrayList<>();
5070         final ArrayList<Expression> rawStrings = new ArrayList<>();
5071         final ArrayList<Expression> cookedStrings = new ArrayList<>();
5072         argumentList.add(null); // filled at the end
5073 
5074         final long templateToken = token;
5075         final boolean hasSubstitutions = type == TEMPLATE_HEAD;
5076         addTemplateLiteralString(rawStrings, cookedStrings);
5077 
5078         if (hasSubstitutions) {
5079             TokenType lastLiteralType;
5080             do {
5081                 final Expression expression = expression();
5082                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5083                     throw error(AbstractParser.message("unterminated.template.expression"), token);
5084                 }
5085                 argumentList.add(expression);
5086 
5087                 lastLiteralType = type;
5088                 addTemplateLiteralString(rawStrings, cookedStrings);
5089             } while (lastLiteralType == TEMPLATE_MIDDLE);
5090         }
5091 
5092         final LiteralNode<Expression[]> rawStringArray = LiteralNode.newInstance(templateToken, finish, rawStrings);
5093         final LiteralNode<Expression[]> cookedStringArray = LiteralNode.newInstance(templateToken, finish, cookedStrings);
5094         final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray);
5095         argumentList.set(0, templateObject);
5096         return optimizeList(argumentList);
5097     }
5098 
5099     private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) {
5100         final long stringToken = token;
5101         final String rawString = lexer.valueOfRawString(stringToken);
5102         final String cookedString = (String) getValue();
5103         next();
5104         rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString));
5105         cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
5106     }
5107 
5108 
5109     /**
5110      * Parse a module.
5111      *
5112      * Module :
5113      *      ModuleBody?
5114      *
5115      * ModuleBody :
5116      *      ModuleItemList
5117      */
5118     private FunctionNode module(final String moduleName) {
5119         final boolean oldStrictMode = isStrictMode;
5120         try {
5121             isStrictMode = true; // Module code is always strict mode code. (ES6 10.2.1)
5122 
5123             // Make a pseudo-token for the script holding its start and length.
5124             final int functionStart = Math.min(Token.descPosition(Token.withDelimiter(token)), finish);
5125             final long functionToken = Token.toDesc(FUNCTION, functionStart, source.getLength() - functionStart);
5126             final int  functionLine  = line;
5127 
5128             final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), moduleName);
5129             final ParserContextFunctionNode script = createParserContextFunctionNode(
5130                             ident,
5131                             functionToken,
5132                             FunctionNode.Kind.MODULE,
5133                             functionLine,
5134                             Collections.<IdentNode>emptyList());
5135             lc.push(script);
5136 
5137             final ParserContextModuleNode module = new ParserContextModuleNode(moduleName);
5138             lc.push(module);
5139 
5140             final ParserContextBlockNode body = newBlock();
5141 
5142             functionDeclarations = new ArrayList<>();
5143             moduleBody();
5144             addFunctionDeclarations(script);
5145             functionDeclarations = null;
5146 
5147             restoreBlock(body);
5148             body.setFlag(Block.NEEDS_SCOPE);
5149             final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
5150             lc.pop(module);
5151             lc.pop(script);
5152             script.setLastToken(token);
5153 
5154             expect(EOF);
5155 
5156             script.setModule(module.createModule());
5157             return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.MODULE, functionLine, programBody);
5158         } finally {
5159             isStrictMode = oldStrictMode;
5160         }
5161     }
5162 
5163     /**
5164      * Parse module body.
5165      *
5166      * ModuleBody :
5167      *      ModuleItemList
5168      *
5169      * ModuleItemList :
5170      *      ModuleItem
5171      *      ModuleItemList ModuleItem
5172      *
5173      * ModuleItem :
5174      *      ImportDeclaration
5175      *      ExportDeclaration
5176      *      StatementListItem
5177      */
5178     private void moduleBody() {
5179         loop:
5180         while (type != EOF) {
5181             switch (type) {
5182             case EOF:
5183                 break loop;
5184             case IMPORT:
5185                 importDeclaration();
5186                 break;
5187             case EXPORT:
5188                 exportDeclaration();
5189                 break;
5190             default:
5191                 // StatementListItem
5192                 statement(true, 0, false, false);
5193                 break;
5194             }
5195         }
5196     }
5197 
5198 
5199     /**
5200      * Parse import declaration.
5201      *
5202      * ImportDeclaration :
5203      *     import ImportClause FromClause ;
5204      *     import ModuleSpecifier ;
5205      * ImportClause :
5206      *     ImportedDefaultBinding
5207      *     NameSpaceImport
5208      *     NamedImports
5209      *     ImportedDefaultBinding , NameSpaceImport
5210      *     ImportedDefaultBinding , NamedImports
5211      * ImportedDefaultBinding :
5212      *     ImportedBinding
5213      * ModuleSpecifier :
5214      *     StringLiteral
5215      * ImportedBinding :
5216      *     BindingIdentifier
5217      */
5218     private void importDeclaration() {
5219         final int startPosition = start;
5220         expect(IMPORT);
5221         final ParserContextModuleNode module = lc.getCurrentModule();
5222         if (type == STRING || type == ESCSTRING) {
5223             // import ModuleSpecifier ;
5224             final IdentNode moduleSpecifier = createIdentNode(token, finish, (String) getValue());
5225             next();
5226             module.addModuleRequest(moduleSpecifier);
5227         } else {
5228             // import ImportClause FromClause ;
5229             List<Module.ImportEntry> importEntries;
5230             if (type == MUL) {
5231                 importEntries = Collections.singletonList(nameSpaceImport(startPosition));
5232             } else if (type == LBRACE) {
5233                 importEntries = namedImports(startPosition);
5234             } else if (isBindingIdentifier()) {
5235                 // ImportedDefaultBinding
5236                 final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding");
5237                 final Module.ImportEntry defaultImport = Module.ImportEntry.importSpecifier(importedDefaultBinding, startPosition, finish);
5238 
5239                 if (type == COMMARIGHT) {
5240                     next();
5241                     importEntries = new ArrayList<>();
5242                     if (type == MUL) {
5243                         importEntries.add(nameSpaceImport(startPosition));
5244                     } else if (type == LBRACE) {
5245                         importEntries.addAll(namedImports(startPosition));
5246                     } else {
5247                         throw error(AbstractParser.message("expected.named.import"));
5248                     }
5249                 } else {
5250                     importEntries = Collections.singletonList(defaultImport);
5251                 }
5252             } else {
5253                 throw error(AbstractParser.message("expected.import"));
5254             }
5255 
5256             final IdentNode moduleSpecifier = fromClause();
5257             module.addModuleRequest(moduleSpecifier);
5258             for (int i = 0; i < importEntries.size(); i++) {
5259                 module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier, finish));
5260             }
5261         }
5262         expect(SEMICOLON);
5263     }
5264 
5265     /**
5266      * NameSpaceImport :
5267      *     * as ImportedBinding
5268      *
5269      * @param startPosition the start of the import declaration
5270      * @return imported binding identifier
5271      */
5272     private Module.ImportEntry nameSpaceImport(final int startPosition) {
5273         assert type == MUL;
5274         final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
5275         next();
5276         final long asToken = token;
5277         final String as = (String) expectValue(IDENT);
5278         if (!"as".equals(as)) {
5279             throw error(AbstractParser.message("expected.as"), asToken);
5280         }
5281         final IdentNode localNameSpace = bindingIdentifier("ImportedBinding");
5282         return Module.ImportEntry.importSpecifier(starName, localNameSpace, startPosition, finish);
5283     }
5284 
5285     /**
5286      * NamedImports :
5287      *     { }
5288      *     { ImportsList }
5289      *     { ImportsList , }
5290      * ImportsList :
5291      *     ImportSpecifier
5292      *     ImportsList , ImportSpecifier
5293      * ImportSpecifier :
5294      *     ImportedBinding
5295      *     IdentifierName as ImportedBinding
5296      * ImportedBinding :
5297      *     BindingIdentifier
5298      */
5299     private List<Module.ImportEntry> namedImports(final int startPosition) {
5300         assert type == LBRACE;
5301         next();
5302         final List<Module.ImportEntry> importEntries = new ArrayList<>();
5303         while (type != RBRACE) {
5304             final boolean bindingIdentifier = isBindingIdentifier();
5305             final long nameToken = token;
5306             final IdentNode importName = getIdentifierName();
5307             if (type == IDENT && "as".equals(getValue())) {
5308                 next();
5309                 final IdentNode localName = bindingIdentifier("ImportedBinding");
5310                 importEntries.add(Module.ImportEntry.importSpecifier(importName, localName, startPosition, finish));
5311             } else if (!bindingIdentifier) {
5312                 throw error(AbstractParser.message("expected.binding.identifier"), nameToken);
5313             } else {
5314                 importEntries.add(Module.ImportEntry.importSpecifier(importName, startPosition, finish));
5315             }
5316             if (type == COMMARIGHT) {
5317                 next();
5318             } else {
5319                 break;
5320             }
5321         }
5322         expect(RBRACE);
5323         return importEntries;
5324     }
5325 
5326     /**
5327      * FromClause :
5328      *     from ModuleSpecifier
5329      */
5330     private IdentNode fromClause() {
5331         final long fromToken = token;
5332         final String name = (String) expectValue(IDENT);
5333         if (!"from".equals(name)) {
5334             throw error(AbstractParser.message("expected.from"), fromToken);
5335         }
5336         if (type == STRING || type == ESCSTRING) {
5337             final IdentNode moduleSpecifier = createIdentNode(Token.recast(token, IDENT), finish, (String) getValue());
5338             next();
5339             return moduleSpecifier;
5340         } else {
5341             throw error(expectMessage(STRING));
5342         }
5343     }
5344 
5345     /**
5346      * Parse export declaration.
5347      *
5348      * ExportDeclaration :
5349      *     export * FromClause ;
5350      *     export ExportClause FromClause ;
5351      *     export ExportClause ;
5352      *     export VariableStatement
5353      *     export Declaration
5354      *     export default HoistableDeclaration[Default]
5355      *     export default ClassDeclaration[Default]
5356      *     export default [lookahead !in {function, class}] AssignmentExpression[In] ;
5357      */
5358     private void exportDeclaration() {
5359         expect(EXPORT);
5360         final int startPosition = start;
5361         final ParserContextModuleNode module = lc.getCurrentModule();
5362         switch (type) {
5363             case MUL: {
5364                 final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
5365                 next();
5366                 final IdentNode moduleRequest = fromClause();
5367                 expect(SEMICOLON);
5368                 module.addModuleRequest(moduleRequest);
5369                 module.addStarExportEntry(Module.ExportEntry.exportStarFrom(starName, moduleRequest, startPosition, finish));
5370                 break;
5371             }
5372             case LBRACE: {
5373                 final List<Module.ExportEntry> exportEntries = exportClause(startPosition);
5374                 if (type == IDENT && "from".equals(getValue())) {
5375                     final IdentNode moduleRequest = fromClause();
5376                     module.addModuleRequest(moduleRequest);
5377                     for (final Module.ExportEntry exportEntry : exportEntries) {
5378                         module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest, finish));
5379                     }
5380                 } else {
5381                     for (final Module.ExportEntry exportEntry : exportEntries) {
5382                         module.addLocalExportEntry(exportEntry);
5383                     }
5384                 }
5385                 expect(SEMICOLON);
5386                 break;
5387             }
5388             case DEFAULT:
5389                 final IdentNode defaultName = createIdentNode(Token.recast(token, IDENT), finish, Module.DEFAULT_NAME);
5390                 next();
5391                 final Expression assignmentExpression;
5392                 IdentNode ident;
5393                 final int lineNumber = line;
5394                 final long rhsToken = token;
5395                 final boolean declaration;
5396                 switch (type) {
5397                     case FUNCTION:
5398                         assignmentExpression = functionExpression(false, true);
5399                         ident = ((FunctionNode) assignmentExpression).getIdent();
5400                         declaration = true;
5401                         break;
5402                     case CLASS:
5403                         assignmentExpression = classDeclaration(true);
5404                         ident = ((ClassNode) assignmentExpression).getIdent();
5405                         declaration = true;
5406                         break;
5407                     default:
5408                         assignmentExpression = assignmentExpression(false);
5409                         ident = null;
5410                         declaration = false;
5411                         break;
5412                 }
5413                 if (ident != null) {
5414                     module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
5415                 } else {
5416                     ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME);
5417                     lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression));
5418                     if (!declaration) {
5419                         expect(SEMICOLON);
5420                     }
5421                     module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
5422                 }
5423                 break;
5424             case VAR:
5425             case LET:
5426             case CONST:
5427                 final List<Statement> statements = lc.getCurrentBlock().getStatements();
5428                 final int previousEnd = statements.size();
5429                 variableStatement(type);
5430                 for (final Statement statement : statements.subList(previousEnd, statements.size())) {
5431                     if (statement instanceof VarNode) {
5432                         module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName(), startPosition, finish));
5433                     }
5434                 }
5435                 break;
5436             case CLASS: {
5437                 final ClassNode classDeclaration = classDeclaration(false);
5438                 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent(), startPosition, finish));
5439                 break;
5440             }
5441             case FUNCTION: {
5442                 final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true);
5443                 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent(), startPosition, finish));
5444                 break;
5445             }
5446             default:
5447                 throw error(AbstractParser.message("invalid.export"), token);
5448         }
5449     }
5450 
5451     /**
5452      * ExportClause :
5453      *     { }
5454      *     { ExportsList }
5455      *     { ExportsList , }
5456      * ExportsList :
5457      *     ExportSpecifier
5458      *     ExportsList , ExportSpecifier
5459      * ExportSpecifier :
5460      *     IdentifierName
5461      *     IdentifierName as IdentifierName
5462      *
5463      * @return a list of ExportSpecifiers
5464      */
5465     private List<Module.ExportEntry> exportClause(final int startPosition) {
5466         assert type == LBRACE;
5467         next();
5468         final List<Module.ExportEntry> exports = new ArrayList<>();
5469         while (type != RBRACE) {
5470             final IdentNode localName = getIdentifierName();
5471             if (type == IDENT && "as".equals(getValue())) {
5472                 next();
5473                 final IdentNode exportName = getIdentifierName();
5474                 exports.add(Module.ExportEntry.exportSpecifier(exportName, localName, startPosition, finish));
5475             } else {
5476                 exports.add(Module.ExportEntry.exportSpecifier(localName, startPosition, finish));
5477             }
5478             if (type == COMMARIGHT) {
5479                 next();
5480             } else {
5481                 break;
5482             }
5483         }
5484         expect(RBRACE);
5485         return exports;
5486     }
5487 
5488     @Override
5489     public String toString() {
5490         return "'JavaScript Parsing'";
5491     }
5492 
5493     private static void markEval(final ParserContext lc) {
5494         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5495         boolean flaggedCurrentFn = false;
5496         while (iter.hasNext()) {
5497             final ParserContextFunctionNode fn = iter.next();
5498             if (!flaggedCurrentFn) {
5499                 fn.setFlag(FunctionNode.HAS_EVAL);
5500                 flaggedCurrentFn = true;
5501                 if (fn.getKind() == FunctionNode.Kind.ARROW) {
5502                     // possible use of this in an eval that's nested in an arrow function, e.g.:
5503                     // function fun(){ return (() => eval("this"))(); };
5504                     markThis(lc);
5505                     markNewTarget(lc);
5506                 }
5507             } else {
5508                 fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
5509             }
5510             final ParserContextBlockNode body = lc.getFunctionBody(fn);
5511             // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
5512             // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
5513             // this method when the parser skips a nested function.
5514             body.setFlag(Block.NEEDS_SCOPE);
5515             fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
5516         }
5517     }
5518 
5519     private void prependStatement(final Statement statement) {
5520         lc.prependStatementToCurrentNode(statement);
5521     }
5522 
5523     private void appendStatement(final Statement statement) {
5524         lc.appendStatementToCurrentNode(statement);
5525     }
5526 
5527     private static void markSuperCall(final ParserContext lc) {
5528         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5529         while (iter.hasNext()) {
5530             final ParserContextFunctionNode fn = iter.next();
5531             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5532                 assert fn.isSubclassConstructor();
5533                 fn.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
5534                 break;
5535             }
5536         }
5537     }
5538 
5539     private ParserContextFunctionNode getCurrentNonArrowFunction() {
5540         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5541         while (iter.hasNext()) {
5542             final ParserContextFunctionNode fn = iter.next();
5543             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5544                 return fn;
5545             }
5546         }
5547         return null;
5548     }
5549 
5550     private static void markThis(final ParserContext lc) {
5551         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5552         while (iter.hasNext()) {
5553             final ParserContextFunctionNode fn = iter.next();
5554             fn.setFlag(FunctionNode.USES_THIS);
5555             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5556                 break;
5557             }
5558         }
5559     }
5560 
5561     private static void markNewTarget(final ParserContext lc) {
5562         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5563         while (iter.hasNext()) {
5564             final ParserContextFunctionNode fn = iter.next();
5565             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5566                 if (!fn.isProgram()) {
5567                     fn.setFlag(FunctionNode.ES6_USES_NEW_TARGET);
5568                 }
5569                 break;
5570             }
5571         }
5572     }
5573 
5574     private boolean inGeneratorFunction() {
5575         return lc.getCurrentFunction().getKind() == FunctionNode.Kind.GENERATOR;
5576     }
5577 }