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                 // FIXME: ES6 catch parameter can be a BindingIdentifier or a BindingPattern
2623                 // We need to generalize this here!
2624                 // http://www.ecma-international.org/ecma-262/6.0/
2625                 final IdentNode exception = getIdent();
2626 
2627                 // ECMA 12.4.1 strict mode restrictions
2628                 verifyStrictIdent(exception, "catch argument");
2629 
2630                 // Nashorn extension: catch clause can have optional
2631                 // condition. So, a single try can have more than one
2632                 // catch clause each with it's own condition.
2633                 final Expression ifExpression;
2634                 if (!env._no_syntax_extensions && type == IF) {
2635                     next();
2636                     // Get the exception condition.
2637                     ifExpression = expression();
2638                 } else {
2639                     ifExpression = null;
2640                 }
2641 
2642                 expect(RPAREN);
2643 
2644                 final ParserContextBlockNode catchBlock = newBlock();
2645                 try {
2646                     // Get CATCH body.
2647                     final Block catchBody = getBlock(true);
2648                     final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
2649                     appendStatement(catchNode);
2650                 } finally {
2651                     restoreBlock(catchBlock);
2652                     catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements()));
2653                 }
2654 
2655                 // If unconditional catch then should to be the end.
2656                 if (ifExpression == null) {
2657                     break;
2658                 }
2659             }
2660 
2661             // Prepare to capture finally statement.
2662             Block finallyStatements = null;
2663 
2664             if (type == FINALLY) {
2665                 next();
2666                 finallyStatements = getBlock(true);
2667             }
2668 
2669             // Need at least one catch or a finally.
2670             if (catchBlocks.isEmpty() && finallyStatements == null) {
2671                 throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
2672             }
2673 
2674             final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
2675             // Add try.
2676             assert lc.peek() == outer;
2677             appendStatement(tryNode);
2678         } finally {
2679             restoreBlock(outer);
2680         }
2681 
2682         appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements())));
2683     }
2684 
2685     /**
2686      * DebuggerStatement :
2687      *      debugger ;
2688      *
2689      * See 12.15
2690      *
2691      * Parse debugger statement.
2692      */
2693     private void  debuggerStatement() {
2694         // Capture DEBUGGER token.
2695         final int  debuggerLine  = line;
2696         final long debuggerToken = token;
2697         // DEBUGGER tested in caller.
2698         next();
2699         endOfLine();
2700         appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish));
2701     }
2702 
2703     /**
2704      * PrimaryExpression :
2705      *      this
2706      *      IdentifierReference
2707      *      Literal
2708      *      ArrayLiteral
2709      *      ObjectLiteral
2710      *      RegularExpressionLiteral
2711      *      TemplateLiteral
2712      *      CoverParenthesizedExpressionAndArrowParameterList
2713      *
2714      * CoverParenthesizedExpressionAndArrowParameterList :
2715      *      ( Expression )
2716      *      ( )
2717      *      ( ... BindingIdentifier )
2718      *      ( Expression , ... BindingIdentifier )
2719      *
2720      * Parse primary expression.
2721      * @return Expression node.
2722      */
2723     @SuppressWarnings("fallthrough")
2724     private Expression primaryExpression() {
2725         // Capture first token.
2726         final int  primaryLine  = line;
2727         final long primaryToken = token;
2728 
2729         switch (type) {
2730         case THIS:
2731             final String name = type.getName();
2732             next();
2733             markThis(lc);
2734             return new IdentNode(primaryToken, finish, name);
2735         case IDENT:
2736             final IdentNode ident = getIdent();
2737             if (ident == null) {
2738                 break;
2739             }
2740             detectSpecialProperty(ident);
2741             return ident;
2742         case OCTAL_LEGACY:
2743             if (isStrictMode) {
2744                throw error(AbstractParser.message("strict.no.octal"), token);
2745             }
2746         case STRING:
2747         case ESCSTRING:
2748         case DECIMAL:
2749         case HEXADECIMAL:
2750         case OCTAL:
2751         case BINARY_NUMBER:
2752         case FLOATING:
2753         case REGEX:
2754         case XML:
2755             return getLiteral();
2756         case EXECSTRING:
2757             return execString(primaryLine, primaryToken);
2758         case FALSE:
2759             next();
2760             return LiteralNode.newInstance(primaryToken, finish, false);
2761         case TRUE:
2762             next();
2763             return LiteralNode.newInstance(primaryToken, finish, true);
2764         case NULL:
2765             next();
2766             return LiteralNode.newInstance(primaryToken, finish);
2767         case LBRACKET:
2768             return arrayLiteral();
2769         case LBRACE:
2770             return objectLiteral();
2771         case LPAREN:
2772             next();
2773 
2774             if (isES6()) {
2775                 if (type == RPAREN) {
2776                     // ()
2777                     nextOrEOL();
2778                     expectDontAdvance(ARROW);
2779                     return new ExpressionList(primaryToken, finish, Collections.emptyList());
2780                 } else if (type == ELLIPSIS) {
2781                     // (...rest)
2782                     final IdentNode restParam = formalParameterList(false).get(0);
2783                     expectDontAdvance(RPAREN);
2784                     nextOrEOL();
2785                     expectDontAdvance(ARROW);
2786                     return new ExpressionList(primaryToken, finish, Collections.singletonList(restParam));
2787                 }
2788             }
2789 
2790             final Expression expression = expression();
2791 
2792             expect(RPAREN);
2793 
2794             return expression;
2795         case TEMPLATE:
2796         case TEMPLATE_HEAD:
2797             return templateLiteral();
2798 
2799         default:
2800             // In this context some operator tokens mark the start of a literal.
2801             if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
2802                 next();
2803                 return getLiteral();
2804             }
2805             if (isNonStrictModeIdent()) {
2806                 return getIdent();
2807             }
2808             break;
2809         }
2810 
2811         return null;
2812     }
2813 
2814     /**
2815      * Convert execString to a call to $EXEC.
2816      *
2817      * @param primaryToken Original string token.
2818      * @return callNode to $EXEC.
2819      */
2820     CallNode execString(final int primaryLine, final long primaryToken) {
2821         // Synthesize an ident to call $EXEC.
2822         final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
2823         // Skip over EXECSTRING.
2824         next();
2825         // Set up argument list for call.
2826         // Skip beginning of edit string expression.
2827         expect(LBRACE);
2828         // Add the following expression to arguments.
2829         final List<Expression> arguments = Collections.singletonList(expression());
2830         // Skip ending of edit string expression.
2831         expect(RBRACE);
2832 
2833         return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
2834     }
2835 
2836     /**
2837      * ArrayLiteral :
2838      *      [ Elision? ]
2839      *      [ ElementList ]
2840      *      [ ElementList , Elision? ]
2841      *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
2842      *
2843      * ElementList : Elision? AssignmentExpression
2844      *      ElementList , Elision? AssignmentExpression
2845      *
2846      * Elision :
2847      *      ,
2848      *      Elision ,
2849      *
2850      * See 12.1.4
2851      * JavaScript 1.8
2852      *
2853      * Parse array literal.
2854      * @return Expression node.
2855      */
2856     @SuppressWarnings("fallthrough")
2857     private LiteralNode<Expression[]> arrayLiteral() {
2858         // Capture LBRACKET token.
2859         final long arrayToken = token;
2860         // LBRACKET tested in caller.
2861         next();
2862 
2863         // Prepare to accumulate elements.
2864         final List<Expression> elements = new ArrayList<>();
2865         // Track elisions.
2866         boolean elision = true;
2867         boolean hasSpread = false;
2868         loop:
2869         while (true) {
2870             long spreadToken = 0;
2871             switch (type) {
2872             case RBRACKET:
2873                 next();
2874 
2875                 break loop;
2876 
2877             case COMMARIGHT:
2878                 next();
2879 
2880                 // If no prior expression
2881                 if (elision) {
2882                     elements.add(null);
2883                 }
2884 
2885                 elision = true;
2886 
2887                 break;
2888 
2889             case ELLIPSIS:
2890                 if (isES6()) {
2891                     hasSpread = true;
2892                     spreadToken = token;
2893                     next();
2894                 }
2895                 // fall through
2896 
2897             default:
2898                 if (!elision) {
2899                     throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2900                 }
2901 
2902                 // Add expression element.
2903                 Expression expression = assignmentExpression(false);
2904                 if (expression != null) {
2905                     if (spreadToken != 0) {
2906                         expression = new UnaryNode(Token.recast(spreadToken, SPREAD_ARRAY), expression);
2907                     }
2908                     elements.add(expression);
2909                 } else {
2910                     expect(RBRACKET);
2911                 }
2912 
2913                 elision = false;
2914                 break;
2915             }
2916         }
2917 
2918         return LiteralNode.newInstance(arrayToken, finish, elements, hasSpread, elision);
2919     }
2920 
2921     /**
2922      * ObjectLiteral :
2923      *      { }
2924      *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2925      *
2926      * PropertyNameAndValueList :
2927      *      PropertyAssignment
2928      *      PropertyNameAndValueList , PropertyAssignment
2929      *
2930      * See 11.1.5
2931      *
2932      * Parse an object literal.
2933      * @return Expression node.
2934      */
2935     private ObjectNode objectLiteral() {
2936         // Capture LBRACE token.
2937         final long objectToken = token;
2938         // LBRACE tested in caller.
2939         next();
2940 
2941         // Object context.
2942         // Prepare to accumulate elements.
2943         final List<PropertyNode> elements = new ArrayList<>();
2944         final Map<String, Integer> map = new HashMap<>();
2945 
2946         // Create a block for the object literal.
2947         boolean commaSeen = true;
2948         loop:
2949         while (true) {
2950             switch (type) {
2951                 case RBRACE:
2952                     next();
2953                     break loop;
2954 
2955                 case COMMARIGHT:
2956                     if (commaSeen) {
2957                         throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2958                     }
2959                     next();
2960                     commaSeen = true;
2961                     break;
2962 
2963                 default:
2964                     if (!commaSeen) {
2965                         throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2966                     }
2967 
2968                     commaSeen = false;
2969                     // Get and add the next property.
2970                     final PropertyNode property = propertyAssignment();
2971 
2972                     if (property.isComputed()) {
2973                         elements.add(property);
2974                         break;
2975                     }
2976 
2977                     final String key = property.getKeyName();
2978                     final Integer existing = map.get(key);
2979 
2980                     if (existing == null) {
2981                         map.put(key, elements.size());
2982                         elements.add(property);
2983                         break;
2984                     }
2985 
2986                     final PropertyNode existingProperty = elements.get(existing);
2987 
2988                     // ECMA section 11.1.5 Object Initialiser
2989                     // point # 4 on property assignment production
2990                     final Expression   value  = property.getValue();
2991                     final FunctionNode getter = property.getGetter();
2992                     final FunctionNode setter = property.getSetter();
2993 
2994                     final Expression   prevValue  = existingProperty.getValue();
2995                     final FunctionNode prevGetter = existingProperty.getGetter();
2996                     final FunctionNode prevSetter = existingProperty.getSetter();
2997 
2998                     if (!isES6()) {
2999                         checkPropertyRedefinition(property, value, getter, setter, prevValue, prevGetter, prevSetter);
3000                     } else {
3001                         if (property.getKey() instanceof IdentNode && ((IdentNode)property.getKey()).isProtoPropertyName() &&
3002                                         existingProperty.getKey() instanceof IdentNode && ((IdentNode)existingProperty.getKey()).isProtoPropertyName()) {
3003                             throw error(AbstractParser.message("multiple.proto.key"), property.getToken());
3004                         }
3005                     }
3006 
3007                     if (value != null || prevValue != null) {
3008                         map.put(key, elements.size());
3009                         elements.add(property);
3010                     } else if (getter != null) {
3011                         assert prevGetter != null || prevSetter != null;
3012                         elements.set(existing, existingProperty.setGetter(getter));
3013                     } else if (setter != null) {
3014                         assert prevGetter != null || prevSetter != null;
3015                         elements.set(existing, existingProperty.setSetter(setter));
3016                     }
3017                     break;
3018             }
3019         }
3020 
3021         return new ObjectNode(objectToken, finish, elements);
3022     }
3023 
3024     private void checkPropertyRedefinition(final PropertyNode property, final Expression value, final FunctionNode getter, final FunctionNode setter, final Expression prevValue, final FunctionNode prevGetter, final FunctionNode prevSetter) {
3025         // ECMA 11.1.5 strict mode restrictions
3026         if (isStrictMode && value != null && prevValue != null) {
3027             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3028         }
3029 
3030         final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
3031         final boolean isAccessor     = getter != null     || setter != null;
3032 
3033         // data property redefined as accessor property
3034         if (prevValue != null && isAccessor) {
3035             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3036         }
3037 
3038         // accessor property redefined as data
3039         if (isPrevAccessor && value != null) {
3040             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3041         }
3042 
3043         if (isAccessor && isPrevAccessor) {
3044             if (getter != null && prevGetter != null ||
3045                     setter != null && prevSetter != null) {
3046                 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3047             }
3048         }
3049     }
3050 
3051     /**
3052      * LiteralPropertyName :
3053      *      IdentifierName
3054      *      StringLiteral
3055      *      NumericLiteral
3056      *
3057      * @return PropertyName node
3058      */
3059     @SuppressWarnings("fallthrough")
3060     private PropertyKey literalPropertyName() {
3061         switch (type) {
3062         case IDENT:
3063             return getIdent().setIsPropertyName();
3064         case OCTAL_LEGACY:
3065             if (isStrictMode) {
3066                 throw error(AbstractParser.message("strict.no.octal"), token);
3067             }
3068         case STRING:
3069         case ESCSTRING:
3070         case DECIMAL:
3071         case HEXADECIMAL:
3072         case OCTAL:
3073         case BINARY_NUMBER:
3074         case FLOATING:
3075             return getLiteral();
3076         default:
3077             return getIdentifierName().setIsPropertyName();
3078         }
3079     }
3080 
3081     /**
3082      * ComputedPropertyName :
3083      *      AssignmentExpression
3084      *
3085      * @return PropertyName node
3086      */
3087     private Expression computedPropertyName() {
3088         expect(LBRACKET);
3089         final Expression expression = assignmentExpression(false);
3090         expect(RBRACKET);
3091         return expression;
3092     }
3093 
3094     /**
3095      * PropertyName :
3096      *      LiteralPropertyName
3097      *      ComputedPropertyName
3098      *
3099      * @return PropertyName node
3100      */
3101     private Expression propertyName() {
3102         if (type == LBRACKET && isES6()) {
3103             return computedPropertyName();
3104         } else {
3105             return (Expression)literalPropertyName();
3106         }
3107     }
3108 
3109     /**
3110      * PropertyAssignment :
3111      *      PropertyName : AssignmentExpression
3112      *      get PropertyName ( ) { FunctionBody }
3113      *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
3114      *
3115      * PropertySetParameterList :
3116      *      Identifier
3117      *
3118      * PropertyName :
3119      *      IdentifierName
3120      *      StringLiteral
3121      *      NumericLiteral
3122      *
3123      * See 11.1.5
3124      *
3125      * Parse an object literal property.
3126      * @return Property or reference node.
3127      */
3128     private PropertyNode propertyAssignment() {
3129         // Capture firstToken.
3130         final long propertyToken = token;
3131         final int  functionLine  = line;
3132 
3133         final Expression propertyName;
3134         final boolean isIdentifier;
3135 
3136         boolean generator = false;
3137         if (type == MUL && isES6()) {
3138             generator = true;
3139             next();
3140         }
3141 
3142         final boolean computed = type == LBRACKET;
3143         if (type == IDENT) {
3144             // Get IDENT.
3145             final String ident = (String)expectValue(IDENT);
3146 
3147             if (type != COLON && (type != LPAREN || !isES6())) {
3148                 final long getSetToken = propertyToken;
3149 
3150                 switch (ident) {
3151                 case GET_NAME:
3152                     final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
3153                     return new PropertyNode(propertyToken, finish, getter.key, null, getter.functionNode, null, false, getter.computed);
3154 
3155                 case SET_NAME:
3156                     final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
3157                     return new PropertyNode(propertyToken, finish, setter.key, null, null, setter.functionNode, false, setter.computed);
3158                 default:
3159                     break;
3160                 }
3161             }
3162 
3163             isIdentifier = true;
3164             IdentNode identNode = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
3165             if (type == COLON && ident.equals("__proto__")) {
3166                 identNode = identNode.setIsProtoPropertyName();
3167             }
3168             propertyName = identNode;
3169         } else {
3170             isIdentifier = isNonStrictModeIdent();
3171             propertyName = propertyName();
3172         }
3173 
3174         Expression propertyValue;
3175 
3176         if (generator) {
3177             expectDontAdvance(LPAREN);
3178         }
3179 
3180         if (type == LPAREN && isES6()) {
3181             propertyValue = propertyMethodFunction(propertyName, propertyToken, functionLine, generator, FunctionNode.ES6_IS_METHOD, computed).functionNode;
3182         } else if (isIdentifier && (type == COMMARIGHT || type == RBRACE || type == ASSIGN) && isES6()) {
3183             propertyValue = createIdentNode(propertyToken, finish, ((IdentNode) propertyName).getPropertyName());
3184             if (type == ASSIGN && isES6()) {
3185                 // TODO if not destructuring, this is a SyntaxError
3186                 final long assignToken = token;
3187                 next();
3188                 final Expression rhs = assignmentExpression(false);
3189                 propertyValue = verifyAssignment(assignToken, propertyValue, rhs);
3190             }
3191         } else {
3192             expect(COLON);
3193 
3194             defaultNames.push(propertyName);
3195             try {
3196                 propertyValue = assignmentExpression(false);
3197             } finally {
3198                 defaultNames.pop();
3199             }
3200         }
3201 
3202         return new PropertyNode(propertyToken, finish, propertyName, propertyValue, null, null, false, computed);
3203     }
3204 
3205     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
3206         return propertyGetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
3207     }
3208 
3209     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine, final int flags) {
3210         final boolean computed = type == LBRACKET;
3211         final Expression propertyName = propertyName();
3212         final String getterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
3213         final IdentNode getNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("get " + getterName));
3214         expect(LPAREN);
3215         expect(RPAREN);
3216 
3217         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
3218         functionNode.setFlag(flags);
3219         if (computed) {
3220             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3221         }
3222         lc.push(functionNode);
3223 
3224         Block functionBody;
3225 
3226 
3227         try {
3228             functionBody = functionBody(functionNode);
3229         } finally {
3230             lc.pop(functionNode);
3231         }
3232 
3233         final FunctionNode  function = createFunctionNode(
3234                 functionNode,
3235                 getSetToken,
3236                 getNameNode,
3237                 Collections.<IdentNode>emptyList(),
3238                 FunctionNode.Kind.GETTER,
3239                 functionLine,
3240                 functionBody);
3241 
3242         return new PropertyFunction(propertyName, function, computed);
3243     }
3244 
3245     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
3246         return propertySetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
3247     }
3248 
3249     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine, final int flags) {
3250         final boolean computed = type == LBRACKET;
3251         final Expression propertyName = propertyName();
3252         final String setterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
3253         final IdentNode setNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("set " + setterName));
3254         expect(LPAREN);
3255         // be sloppy and allow missing setter parameter even though
3256         // spec does not permit it!
3257         final IdentNode argIdent;
3258         if (isBindingIdentifier()) {
3259             argIdent = getIdent();
3260             verifyIdent(argIdent, "setter argument");
3261         } else {
3262             argIdent = null;
3263         }
3264         expect(RPAREN);
3265         final List<IdentNode> parameters = new ArrayList<>();
3266         if (argIdent != null) {
3267             parameters.add(argIdent);
3268         }
3269 
3270 
3271         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
3272         functionNode.setFlag(flags);
3273         if (computed) {
3274             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3275         }
3276         lc.push(functionNode);
3277 
3278         Block functionBody;
3279         try {
3280             functionBody = functionBody(functionNode);
3281         } finally {
3282             lc.pop(functionNode);
3283         }
3284 
3285 
3286         final FunctionNode  function = createFunctionNode(
3287                 functionNode,
3288                 getSetToken,
3289                 setNameNode,
3290                 parameters,
3291                 FunctionNode.Kind.SETTER,
3292                 functionLine,
3293                 functionBody);
3294 
3295         return new PropertyFunction(propertyName, function, computed);
3296     }
3297 
3298     private PropertyFunction propertyMethodFunction(final Expression key, final long methodToken, final int methodLine, final boolean generator, final int flags, final boolean computed) {
3299         final String methodName = key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : getDefaultValidFunctionName(methodLine, false);
3300         final IdentNode methodNameNode = createIdentNode(((Node)key).getToken(), finish, methodName);
3301 
3302         final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
3303         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(methodNameNode, methodToken, functionKind, methodLine, null);
3304         functionNode.setFlag(flags);
3305         if (computed) {
3306             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3307         }
3308         lc.push(functionNode);
3309 
3310         try {
3311             final ParserContextBlockNode parameterBlock = newBlock();
3312             final List<IdentNode> parameters;
3313             try {
3314                 expect(LPAREN);
3315                 parameters = formalParameterList(generator);
3316                 functionNode.setParameters(parameters);
3317                 expect(RPAREN);
3318             } finally {
3319                 restoreBlock(parameterBlock);
3320             }
3321 
3322             Block functionBody = functionBody(functionNode);
3323 
3324             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
3325 
3326             final FunctionNode  function = createFunctionNode(
3327                             functionNode,
3328                             methodToken,
3329                             methodNameNode,
3330                             parameters,
3331                             functionKind,
3332                             methodLine,
3333                             functionBody);
3334             return new PropertyFunction(key, function, computed);
3335         } finally {
3336             lc.pop(functionNode);
3337         }
3338     }
3339 
3340     private static class PropertyFunction {
3341         final Expression key;
3342         final FunctionNode functionNode;
3343         final boolean computed;
3344 
3345         PropertyFunction(final Expression key, final FunctionNode function, final boolean computed) {
3346             this.key = key;
3347             this.functionNode = function;
3348             this.computed = computed;
3349         }
3350     }
3351 
3352     /**
3353      * LeftHandSideExpression :
3354      *      NewExpression
3355      *      CallExpression
3356      *
3357      * CallExpression :
3358      *      MemberExpression Arguments
3359      *      SuperCall
3360      *      CallExpression Arguments
3361      *      CallExpression [ Expression ]
3362      *      CallExpression . IdentifierName
3363      *
3364      * SuperCall :
3365      *      super Arguments
3366      *
3367      * See 11.2
3368      *
3369      * Parse left hand side expression.
3370      * @return Expression node.
3371      */
3372     private Expression leftHandSideExpression() {
3373         int  callLine  = line;
3374         long callToken = token;
3375 
3376         Expression lhs = memberExpression();
3377 
3378         if (type == LPAREN) {
3379             final List<Expression> arguments = optimizeList(argumentList());
3380 
3381             // Catch special functions.
3382             if (lhs instanceof IdentNode) {
3383                 detectSpecialFunction((IdentNode)lhs);
3384             }
3385 
3386             lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3387         }
3388 
3389         loop:
3390         while (true) {
3391             // Capture token.
3392             callLine  = line;
3393             callToken = token;
3394 
3395             switch (type) {
3396             case LPAREN: {
3397                 // Get NEW or FUNCTION arguments.
3398                 final List<Expression> arguments = optimizeList(argumentList());
3399 
3400                 // Create call node.
3401                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3402 
3403                 break;
3404             }
3405             case LBRACKET: {
3406                 next();
3407 
3408                 // Get array index.
3409                 final Expression rhs = expression();
3410 
3411                 expect(RBRACKET);
3412 
3413                 // Create indexing node.
3414                 lhs = new IndexNode(callToken, finish, lhs, rhs);
3415 
3416                 break;
3417             }
3418             case PERIOD: {
3419                 next();
3420 
3421                 final IdentNode property = getIdentifierName();
3422 
3423                 // Create property access node.
3424                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
3425 
3426                 break;
3427             }
3428             case TEMPLATE:
3429             case TEMPLATE_HEAD: {
3430                 // tagged template literal
3431                 final List<Expression> arguments = templateLiteralArgumentList();
3432 
3433                 // Create call node.
3434                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3435 
3436                 break;
3437             }
3438             default:
3439                 break loop;
3440             }
3441         }
3442 
3443         return lhs;
3444     }
3445 
3446     /**
3447      * NewExpression :
3448      *      MemberExpression
3449      *      new NewExpression
3450      *
3451      * See 11.2
3452      *
3453      * Parse new expression.
3454      * @return Expression node.
3455      */
3456     private Expression newExpression() {
3457         final long newToken = token;
3458         // NEW is tested in caller.
3459         next();
3460 
3461         if (type == PERIOD && isES6()) {
3462             next();
3463             if (type == IDENT && "target".equals(getValue())) {
3464                 if (lc.getCurrentFunction().isProgram()) {
3465                     throw error(AbstractParser.message("new.target.in.function"), token);
3466                 }
3467                 next();
3468                 markNewTarget(lc);
3469                 return new IdentNode(newToken, finish, "new.target");
3470             } else {
3471                 throw error(AbstractParser.message("expected.target"), token);
3472             }
3473         }
3474 
3475         // Get function base.
3476         final int  callLine    = line;
3477         final Expression constructor = memberExpression();
3478         if (constructor == null) {
3479             return null;
3480         }
3481         // Get arguments.
3482         ArrayList<Expression> arguments;
3483 
3484         // Allow for missing arguments.
3485         if (type == LPAREN) {
3486             arguments = argumentList();
3487         } else {
3488             arguments = new ArrayList<>();
3489         }
3490 
3491         // Nashorn extension: This is to support the following interface implementation
3492         // syntax:
3493         //
3494         //     var r = new java.lang.Runnable() {
3495         //         run: function() { println("run"); }
3496         //     };
3497         //
3498         // The object literal following the "new Constructor()" expression
3499         // is passed as an additional (last) argument to the constructor.
3500         if (!env._no_syntax_extensions && type == LBRACE) {
3501             arguments.add(objectLiteral());
3502         }
3503 
3504         final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
3505 
3506         return new UnaryNode(newToken, callNode);
3507     }
3508 
3509     /**
3510      * MemberExpression :
3511      *      PrimaryExpression
3512      *        FunctionExpression
3513      *        ClassExpression
3514      *        GeneratorExpression
3515      *      MemberExpression [ Expression ]
3516      *      MemberExpression . IdentifierName
3517      *      MemberExpression TemplateLiteral
3518      *      SuperProperty
3519      *      MetaProperty
3520      *      new MemberExpression Arguments
3521      *
3522      * SuperProperty :
3523      *      super [ Expression ]
3524      *      super . IdentifierName
3525      *
3526      * MetaProperty :
3527      *      NewTarget
3528      *
3529      * Parse member expression.
3530      * @return Expression node.
3531      */
3532     @SuppressWarnings("fallthrough")
3533     private Expression memberExpression() {
3534         // Prepare to build operation.
3535         Expression lhs;
3536         boolean isSuper = false;
3537 
3538         switch (type) {
3539         case NEW:
3540             // Get new expression.
3541             lhs = newExpression();
3542             break;
3543 
3544         case FUNCTION:
3545             // Get function expression.
3546             lhs = functionExpression(false, false);
3547             break;
3548 
3549         case CLASS:
3550             if (isES6()) {
3551                 lhs = classExpression(false);
3552                 break;
3553             } else {
3554                 // fall through
3555             }
3556 
3557         case SUPER:
3558             if (isES6()) {
3559                 final ParserContextFunctionNode currentFunction = getCurrentNonArrowFunction();
3560                 if (currentFunction.isMethod()) {
3561                     final long identToken = Token.recast(token, IDENT);
3562                     next();
3563                     lhs = createIdentNode(identToken, finish, SUPER.getName());
3564 
3565                     switch (type) {
3566                         case LBRACKET:
3567                         case PERIOD:
3568                             getCurrentNonArrowFunction().setFlag(FunctionNode.ES6_USES_SUPER);
3569                             isSuper = true;
3570                             break;
3571                         case LPAREN:
3572                             if (currentFunction.isSubclassConstructor()) {
3573                                 lhs = ((IdentNode)lhs).setIsDirectSuper();
3574                                 break;
3575                             } else {
3576                                 // fall through to throw error
3577                             }
3578                         default:
3579                             throw error(AbstractParser.message("invalid.super"), identToken);
3580                     }
3581                     break;
3582                 } else {
3583                     // fall through
3584                 }
3585             } else {
3586                 // fall through
3587             }
3588 
3589         default:
3590             // Get primary expression.
3591             lhs = primaryExpression();
3592             break;
3593         }
3594 
3595         loop:
3596         while (true) {
3597             // Capture token.
3598             final long callToken = token;
3599 
3600             switch (type) {
3601             case LBRACKET: {
3602                 next();
3603 
3604                 // Get array index.
3605                 final Expression index = expression();
3606 
3607                 expect(RBRACKET);
3608 
3609                 // Create indexing node.
3610                 lhs = new IndexNode(callToken, finish, lhs, index);
3611 
3612                 if (isSuper) {
3613                     isSuper = false;
3614                     lhs = ((BaseNode) lhs).setIsSuper();
3615                 }
3616 
3617                 break;
3618             }
3619             case PERIOD: {
3620                 if (lhs == null) {
3621                     throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3622                 }
3623 
3624                 next();
3625 
3626                 final IdentNode property = getIdentifierName();
3627 
3628                 // Create property access node.
3629                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
3630 
3631                 if (isSuper) {
3632                     isSuper = false;
3633                     lhs = ((BaseNode) lhs).setIsSuper();
3634                 }
3635 
3636                 break;
3637             }
3638             case TEMPLATE:
3639             case TEMPLATE_HEAD: {
3640                 // tagged template literal
3641                 final int callLine = line;
3642                 final List<Expression> arguments = templateLiteralArgumentList();
3643 
3644                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3645 
3646                 break;
3647             }
3648             default:
3649                 break loop;
3650             }
3651         }
3652 
3653         return lhs;
3654     }
3655 
3656     /**
3657      * Arguments :
3658      *      ( )
3659      *      ( ArgumentList )
3660      *
3661      * ArgumentList :
3662      *      AssignmentExpression
3663      *      ... AssignmentExpression
3664      *      ArgumentList , AssignmentExpression
3665      *      ArgumentList , ... AssignmentExpression
3666      *
3667      * See 11.2
3668      *
3669      * Parse function call arguments.
3670      * @return Argument list.
3671      */
3672     private ArrayList<Expression> argumentList() {
3673         // Prepare to accumulate list of arguments.
3674         final ArrayList<Expression> nodeList = new ArrayList<>();
3675         // LPAREN tested in caller.
3676         next();
3677 
3678         // Track commas.
3679         boolean first = true;
3680 
3681         while (type != RPAREN) {
3682             // Comma prior to every argument except the first.
3683             if (!first) {
3684                 expect(COMMARIGHT);
3685             } else {
3686                 first = false;
3687             }
3688 
3689             long spreadToken = 0;
3690             if (type == ELLIPSIS && isES6()) {
3691                 spreadToken = token;
3692                 next();
3693             }
3694 
3695             // Get argument expression.
3696             Expression expression = assignmentExpression(false);
3697             if (spreadToken != 0) {
3698                 expression = new UnaryNode(Token.recast(spreadToken, TokenType.SPREAD_ARGUMENT), expression);
3699             }
3700             nodeList.add(expression);
3701         }
3702 
3703         expect(RPAREN);
3704         return nodeList;
3705     }
3706 
3707     private static <T> List<T> optimizeList(final ArrayList<T> list) {
3708         switch(list.size()) {
3709             case 0: {
3710                 return Collections.emptyList();
3711             }
3712             case 1: {
3713                 return Collections.singletonList(list.get(0));
3714             }
3715             default: {
3716                 list.trimToSize();
3717                 return list;
3718             }
3719         }
3720     }
3721 
3722     /**
3723      * FunctionDeclaration :
3724      *      function Identifier ( FormalParameterList? ) { FunctionBody }
3725      *
3726      * FunctionExpression :
3727      *      function Identifier? ( FormalParameterList? ) { FunctionBody }
3728      *
3729      * See 13
3730      *
3731      * Parse function declaration.
3732      * @param isStatement True if for is a statement.
3733      *
3734      * @return Expression node.
3735      */
3736     private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
3737         final long functionToken = token;
3738         final int  functionLine  = line;
3739         // FUNCTION is tested in caller.
3740         assert type == FUNCTION;
3741         next();
3742 
3743         boolean generator = false;
3744         if (type == MUL && isES6()) {
3745             generator = true;
3746             next();
3747         }
3748 
3749         IdentNode name = null;
3750 
3751         if (isBindingIdentifier()) {
3752             if (type == YIELD && ((!isStatement && generator) || (isStatement && inGeneratorFunction()))) {
3753                 // 12.1.1 Early SyntaxError if:
3754                 // GeneratorExpression with BindingIdentifier yield
3755                 // HoistableDeclaration with BindingIdentifier yield in generator function body
3756                 expect(IDENT);
3757             }
3758             name = getIdent();
3759             verifyStrictIdent(name, "function name");
3760         } else if (isStatement) {
3761             // Nashorn extension: anonymous function statements.
3762             // Do not allow anonymous function statement if extensions
3763             // are now allowed. But if we are reparsing then anon function
3764             // statement is possible - because it was used as function
3765             // expression in surrounding code.
3766             if (env._no_syntax_extensions && reparsedFunction == null) {
3767                 expect(IDENT);
3768             }
3769         }
3770 
3771         // name is null, generate anonymous name
3772         boolean isAnonymous = false;
3773         if (name == null) {
3774             final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
3775             name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
3776             isAnonymous = true;
3777         }
3778 
3779         final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
3780         List<IdentNode> parameters = Collections.emptyList();
3781         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, functionKind, functionLine, parameters);
3782         lc.push(functionNode);
3783 
3784         Block functionBody = null;
3785         // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
3786         // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
3787         hideDefaultName();
3788         try {
3789             final ParserContextBlockNode parameterBlock = newBlock();
3790             try {
3791                 expect(LPAREN);
3792                 parameters = formalParameterList(generator);
3793                 functionNode.setParameters(parameters);
3794                 expect(RPAREN);
3795             } finally {
3796                 restoreBlock(parameterBlock);
3797             }
3798 
3799             functionBody = functionBody(functionNode);
3800 
3801             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
3802         } finally {
3803             defaultNames.pop();
3804             lc.pop(functionNode);
3805         }
3806 
3807         if (isStatement) {
3808             if (topLevel || useBlockScope() || (!isStrictMode && env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ACCEPT)) {
3809                 functionNode.setFlag(FunctionNode.IS_DECLARED);
3810             } else if (isStrictMode) {
3811                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
3812             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
3813                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
3814             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
3815                 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
3816             }
3817             if (isArguments(name)) {
3818                lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
3819             }
3820         }
3821 
3822         if (isAnonymous) {
3823             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3824         }
3825 
3826         verifyParameterList(parameters, functionNode);
3827 
3828         final FunctionNode function = createFunctionNode(
3829                 functionNode,
3830                 functionToken,
3831                 name,
3832                 parameters,
3833                 functionKind,
3834                 functionLine,
3835                 functionBody);
3836 
3837         if (isStatement) {
3838             if (isAnonymous) {
3839                 appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function));
3840                 return function;
3841             }
3842 
3843             // mark ES6 block functions as lexically scoped
3844             final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
3845             final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
3846             if (topLevel) {
3847                 functionDeclarations.add(varNode);
3848             } else if (useBlockScope()) {
3849                 prependStatement(varNode); // Hoist to beginning of current block
3850             } else {
3851                 appendStatement(varNode);
3852             }
3853         }
3854 
3855         return function;
3856     }
3857 
3858     private void verifyParameterList(final List<IdentNode> parameters, final ParserContextFunctionNode functionNode) {
3859         final IdentNode duplicateParameter = functionNode.getDuplicateParameterBinding();
3860         if (duplicateParameter != null) {
3861             if (functionNode.isStrict() || functionNode.getKind() == FunctionNode.Kind.ARROW || !functionNode.isSimpleParameterList()) {
3862                 throw error(AbstractParser.message("strict.param.redefinition", duplicateParameter.getName()), duplicateParameter.getToken());
3863             }
3864 
3865             final int arity = parameters.size();
3866             final HashSet<String> parametersSet = new HashSet<>(arity);
3867 
3868             for (int i = arity - 1; i >= 0; i--) {
3869                 final IdentNode parameter = parameters.get(i);
3870                 String parameterName = parameter.getName();
3871 
3872                 if (parametersSet.contains(parameterName)) {
3873                     // redefinition of parameter name, rename in non-strict mode
3874                     parameterName = functionNode.uniqueName(parameterName);
3875                     final long parameterToken = parameter.getToken();
3876                     parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
3877                 }
3878                 parametersSet.add(parameterName);
3879             }
3880         }
3881     }
3882 
3883     private static Block maybeWrapBodyInParameterBlock(final Block functionBody, final ParserContextBlockNode parameterBlock) {
3884         assert functionBody.isFunctionBody();
3885         if (!parameterBlock.getStatements().isEmpty()) {
3886             parameterBlock.appendStatement(new BlockStatement(functionBody));
3887             return new Block(parameterBlock.getToken(), functionBody.getFinish(), (functionBody.getFlags() | Block.IS_PARAMETER_BLOCK) & ~Block.IS_BODY, parameterBlock.getStatements());
3888         }
3889         return functionBody;
3890     }
3891 
3892     private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
3893         final String defaultFunctionName = getDefaultFunctionName();
3894         if (isValidIdentifier(defaultFunctionName)) {
3895             if (isStatement) {
3896                 // The name will be used as the LHS of a symbol assignment. We add the anonymous function
3897                 // prefix to ensure that it can't clash with another variable.
3898                 return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
3899             }
3900             return defaultFunctionName;
3901         }
3902         return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
3903     }
3904 
3905     private static boolean isValidIdentifier(final String name) {
3906         if (name == null || name.isEmpty()) {
3907             return false;
3908         }
3909         if (!Character.isJavaIdentifierStart(name.charAt(0))) {
3910             return false;
3911         }
3912         for (int i = 1; i < name.length(); ++i) {
3913             if (!Character.isJavaIdentifierPart(name.charAt(i))) {
3914                 return false;
3915             }
3916         }
3917         return true;
3918     }
3919 
3920     private String getDefaultFunctionName() {
3921         if (!defaultNames.isEmpty()) {
3922             final Object nameExpr = defaultNames.peek();
3923             if (nameExpr instanceof PropertyKey) {
3924                 markDefaultNameUsed();
3925                 return ((PropertyKey)nameExpr).getPropertyName();
3926             } else if (nameExpr instanceof AccessNode) {
3927                 markDefaultNameUsed();
3928                 return ((AccessNode)nameExpr).getProperty();
3929             }
3930         }
3931         return null;
3932     }
3933 
3934     private void markDefaultNameUsed() {
3935         defaultNames.pop();
3936         hideDefaultName();
3937     }
3938 
3939     private void hideDefaultName() {
3940         // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
3941         // from. Can't be null
3942         defaultNames.push("");
3943     }
3944 
3945     /**
3946      * FormalParameterList :
3947      *      Identifier
3948      *      FormalParameterList , Identifier
3949      *
3950      * See 13
3951      *
3952      * Parse function parameter list.
3953      * @return List of parameter nodes.
3954      */
3955     private List<IdentNode> formalParameterList(final boolean yield) {
3956         return formalParameterList(RPAREN, yield);
3957     }
3958 
3959     /**
3960      * Same as the other method of the same name - except that the end
3961      * token type expected is passed as argument to this method.
3962      *
3963      * FormalParameterList :
3964      *      Identifier
3965      *      FormalParameterList , Identifier
3966      *
3967      * See 13
3968      *
3969      * Parse function parameter list.
3970      * @return List of parameter nodes.
3971      */
3972     private List<IdentNode> formalParameterList(final TokenType endType, final boolean yield) {
3973         // Prepare to gather parameters.
3974         final ArrayList<IdentNode> parameters = new ArrayList<>();
3975         // Track commas.
3976         boolean first = true;
3977 
3978         while (type != endType) {
3979             // Comma prior to every argument except the first.
3980             if (!first) {
3981                 expect(COMMARIGHT);
3982             } else {
3983                 first = false;
3984             }
3985 
3986             boolean restParameter = false;
3987             if (type == ELLIPSIS && isES6()) {
3988                 next();
3989                 restParameter = true;
3990             }
3991 
3992             if (type == YIELD && yield) {
3993                 expect(IDENT);
3994             }
3995 
3996             final long paramToken = token;
3997             final int paramLine = line;
3998             final String contextString = "function parameter";
3999             IdentNode ident;
4000             if (isBindingIdentifier() || restParameter || !isES6()) {
4001                 ident = bindingIdentifier(contextString);
4002 
4003                 if (restParameter) {
4004                     ident = ident.setIsRestParameter();
4005                     // rest parameter must be last
4006                     expectDontAdvance(endType);
4007                     parameters.add(ident);
4008                     break;
4009                 } else if (type == ASSIGN && isES6()) {
4010                     next();
4011                     ident = ident.setIsDefaultParameter();
4012 
4013                     if (type == YIELD && yield) {
4014                         // error: yield in default expression
4015                         expect(IDENT);
4016                     }
4017 
4018                     // default parameter
4019                     final Expression initializer = assignmentExpression(false);
4020 
4021                     final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4022                     if (currentFunction != null) {
4023                         if (env._parse_only) {
4024                             // keep what is seen in source "as is" and save it as parameter expression
4025                             final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, initializer);
4026                             currentFunction.addParameterExpression(ident, assignment);
4027                         } else {
4028                             // desugar to: param = (param === undefined) ? initializer : param;
4029                             // possible alternative: if (param === undefined) param = initializer;
4030                             final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4031                             final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4032                             final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
4033                             lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4034                         }
4035                     }
4036                 }
4037 
4038                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4039                 if (currentFunction != null) {
4040                     currentFunction.addParameterBinding(ident);
4041                     if (ident.isRestParameter() || ident.isDefaultParameter()) {
4042                         currentFunction.setSimpleParameterList(false);
4043                     }
4044                 }
4045             } else {
4046                 final Expression pattern = bindingPattern();
4047                 // Introduce synthetic temporary parameter to capture the object to be destructured.
4048                 ident = createIdentNode(paramToken, pattern.getFinish(), String.format("arguments[%d]", parameters.size())).setIsDestructuredParameter();
4049                 verifyDestructuringParameterBindingPattern(pattern, paramToken, paramLine, contextString);
4050 
4051                 Expression value = ident;
4052                 if (type == ASSIGN) {
4053                     next();
4054                     ident = ident.setIsDefaultParameter();
4055 
4056                     // binding pattern with initializer. desugar to: (param === undefined) ? initializer : param
4057                     final Expression initializer = assignmentExpression(false);
4058 
4059                     if (env._parse_only) {
4060                         // we don't want the synthetic identifier in parse only mode
4061                         value = initializer;
4062                     } else {
4063                         // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list)
4064                         final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4065                         value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4066                     }
4067                 }
4068 
4069                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4070                 if (currentFunction != null) {
4071                     // destructuring assignment
4072                     final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), pattern, value);
4073                     if (env._parse_only) {
4074                         // in parse-only mode, represent source tree "as is"
4075                         if (ident.isDefaultParameter()) {
4076                             currentFunction.addParameterExpression(ident, assignment);
4077                         } else {
4078                             currentFunction.addParameterExpression(ident, pattern);
4079                         }
4080                     } else {
4081                         lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4082                     }
4083                 }
4084             }
4085             parameters.add(ident);
4086         }
4087 
4088         parameters.trimToSize();
4089         return parameters;
4090     }
4091 
4092     private void verifyDestructuringParameterBindingPattern(final Expression pattern, final long paramToken, final int paramLine, final String contextString) {
4093         verifyDestructuringBindingPattern(pattern, new Consumer<IdentNode>() {
4094             public void accept(final IdentNode identNode) {
4095                 verifyIdent(identNode, contextString);
4096 
4097                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4098                 if (currentFunction != null) {
4099                     // declare function-scope variables for destructuring bindings
4100                     if (!env._parse_only) {
4101                         lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null));
4102                     }
4103                     // detect duplicate bounds names in parameter list
4104                     currentFunction.addParameterBinding(identNode);
4105                     currentFunction.setSimpleParameterList(false);
4106                 }
4107             }
4108         });
4109     }
4110 
4111     /**
4112      * FunctionBody :
4113      *      SourceElements?
4114      *
4115      * See 13
4116      *
4117      * Parse function body.
4118      * @return function node (body.)
4119      */
4120     private Block functionBody(final ParserContextFunctionNode functionNode) {
4121         long lastToken = 0L;
4122         ParserContextBlockNode body = null;
4123         final long bodyToken = token;
4124         Block functionBody;
4125         int bodyFinish = 0;
4126 
4127         final boolean parseBody;
4128         Object endParserState = null;
4129         try {
4130             // Create a new function block.
4131             body = newBlock();
4132             if (env._debug_scopes) {
4133                 // debug scope options forces everything to be in scope
4134                 markEval(lc);
4135             }
4136             assert functionNode != null;
4137             final int functionId = functionNode.getId();
4138             parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
4139             // Nashorn extension: expression closures
4140             if ((!env._no_syntax_extensions || functionNode.getKind() == FunctionNode.Kind.ARROW) && type != LBRACE) {
4141                 /*
4142                  * Example:
4143                  *
4144                  * function square(x) x * x;
4145                  * print(square(3));
4146                  */
4147 
4148                 // just expression as function body
4149                 final Expression expr = assignmentExpression(false);
4150                 lastToken = previousToken;
4151                 functionNode.setLastToken(previousToken);
4152                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
4153                 // EOL uses length field to store the line number
4154                 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
4155                 // Only create the return node if we aren't skipping nested functions. Note that we aren't
4156                 // skipping parsing of these extended functions; they're considered to be small anyway. Also,
4157                 // they don't end with a single well known token, so it'd be very hard to get correctly (see
4158                 // the note below for reasoning on skipping happening before instead of after RBRACE for
4159                 // details).
4160                 if (parseBody) {
4161                     functionNode.setFlag(FunctionNode.HAS_EXPRESSION_BODY);
4162                     final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
4163                     appendStatement(returnNode);
4164                 }
4165                 // bodyFinish = finish;
4166             } else {
4167                 expectDontAdvance(LBRACE);
4168                 if (parseBody || !skipFunctionBody(functionNode)) {
4169                     next();
4170                     // Gather the function elements.
4171                     final List<Statement> prevFunctionDecls = functionDeclarations;
4172                     functionDeclarations = new ArrayList<>();
4173                     try {
4174                         sourceElements(0);
4175                         addFunctionDeclarations(functionNode);
4176                     } finally {
4177                         functionDeclarations = prevFunctionDecls;
4178                     }
4179 
4180                     lastToken = token;
4181                     if (parseBody) {
4182                         // Since the lexer can read ahead and lexify some number of tokens in advance and have
4183                         // them buffered in the TokenStream, we need to produce a lexer state as it was just
4184                         // before it lexified RBRACE, and not whatever is its current (quite possibly well read
4185                         // ahead) state.
4186                         endParserState = new ParserState(Token.descPosition(token), line, linePosition);
4187 
4188                         // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
4189                         // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
4190                         // state after it. The reason is that RBRACE is a well-known token that we can expect and
4191                         // will never involve us getting into a weird lexer state, and as such is a great reparse
4192                         // point. Typical example of a weird lexer state after RBRACE would be:
4193                         //     function this_is_skipped() { ... } "use strict";
4194                         // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
4195                         // of compensating for the possibility of a string literal (or similar) after RBRACE,
4196                         // we'll rather just restart parsing from this well-known, friendly token instead.
4197                     }
4198                 }
4199                 bodyFinish = finish;
4200                 functionNode.setLastToken(token);
4201                 expect(RBRACE);
4202             }
4203         } finally {
4204             restoreBlock(body);
4205         }
4206 
4207         // NOTE: we can only do alterations to the function node after restoreFunctionNode.
4208 
4209         if (parseBody) {
4210             functionNode.setEndParserState(endParserState);
4211         } else if (!body.getStatements().isEmpty()){
4212             // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
4213             // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
4214             // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
4215             // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
4216             // nested bodies early if we were supposed to skip 'em.
4217             body.setStatements(Collections.<Statement>emptyList());
4218         }
4219 
4220         if (reparsedFunction != null) {
4221             // We restore the flags stored in the function's ScriptFunctionData that we got when we first
4222             // eagerly parsed the code. We're doing it because some flags would be set based on the
4223             // content of the function, or even content of its nested functions, most of which are normally
4224             // skipped during an on-demand compilation.
4225             final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
4226             if (data != null) {
4227                 // Data can be null if when we originally parsed the file, we removed the function declaration
4228                 // as it was dead code.
4229                 functionNode.setFlag(data.getFunctionFlags());
4230                 // This compensates for missing markEval() in case the function contains an inner function
4231                 // that contains eval(), that now we didn't discover since we skipped the inner function.
4232                 if (functionNode.hasNestedEval()) {
4233                     assert functionNode.hasScopeBlock();
4234                     body.setFlag(Block.NEEDS_SCOPE);
4235                 }
4236             }
4237         }
4238         functionBody = new Block(bodyToken, bodyFinish, body.getFlags() | Block.IS_BODY, body.getStatements());
4239         return functionBody;
4240     }
4241 
4242     private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
4243         if (reparsedFunction == null) {
4244             // Not reparsing, so don't skip any function body.
4245             return false;
4246         }
4247         // Skip to the RBRACE of this function, and continue parsing from there.
4248         final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
4249         if (data == null) {
4250             // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
4251             // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
4252             // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
4253             return false;
4254         }
4255         final ParserState parserState = (ParserState)data.getEndParserState();
4256         assert parserState != null;
4257 
4258         if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) {
4259             // RBRACE is already in the token stream, so fast forward to it
4260             for (; k < stream.last(); k++) {
4261                 final long nextToken = stream.get(k + 1);
4262                 if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) {
4263                     token = stream.get(k);
4264                     type = Token.descType(token);
4265                     next();
4266                     assert type == RBRACE && start == parserState.position;
4267                     return true;
4268                 }
4269             }
4270         }
4271 
4272         stream.reset();
4273         lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
4274         line = parserState.line;
4275         linePosition = parserState.linePosition;
4276         // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
4277         // the RBRACE.
4278         type = SEMICOLON;
4279         scanFirstToken();
4280 
4281         return true;
4282     }
4283 
4284     /**
4285      * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
4286      * for resuming parsing after skipping a function body.
4287      */
4288     private static class ParserState implements Serializable {
4289         private final int position;
4290         private final int line;
4291         private final int linePosition;
4292 
4293         private static final long serialVersionUID = -2382565130754093694L;
4294 
4295         ParserState(final int position, final int line, final int linePosition) {
4296             this.position = position;
4297             this.line = line;
4298             this.linePosition = linePosition;
4299         }
4300 
4301         Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
4302             final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
4303             newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
4304             return newLexer;
4305         }
4306     }
4307 
4308     private void printAST(final FunctionNode functionNode) {
4309         if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) {
4310             env.getErr().println(new ASTWriter(functionNode));
4311         }
4312 
4313         if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) {
4314             env.getErr().println(new PrintVisitor(functionNode, true, false));
4315         }
4316     }
4317 
4318     private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
4319         VarNode lastDecl = null;
4320         for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
4321             Statement decl = functionDeclarations.get(i);
4322             if (lastDecl == null && decl instanceof VarNode) {
4323                 decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
4324                 functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
4325             }
4326             prependStatement(decl);
4327         }
4328     }
4329 
4330     private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
4331         if (env._parse_only || earlyError) {
4332             throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
4333         }
4334         final ArrayList<Expression> args = new ArrayList<>();
4335         args.add(lhs);
4336         if (rhs == null) {
4337             args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
4338         } else {
4339             args.add(rhs);
4340         }
4341         args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
4342         return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
4343     }
4344 
4345     /**
4346      * PostfixExpression :
4347      *      LeftHandSideExpression
4348      *      LeftHandSideExpression ++ // [no LineTerminator here]
4349      *      LeftHandSideExpression -- // [no LineTerminator here]
4350      *
4351      * See 11.3
4352      *
4353      * UnaryExpression :
4354      *      PostfixExpression
4355      *      delete UnaryExpression
4356      *      void UnaryExpression
4357      *      typeof UnaryExpression
4358      *      ++ UnaryExpression
4359      *      -- UnaryExpression
4360      *      + UnaryExpression
4361      *      - UnaryExpression
4362      *      ~ UnaryExpression
4363      *      ! UnaryExpression
4364      *
4365      * See 11.4
4366      *
4367      * Parse unary expression.
4368      * @return Expression node.
4369      */
4370     private Expression unaryExpression() {
4371         final int  unaryLine  = line;
4372         final long unaryToken = token;
4373 
4374         switch (type) {
4375         case DELETE: {
4376             next();
4377             final Expression expr = unaryExpression();
4378             if (expr instanceof BaseNode || expr instanceof IdentNode) {
4379                 return new UnaryNode(unaryToken, expr);
4380             }
4381             appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
4382             return LiteralNode.newInstance(unaryToken, finish, true);
4383         }
4384         case VOID:
4385         case TYPEOF:
4386         case ADD:
4387         case SUB:
4388         case BIT_NOT:
4389         case NOT:
4390             next();
4391             final Expression expr = unaryExpression();
4392             return new UnaryNode(unaryToken, expr);
4393 
4394         case INCPREFIX:
4395         case DECPREFIX:
4396             final TokenType opType = type;
4397             next();
4398 
4399             final Expression lhs = leftHandSideExpression();
4400             // ++, -- without operand..
4401             if (lhs == null) {
4402                 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
4403             }
4404 
4405             return verifyIncDecExpression(unaryToken, opType, lhs, false);
4406 
4407         default:
4408             break;
4409         }
4410 
4411         final Expression expression = leftHandSideExpression();
4412 
4413         if (last != EOL) {
4414             switch (type) {
4415             case INCPREFIX:
4416             case DECPREFIX:
4417                 final long opToken = token;
4418                 final TokenType opType = type;
4419                 final Expression lhs = expression;
4420                 // ++, -- without operand..
4421                 if (lhs == null) {
4422                     throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
4423                 }
4424                 next();
4425 
4426                 return verifyIncDecExpression(opToken, opType, lhs, true);
4427             default:
4428                 break;
4429             }
4430         }
4431 
4432         if (expression == null) {
4433             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
4434         }
4435 
4436         return expression;
4437     }
4438 
4439     private Expression verifyIncDecExpression(final long unaryToken, final TokenType opType, final Expression lhs, final boolean isPostfix) {
4440         assert lhs != null;
4441 
4442         if (!(lhs instanceof AccessNode ||
4443               lhs instanceof IndexNode ||
4444               lhs instanceof IdentNode)) {
4445             return referenceError(lhs, null, env._early_lvalue_error);
4446         }
4447 
4448         if (lhs instanceof IdentNode) {
4449             if (!checkIdentLValue((IdentNode)lhs)) {
4450                 return referenceError(lhs, null, false);
4451             }
4452             verifyIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
4453         }
4454 
4455         return incDecExpression(unaryToken, opType, lhs, isPostfix);
4456     }
4457 
4458     /**
4459      * {@code
4460      * MultiplicativeExpression :
4461      *      UnaryExpression
4462      *      MultiplicativeExpression * UnaryExpression
4463      *      MultiplicativeExpression / UnaryExpression
4464      *      MultiplicativeExpression % UnaryExpression
4465      *
4466      * See 11.5
4467      *
4468      * AdditiveExpression :
4469      *      MultiplicativeExpression
4470      *      AdditiveExpression + MultiplicativeExpression
4471      *      AdditiveExpression - MultiplicativeExpression
4472      *
4473      * See 11.6
4474      *
4475      * ShiftExpression :
4476      *      AdditiveExpression
4477      *      ShiftExpression << AdditiveExpression
4478      *      ShiftExpression >> AdditiveExpression
4479      *      ShiftExpression >>> AdditiveExpression
4480      *
4481      * See 11.7
4482      *
4483      * RelationalExpression :
4484      *      ShiftExpression
4485      *      RelationalExpression < ShiftExpression
4486      *      RelationalExpression > ShiftExpression
4487      *      RelationalExpression <= ShiftExpression
4488      *      RelationalExpression >= ShiftExpression
4489      *      RelationalExpression instanceof ShiftExpression
4490      *      RelationalExpression in ShiftExpression // if !noIf
4491      *
4492      * See 11.8
4493      *
4494      *      RelationalExpression
4495      *      EqualityExpression == RelationalExpression
4496      *      EqualityExpression != RelationalExpression
4497      *      EqualityExpression === RelationalExpression
4498      *      EqualityExpression !== RelationalExpression
4499      *
4500      * See 11.9
4501      *
4502      * BitwiseANDExpression :
4503      *      EqualityExpression
4504      *      BitwiseANDExpression & EqualityExpression
4505      *
4506      * BitwiseXORExpression :
4507      *      BitwiseANDExpression
4508      *      BitwiseXORExpression ^ BitwiseANDExpression
4509      *
4510      * BitwiseORExpression :
4511      *      BitwiseXORExpression
4512      *      BitwiseORExpression | BitwiseXORExpression
4513      *
4514      * See 11.10
4515      *
4516      * LogicalANDExpression :
4517      *      BitwiseORExpression
4518      *      LogicalANDExpression && BitwiseORExpression
4519      *
4520      * LogicalORExpression :
4521      *      LogicalANDExpression
4522      *      LogicalORExpression || LogicalANDExpression
4523      *
4524      * See 11.11
4525      *
4526      * ConditionalExpression :
4527      *      LogicalORExpression
4528      *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
4529      *
4530      * See 11.12
4531      *
4532      * AssignmentExpression :
4533      *      ConditionalExpression
4534      *      LeftHandSideExpression AssignmentOperator AssignmentExpression
4535      *
4536      * AssignmentOperator :
4537      *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
4538      *
4539      * See 11.13
4540      *
4541      * Expression :
4542      *      AssignmentExpression
4543      *      Expression , AssignmentExpression
4544      *
4545      * See 11.14
4546      * }
4547      *
4548      * Parse expression.
4549      * @return Expression node.
4550      */
4551     protected Expression expression() {
4552         // This method is protected so that subclass can get details
4553         // at expression start point!
4554 
4555         // Include commas in expression parsing.
4556         return expression(false);
4557     }
4558 
4559     private Expression expression(final boolean noIn) {
4560         Expression assignmentExpression = assignmentExpression(noIn);
4561         while (type == COMMARIGHT) {
4562             final long commaToken = token;
4563             next();
4564 
4565             boolean rhsRestParameter = false;
4566             if (type == ELLIPSIS && isES6()) {
4567                 // (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).
4568                 // 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.
4569                 if (isRestParameterEndOfArrowFunctionParameterList()) {
4570                     next();
4571                     rhsRestParameter = true;
4572                 }
4573             }
4574 
4575             Expression rhs = assignmentExpression(noIn);
4576 
4577             if (rhsRestParameter) {
4578                 rhs = ((IdentNode)rhs).setIsRestParameter();
4579                 // Our only valid move is to end Expression here and continue with ArrowFunction.
4580                 // We've already checked that this is the parameter list of an arrow function (see above).
4581                 // RPAREN is next, so we'll finish the binary expression and drop out of the loop.
4582                 assert type == RPAREN;
4583             }
4584 
4585             assignmentExpression = new BinaryNode(commaToken, assignmentExpression, rhs);
4586         }
4587         return assignmentExpression;
4588     }
4589 
4590     private Expression expression(final int minPrecedence, final boolean noIn) {
4591         return expression(unaryExpression(), minPrecedence, noIn);
4592     }
4593 
4594     private JoinPredecessorExpression joinPredecessorExpression() {
4595         return new JoinPredecessorExpression(expression());
4596     }
4597 
4598     private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
4599         // Get the precedence of the next operator.
4600         int precedence = type.getPrecedence();
4601         Expression lhs = exprLhs;
4602 
4603         // While greater precedence.
4604         while (type.isOperator(noIn) && precedence >= minPrecedence) {
4605             // Capture the operator token.
4606             final long op = token;
4607 
4608             if (type == TERNARY) {
4609                 // Skip operator.
4610                 next();
4611 
4612                 // Pass expression. Middle expression of a conditional expression can be a "in"
4613                 // expression - even in the contexts where "in" is not permitted.
4614                 final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
4615 
4616                 expect(COLON);
4617 
4618                 // Fail expression.
4619                 final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
4620 
4621                 // Build up node.
4622                 lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
4623             } else {
4624                 // Skip operator.
4625                 next();
4626 
4627                  // Get the next primary expression.
4628                 Expression rhs;
4629                 final boolean isAssign = Token.descType(op) == ASSIGN;
4630                 if(isAssign) {
4631                     defaultNames.push(lhs);
4632                 }
4633                 try {
4634                     rhs = unaryExpression();
4635                     // Get precedence of next operator.
4636                     int nextPrecedence = type.getPrecedence();
4637 
4638                     // Subtask greater precedence.
4639                     while (type.isOperator(noIn) &&
4640                            (nextPrecedence > precedence ||
4641                            nextPrecedence == precedence && !type.isLeftAssociative())) {
4642                         rhs = expression(rhs, nextPrecedence, noIn);
4643                         nextPrecedence = type.getPrecedence();
4644                     }
4645                 } finally {
4646                     if(isAssign) {
4647                         defaultNames.pop();
4648                     }
4649                 }
4650                 lhs = verifyAssignment(op, lhs, rhs);
4651             }
4652 
4653             precedence = type.getPrecedence();
4654         }
4655 
4656         return lhs;
4657     }
4658 
4659     /**
4660      * AssignmentExpression.
4661      *
4662      * AssignmentExpression[In, Yield] :
4663      *   ConditionalExpression[?In, ?Yield]
4664      *   [+Yield] YieldExpression[?In]
4665      *   ArrowFunction[?In, ?Yield]
4666      *   LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield]
4667      *   LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield]
4668      *
4669      * @param noIn {@code true} if IN operator should be ignored.
4670      * @return the assignment expression
4671      */
4672     protected Expression assignmentExpression(final boolean noIn) {
4673         // This method is protected so that subclass can get details
4674         // at assignment expression start point!
4675 
4676         if (type == YIELD && inGeneratorFunction() && isES6()) {
4677             return yieldExpression(noIn);
4678         }
4679 
4680         final long startToken = token;
4681         final int startLine = line;
4682         final Expression exprLhs = conditionalExpression(noIn);
4683 
4684         if (type == ARROW && isES6()) {
4685             if (checkNoLineTerminator()) {
4686                 final Expression paramListExpr;
4687                 if (exprLhs instanceof ExpressionList) {
4688                     paramListExpr = (((ExpressionList)exprLhs).getExpressions().isEmpty() ? null : ((ExpressionList)exprLhs).getExpressions().get(0));
4689                 } else {
4690                     paramListExpr = exprLhs;
4691                 }
4692                 return arrowFunction(startToken, startLine, paramListExpr);
4693             }
4694         }
4695         assert !(exprLhs instanceof ExpressionList);
4696 
4697         if (isAssignmentOperator(type)) {
4698             final boolean isAssign = type == ASSIGN;
4699             if (isAssign) {
4700                 defaultNames.push(exprLhs);
4701             }
4702             try {
4703                 final long assignToken = token;
4704                 next();
4705                 final Expression exprRhs = assignmentExpression(noIn);
4706                 return verifyAssignment(assignToken, exprLhs, exprRhs);
4707             } finally {
4708                 if (isAssign) {
4709                     defaultNames.pop();
4710                 }
4711             }
4712         } else {
4713             return exprLhs;
4714         }
4715     }
4716 
4717     /**
4718      * Is type one of {@code = *= /= %= += -= <<= >>= >>>= &= ^= |=}?
4719      */
4720     private static boolean isAssignmentOperator(final TokenType type) {
4721         switch (type) {
4722         case ASSIGN:
4723         case ASSIGN_ADD:
4724         case ASSIGN_BIT_AND:
4725         case ASSIGN_BIT_OR:
4726         case ASSIGN_BIT_XOR:
4727         case ASSIGN_DIV:
4728         case ASSIGN_MOD:
4729         case ASSIGN_MUL:
4730         case ASSIGN_SAR:
4731         case ASSIGN_SHL:
4732         case ASSIGN_SHR:
4733         case ASSIGN_SUB:
4734             return true;
4735         }
4736         return false;
4737     }
4738 
4739     /**
4740      * ConditionalExpression.
4741      */
4742     private Expression conditionalExpression(final boolean noIn) {
4743         return expression(TERNARY.getPrecedence(), noIn);
4744     }
4745 
4746     /**
4747      * ArrowFunction.
4748      *
4749      * @param startToken start token of the ArrowParameters expression
4750      * @param functionLine start line of the arrow function
4751      * @param paramListExpr ArrowParameters expression or {@code null} for {@code ()} (empty list)
4752      */
4753     private Expression arrowFunction(final long startToken, final int functionLine, final Expression paramListExpr) {
4754         // caller needs to check that there's no LineTerminator between parameter list and arrow
4755         assert type != ARROW || checkNoLineTerminator();
4756         expect(ARROW);
4757 
4758         final long functionToken = Token.recast(startToken, ARROW);
4759         final IdentNode name = new IdentNode(functionToken, Token.descPosition(functionToken), NameCodec.encode("=>:") + functionLine);
4760         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.ARROW, functionLine, null);
4761         functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
4762 
4763         lc.push(functionNode);
4764         try {
4765             final ParserContextBlockNode parameterBlock = newBlock();
4766             final List<IdentNode> parameters;
4767             try {
4768                 parameters = convertArrowFunctionParameterList(paramListExpr, functionLine);
4769                 functionNode.setParameters(parameters);
4770 
4771                 if (!functionNode.isSimpleParameterList()) {
4772                     markEvalInArrowParameterList(parameterBlock);
4773                 }
4774             } finally {
4775                 restoreBlock(parameterBlock);
4776             }
4777             Block functionBody = functionBody(functionNode);
4778 
4779             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
4780 
4781             verifyParameterList(parameters, functionNode);
4782 
4783             final FunctionNode function = createFunctionNode(
4784                             functionNode,
4785                             functionToken,
4786                             name,
4787                             parameters,
4788                             FunctionNode.Kind.ARROW,
4789                             functionLine,
4790                             functionBody);
4791             return function;
4792         } finally {
4793             lc.pop(functionNode);
4794         }
4795     }
4796 
4797     private void markEvalInArrowParameterList(final ParserContextBlockNode parameterBlock) {
4798         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
4799         final ParserContextFunctionNode current = iter.next();
4800         final ParserContextFunctionNode parent = iter.next();
4801 
4802         if (parent.getFlag(FunctionNode.HAS_EVAL) != 0) {
4803             // we might have flagged has-eval in the parent function during parsing the parameter list,
4804             // if the parameter list contains eval; must tag arrow function as has-eval.
4805             for (final Statement st : parameterBlock.getStatements()) {
4806                 st.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
4807                     @Override
4808                     public boolean enterCallNode(final CallNode callNode) {
4809                         if (callNode.getFunction() instanceof IdentNode && ((IdentNode) callNode.getFunction()).getName().equals("eval")) {
4810                             current.setFlag(FunctionNode.HAS_EVAL);
4811                         }
4812                         return true;
4813                     }
4814                 });
4815             }
4816             // TODO: function containing the arrow function should not be flagged has-eval
4817         }
4818     }
4819 
4820     private List<IdentNode> convertArrowFunctionParameterList(final Expression paramListExpr, final int functionLine) {
4821         final List<IdentNode> parameters;
4822         if (paramListExpr == null) {
4823             // empty parameter list, i.e. () =>
4824             parameters = Collections.emptyList();
4825         } else if (paramListExpr instanceof IdentNode || paramListExpr.isTokenType(ASSIGN) || isDestructuringLhs(paramListExpr)) {
4826             parameters = Collections.singletonList(verifyArrowParameter(paramListExpr, 0, functionLine));
4827         } else if (paramListExpr instanceof BinaryNode && Token.descType(paramListExpr.getToken()) == COMMARIGHT) {
4828             parameters = new ArrayList<>();
4829             Expression car = paramListExpr;
4830             do {
4831                 final Expression cdr = ((BinaryNode) car).rhs();
4832                 parameters.add(0, verifyArrowParameter(cdr, parameters.size(), functionLine));
4833                 car = ((BinaryNode) car).lhs();
4834             } while (car instanceof BinaryNode && Token.descType(car.getToken()) == COMMARIGHT);
4835             parameters.add(0, verifyArrowParameter(car, parameters.size(), functionLine));
4836         } else {
4837             throw error(AbstractParser.message("expected.arrow.parameter"), paramListExpr.getToken());
4838         }
4839         return parameters;
4840     }
4841 
4842     private IdentNode verifyArrowParameter(final Expression param, final int index, final int paramLine) {
4843         final String contextString = "function parameter";
4844         if (param instanceof IdentNode) {
4845             final IdentNode ident = (IdentNode)param;
4846             verifyStrictIdent(ident, contextString);
4847             final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4848             if (currentFunction != null) {
4849                 currentFunction.addParameterBinding(ident);
4850             }
4851             return ident;
4852         }
4853 
4854         if (param.isTokenType(ASSIGN)) {
4855             final Expression lhs = ((BinaryNode) param).lhs();
4856             final long paramToken = lhs.getToken();
4857             final Expression initializer = ((BinaryNode) param).rhs();
4858             if (lhs instanceof IdentNode) {
4859                 // default parameter
4860                 final IdentNode ident = (IdentNode) lhs;
4861 
4862                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4863                 if (currentFunction != null) {
4864                     if (env._parse_only) {
4865                         currentFunction.addParameterExpression(ident, param);
4866                     } else {
4867                         final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4868                         final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4869                         final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
4870                         lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4871                     }
4872 
4873                     currentFunction.addParameterBinding(ident);
4874                     currentFunction.setSimpleParameterList(false);
4875                 }
4876                 return ident;
4877             } else if (isDestructuringLhs(lhs)) {
4878                 // binding pattern with initializer
4879                 // Introduce synthetic temporary parameter to capture the object to be destructured.
4880                 final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter().setIsDefaultParameter();
4881                 verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
4882 
4883                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4884                 if (currentFunction != null) {
4885                     if (env._parse_only) {
4886                         currentFunction.addParameterExpression(ident, param);
4887                     } else {
4888                         final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4889                         final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4890                         final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value);
4891                         lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4892                     }
4893                 }
4894                 return ident;
4895             }
4896         } else if (isDestructuringLhs(param)) {
4897             // binding pattern
4898             final long paramToken = param.getToken();
4899 
4900             // Introduce synthetic temporary parameter to capture the object to be destructured.
4901             final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter();
4902             verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
4903 
4904             final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4905             if (currentFunction != null) {
4906                 if (env._parse_only) {
4907                     currentFunction.addParameterExpression(ident, param);
4908                 } else {
4909                     final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident);
4910                     lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4911                 }
4912             }
4913             return ident;
4914         }
4915         throw error(AbstractParser.message("invalid.arrow.parameter"), param.getToken());
4916     }
4917 
4918     private boolean checkNoLineTerminator() {
4919         assert type == ARROW;
4920         if (last == RPAREN) {
4921             return true;
4922         } else if (last == IDENT) {
4923             return true;
4924         }
4925         for (int i = k - 1; i >= 0; i--) {
4926             final TokenType t = T(i);
4927             switch (t) {
4928             case RPAREN:
4929             case IDENT:
4930                 return true;
4931             case EOL:
4932                 return false;
4933             case COMMENT:
4934                 continue;
4935             default:
4936                 if (t.getKind() == TokenKind.FUTURESTRICT) {
4937                     return true;
4938                 }
4939                 return false;
4940             }
4941         }
4942         return false;
4943     }
4944 
4945     /**
4946      * Peek ahead to see if what follows after the ellipsis is a rest parameter
4947      * at the end of an arrow function parameter list.
4948      */
4949     private boolean isRestParameterEndOfArrowFunctionParameterList() {
4950         assert type == ELLIPSIS;
4951         // find IDENT, RPAREN, ARROW, in that order, skipping over EOL (where allowed) and COMMENT
4952         int i = 1;
4953         for (;;) {
4954             final TokenType t = T(k + i++);
4955             if (t == IDENT) {
4956                 break;
4957             } else if (t == EOL || t == COMMENT) {
4958                 continue;
4959             } else {
4960                 return false;
4961             }
4962         }
4963         for (;;) {
4964             final TokenType t = T(k + i++);
4965             if (t == RPAREN) {
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 == ARROW) {
4976                 break;
4977             } else if (t == COMMENT) {
4978                 continue;
4979             } else {
4980                 return false;
4981             }
4982         }
4983         return true;
4984     }
4985 
4986     /**
4987      * Parse an end of line.
4988      */
4989     private void endOfLine() {
4990         switch (type) {
4991         case SEMICOLON:
4992         case EOL:
4993             next();
4994             break;
4995         case RPAREN:
4996         case RBRACKET:
4997         case RBRACE:
4998         case EOF:
4999             break;
5000         default:
5001             if (last != EOL) {
5002                 expect(SEMICOLON);
5003             }
5004             break;
5005         }
5006     }
5007 
5008     /**
5009      * Parse untagged template literal as string concatenation.
5010      */
5011     private Expression templateLiteral() {
5012         assert type == TEMPLATE || type == TEMPLATE_HEAD;
5013         final boolean noSubstitutionTemplate = type == TEMPLATE;
5014         long lastLiteralToken = token;
5015         LiteralNode<?> literal = getLiteral();
5016         if (noSubstitutionTemplate) {
5017             return literal;
5018         }
5019 
5020         if (env._parse_only) {
5021             final List<Expression> exprs = new ArrayList<>();
5022             exprs.add(literal);
5023             TokenType lastLiteralType;
5024             do {
5025                 final Expression expression = expression();
5026                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5027                     throw error(AbstractParser.message("unterminated.template.expression"), token);
5028                 }
5029                 exprs.add(expression);
5030                 lastLiteralType = type;
5031                 literal = getLiteral();
5032                 exprs.add(literal);
5033             } while (lastLiteralType == TEMPLATE_MIDDLE);
5034             return new TemplateLiteral(exprs);
5035         } else {
5036             Expression concat = literal;
5037             TokenType lastLiteralType;
5038             do {
5039                 final Expression expression = expression();
5040                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5041                     throw error(AbstractParser.message("unterminated.template.expression"), token);
5042                 }
5043                 concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression);
5044                 lastLiteralType = type;
5045                 lastLiteralToken = token;
5046                 literal = getLiteral();
5047                 concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal);
5048             } while (lastLiteralType == TEMPLATE_MIDDLE);
5049             return concat;
5050         }
5051     }
5052 
5053     /**
5054      * Parse tagged template literal as argument list.
5055      * @return argument list for a tag function call (template object, ...substitutions)
5056      */
5057     private List<Expression> templateLiteralArgumentList() {
5058         assert type == TEMPLATE || type == TEMPLATE_HEAD;
5059         final ArrayList<Expression> argumentList = new ArrayList<>();
5060         final ArrayList<Expression> rawStrings = new ArrayList<>();
5061         final ArrayList<Expression> cookedStrings = new ArrayList<>();
5062         argumentList.add(null); // filled at the end
5063 
5064         final long templateToken = token;
5065         final boolean hasSubstitutions = type == TEMPLATE_HEAD;
5066         addTemplateLiteralString(rawStrings, cookedStrings);
5067 
5068         if (hasSubstitutions) {
5069             TokenType lastLiteralType;
5070             do {
5071                 final Expression expression = expression();
5072                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5073                     throw error(AbstractParser.message("unterminated.template.expression"), token);
5074                 }
5075                 argumentList.add(expression);
5076 
5077                 lastLiteralType = type;
5078                 addTemplateLiteralString(rawStrings, cookedStrings);
5079             } while (lastLiteralType == TEMPLATE_MIDDLE);
5080         }
5081 
5082         final LiteralNode<Expression[]> rawStringArray = LiteralNode.newInstance(templateToken, finish, rawStrings);
5083         final LiteralNode<Expression[]> cookedStringArray = LiteralNode.newInstance(templateToken, finish, cookedStrings);
5084         final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray);
5085         argumentList.set(0, templateObject);
5086         return optimizeList(argumentList);
5087     }
5088 
5089     private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) {
5090         final long stringToken = token;
5091         final String rawString = lexer.valueOfRawString(stringToken);
5092         final String cookedString = (String) getValue();
5093         next();
5094         rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString));
5095         cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
5096     }
5097 
5098 
5099     /**
5100      * Parse a module.
5101      *
5102      * Module :
5103      *      ModuleBody?
5104      *
5105      * ModuleBody :
5106      *      ModuleItemList
5107      */
5108     private FunctionNode module(final String moduleName) {
5109         final boolean oldStrictMode = isStrictMode;
5110         try {
5111             isStrictMode = true; // Module code is always strict mode code. (ES6 10.2.1)
5112 
5113             // Make a pseudo-token for the script holding its start and length.
5114             final int functionStart = Math.min(Token.descPosition(Token.withDelimiter(token)), finish);
5115             final long functionToken = Token.toDesc(FUNCTION, functionStart, source.getLength() - functionStart);
5116             final int  functionLine  = line;
5117 
5118             final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), moduleName);
5119             final ParserContextFunctionNode script = createParserContextFunctionNode(
5120                             ident,
5121                             functionToken,
5122                             FunctionNode.Kind.MODULE,
5123                             functionLine,
5124                             Collections.<IdentNode>emptyList());
5125             lc.push(script);
5126 
5127             final ParserContextModuleNode module = new ParserContextModuleNode(moduleName);
5128             lc.push(module);
5129 
5130             final ParserContextBlockNode body = newBlock();
5131 
5132             functionDeclarations = new ArrayList<>();
5133             moduleBody();
5134             addFunctionDeclarations(script);
5135             functionDeclarations = null;
5136 
5137             restoreBlock(body);
5138             body.setFlag(Block.NEEDS_SCOPE);
5139             final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
5140             lc.pop(module);
5141             lc.pop(script);
5142             script.setLastToken(token);
5143 
5144             expect(EOF);
5145 
5146             script.setModule(module.createModule());
5147             return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.MODULE, functionLine, programBody);
5148         } finally {
5149             isStrictMode = oldStrictMode;
5150         }
5151     }
5152 
5153     /**
5154      * Parse module body.
5155      *
5156      * ModuleBody :
5157      *      ModuleItemList
5158      *
5159      * ModuleItemList :
5160      *      ModuleItem
5161      *      ModuleItemList ModuleItem
5162      *
5163      * ModuleItem :
5164      *      ImportDeclaration
5165      *      ExportDeclaration
5166      *      StatementListItem
5167      */
5168     private void moduleBody() {
5169         loop:
5170         while (type != EOF) {
5171             switch (type) {
5172             case EOF:
5173                 break loop;
5174             case IMPORT:
5175                 importDeclaration();
5176                 break;
5177             case EXPORT:
5178                 exportDeclaration();
5179                 break;
5180             default:
5181                 // StatementListItem
5182                 statement(true, 0, false, false);
5183                 break;
5184             }
5185         }
5186     }
5187 
5188 
5189     /**
5190      * Parse import declaration.
5191      *
5192      * ImportDeclaration :
5193      *     import ImportClause FromClause ;
5194      *     import ModuleSpecifier ;
5195      * ImportClause :
5196      *     ImportedDefaultBinding
5197      *     NameSpaceImport
5198      *     NamedImports
5199      *     ImportedDefaultBinding , NameSpaceImport
5200      *     ImportedDefaultBinding , NamedImports
5201      * ImportedDefaultBinding :
5202      *     ImportedBinding
5203      * ModuleSpecifier :
5204      *     StringLiteral
5205      * ImportedBinding :
5206      *     BindingIdentifier
5207      */
5208     private void importDeclaration() {
5209         final int startPosition = start;
5210         expect(IMPORT);
5211         final ParserContextModuleNode module = lc.getCurrentModule();
5212         if (type == STRING || type == ESCSTRING) {
5213             // import ModuleSpecifier ;
5214             final IdentNode moduleSpecifier = createIdentNode(token, finish, (String) getValue());
5215             next();
5216             module.addModuleRequest(moduleSpecifier);
5217         } else {
5218             // import ImportClause FromClause ;
5219             List<Module.ImportEntry> importEntries;
5220             if (type == MUL) {
5221                 importEntries = Collections.singletonList(nameSpaceImport(startPosition));
5222             } else if (type == LBRACE) {
5223                 importEntries = namedImports(startPosition);
5224             } else if (isBindingIdentifier()) {
5225                 // ImportedDefaultBinding
5226                 final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding");
5227                 final Module.ImportEntry defaultImport = Module.ImportEntry.importSpecifier(importedDefaultBinding, startPosition, finish);
5228 
5229                 if (type == COMMARIGHT) {
5230                     next();
5231                     importEntries = new ArrayList<>();
5232                     if (type == MUL) {
5233                         importEntries.add(nameSpaceImport(startPosition));
5234                     } else if (type == LBRACE) {
5235                         importEntries.addAll(namedImports(startPosition));
5236                     } else {
5237                         throw error(AbstractParser.message("expected.named.import"));
5238                     }
5239                 } else {
5240                     importEntries = Collections.singletonList(defaultImport);
5241                 }
5242             } else {
5243                 throw error(AbstractParser.message("expected.import"));
5244             }
5245 
5246             final IdentNode moduleSpecifier = fromClause();
5247             module.addModuleRequest(moduleSpecifier);
5248             for (int i = 0; i < importEntries.size(); i++) {
5249                 module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier, finish));
5250             }
5251         }
5252         expect(SEMICOLON);
5253     }
5254 
5255     /**
5256      * NameSpaceImport :
5257      *     * as ImportedBinding
5258      *
5259      * @param startPosition the start of the import declaration
5260      * @return imported binding identifier
5261      */
5262     private Module.ImportEntry nameSpaceImport(final int startPosition) {
5263         assert type == MUL;
5264         final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
5265         next();
5266         final long asToken = token;
5267         final String as = (String) expectValue(IDENT);
5268         if (!"as".equals(as)) {
5269             throw error(AbstractParser.message("expected.as"), asToken);
5270         }
5271         final IdentNode localNameSpace = bindingIdentifier("ImportedBinding");
5272         return Module.ImportEntry.importSpecifier(starName, localNameSpace, startPosition, finish);
5273     }
5274 
5275     /**
5276      * NamedImports :
5277      *     { }
5278      *     { ImportsList }
5279      *     { ImportsList , }
5280      * ImportsList :
5281      *     ImportSpecifier
5282      *     ImportsList , ImportSpecifier
5283      * ImportSpecifier :
5284      *     ImportedBinding
5285      *     IdentifierName as ImportedBinding
5286      * ImportedBinding :
5287      *     BindingIdentifier
5288      */
5289     private List<Module.ImportEntry> namedImports(final int startPosition) {
5290         assert type == LBRACE;
5291         next();
5292         final List<Module.ImportEntry> importEntries = new ArrayList<>();
5293         while (type != RBRACE) {
5294             final boolean bindingIdentifier = isBindingIdentifier();
5295             final long nameToken = token;
5296             final IdentNode importName = getIdentifierName();
5297             if (type == IDENT && "as".equals(getValue())) {
5298                 next();
5299                 final IdentNode localName = bindingIdentifier("ImportedBinding");
5300                 importEntries.add(Module.ImportEntry.importSpecifier(importName, localName, startPosition, finish));
5301             } else if (!bindingIdentifier) {
5302                 throw error(AbstractParser.message("expected.binding.identifier"), nameToken);
5303             } else {
5304                 importEntries.add(Module.ImportEntry.importSpecifier(importName, startPosition, finish));
5305             }
5306             if (type == COMMARIGHT) {
5307                 next();
5308             } else {
5309                 break;
5310             }
5311         }
5312         expect(RBRACE);
5313         return importEntries;
5314     }
5315 
5316     /**
5317      * FromClause :
5318      *     from ModuleSpecifier
5319      */
5320     private IdentNode fromClause() {
5321         final long fromToken = token;
5322         final String name = (String) expectValue(IDENT);
5323         if (!"from".equals(name)) {
5324             throw error(AbstractParser.message("expected.from"), fromToken);
5325         }
5326         if (type == STRING || type == ESCSTRING) {
5327             final IdentNode moduleSpecifier = createIdentNode(Token.recast(token, IDENT), finish, (String) getValue());
5328             next();
5329             return moduleSpecifier;
5330         } else {
5331             throw error(expectMessage(STRING));
5332         }
5333     }
5334 
5335     /**
5336      * Parse export declaration.
5337      *
5338      * ExportDeclaration :
5339      *     export * FromClause ;
5340      *     export ExportClause FromClause ;
5341      *     export ExportClause ;
5342      *     export VariableStatement
5343      *     export Declaration
5344      *     export default HoistableDeclaration[Default]
5345      *     export default ClassDeclaration[Default]
5346      *     export default [lookahead !in {function, class}] AssignmentExpression[In] ;
5347      */
5348     private void exportDeclaration() {
5349         expect(EXPORT);
5350         final int startPosition = start;
5351         final ParserContextModuleNode module = lc.getCurrentModule();
5352         switch (type) {
5353             case MUL: {
5354                 final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
5355                 next();
5356                 final IdentNode moduleRequest = fromClause();
5357                 expect(SEMICOLON);
5358                 module.addModuleRequest(moduleRequest);
5359                 module.addStarExportEntry(Module.ExportEntry.exportStarFrom(starName, moduleRequest, startPosition, finish));
5360                 break;
5361             }
5362             case LBRACE: {
5363                 final List<Module.ExportEntry> exportEntries = exportClause(startPosition);
5364                 if (type == IDENT && "from".equals(getValue())) {
5365                     final IdentNode moduleRequest = fromClause();
5366                     module.addModuleRequest(moduleRequest);
5367                     for (final Module.ExportEntry exportEntry : exportEntries) {
5368                         module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest, finish));
5369                     }
5370                 } else {
5371                     for (final Module.ExportEntry exportEntry : exportEntries) {
5372                         module.addLocalExportEntry(exportEntry);
5373                     }
5374                 }
5375                 expect(SEMICOLON);
5376                 break;
5377             }
5378             case DEFAULT:
5379                 final IdentNode defaultName = createIdentNode(Token.recast(token, IDENT), finish, Module.DEFAULT_NAME);
5380                 next();
5381                 final Expression assignmentExpression;
5382                 IdentNode ident;
5383                 final int lineNumber = line;
5384                 final long rhsToken = token;
5385                 final boolean declaration;
5386                 switch (type) {
5387                     case FUNCTION:
5388                         assignmentExpression = functionExpression(false, true);
5389                         ident = ((FunctionNode) assignmentExpression).getIdent();
5390                         declaration = true;
5391                         break;
5392                     case CLASS:
5393                         assignmentExpression = classDeclaration(true);
5394                         ident = ((ClassNode) assignmentExpression).getIdent();
5395                         declaration = true;
5396                         break;
5397                     default:
5398                         assignmentExpression = assignmentExpression(false);
5399                         ident = null;
5400                         declaration = false;
5401                         break;
5402                 }
5403                 if (ident != null) {
5404                     module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
5405                 } else {
5406                     ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME);
5407                     lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression));
5408                     if (!declaration) {
5409                         expect(SEMICOLON);
5410                     }
5411                     module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
5412                 }
5413                 break;
5414             case VAR:
5415             case LET:
5416             case CONST:
5417                 final List<Statement> statements = lc.getCurrentBlock().getStatements();
5418                 final int previousEnd = statements.size();
5419                 variableStatement(type);
5420                 for (final Statement statement : statements.subList(previousEnd, statements.size())) {
5421                     if (statement instanceof VarNode) {
5422                         module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName(), startPosition, finish));
5423                     }
5424                 }
5425                 break;
5426             case CLASS: {
5427                 final ClassNode classDeclaration = classDeclaration(false);
5428                 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent(), startPosition, finish));
5429                 break;
5430             }
5431             case FUNCTION: {
5432                 final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true);
5433                 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent(), startPosition, finish));
5434                 break;
5435             }
5436             default:
5437                 throw error(AbstractParser.message("invalid.export"), token);
5438         }
5439     }
5440 
5441     /**
5442      * ExportClause :
5443      *     { }
5444      *     { ExportsList }
5445      *     { ExportsList , }
5446      * ExportsList :
5447      *     ExportSpecifier
5448      *     ExportsList , ExportSpecifier
5449      * ExportSpecifier :
5450      *     IdentifierName
5451      *     IdentifierName as IdentifierName
5452      *
5453      * @return a list of ExportSpecifiers
5454      */
5455     private List<Module.ExportEntry> exportClause(final int startPosition) {
5456         assert type == LBRACE;
5457         next();
5458         final List<Module.ExportEntry> exports = new ArrayList<>();
5459         while (type != RBRACE) {
5460             final IdentNode localName = getIdentifierName();
5461             if (type == IDENT && "as".equals(getValue())) {
5462                 next();
5463                 final IdentNode exportName = getIdentifierName();
5464                 exports.add(Module.ExportEntry.exportSpecifier(exportName, localName, startPosition, finish));
5465             } else {
5466                 exports.add(Module.ExportEntry.exportSpecifier(localName, startPosition, finish));
5467             }
5468             if (type == COMMARIGHT) {
5469                 next();
5470             } else {
5471                 break;
5472             }
5473         }
5474         expect(RBRACE);
5475         return exports;
5476     }
5477 
5478     @Override
5479     public String toString() {
5480         return "'JavaScript Parsing'";
5481     }
5482 
5483     private static void markEval(final ParserContext lc) {
5484         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5485         boolean flaggedCurrentFn = false;
5486         while (iter.hasNext()) {
5487             final ParserContextFunctionNode fn = iter.next();
5488             if (!flaggedCurrentFn) {
5489                 fn.setFlag(FunctionNode.HAS_EVAL);
5490                 flaggedCurrentFn = true;
5491                 if (fn.getKind() == FunctionNode.Kind.ARROW) {
5492                     // possible use of this in an eval that's nested in an arrow function, e.g.:
5493                     // function fun(){ return (() => eval("this"))(); };
5494                     markThis(lc);
5495                     markNewTarget(lc);
5496                 }
5497             } else {
5498                 fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
5499             }
5500             final ParserContextBlockNode body = lc.getFunctionBody(fn);
5501             // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
5502             // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
5503             // this method when the parser skips a nested function.
5504             body.setFlag(Block.NEEDS_SCOPE);
5505             fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
5506         }
5507     }
5508 
5509     private void prependStatement(final Statement statement) {
5510         lc.prependStatementToCurrentNode(statement);
5511     }
5512 
5513     private void appendStatement(final Statement statement) {
5514         lc.appendStatementToCurrentNode(statement);
5515     }
5516 
5517     private static void markSuperCall(final ParserContext lc) {
5518         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5519         while (iter.hasNext()) {
5520             final ParserContextFunctionNode fn = iter.next();
5521             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5522                 assert fn.isSubclassConstructor();
5523                 fn.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
5524                 break;
5525             }
5526         }
5527     }
5528 
5529     private ParserContextFunctionNode getCurrentNonArrowFunction() {
5530         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5531         while (iter.hasNext()) {
5532             final ParserContextFunctionNode fn = iter.next();
5533             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5534                 return fn;
5535             }
5536         }
5537         return null;
5538     }
5539 
5540     private static void markThis(final ParserContext lc) {
5541         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5542         while (iter.hasNext()) {
5543             final ParserContextFunctionNode fn = iter.next();
5544             fn.setFlag(FunctionNode.USES_THIS);
5545             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5546                 break;
5547             }
5548         }
5549     }
5550 
5551     private static void markNewTarget(final ParserContext lc) {
5552         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5553         while (iter.hasNext()) {
5554             final ParserContextFunctionNode fn = iter.next();
5555             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5556                 if (!fn.isProgram()) {
5557                     fn.setFlag(FunctionNode.ES6_USES_NEW_TARGET);
5558                 }
5559                 break;
5560             }
5561         }
5562     }
5563 
5564     private boolean inGeneratorFunction() {
5565         return lc.getCurrentFunction().getKind() == FunctionNode.Kind.GENERATOR;
5566     }
5567 }