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 
1966                 // for each (init; test; modify) is invalid
1967                 if ((flags & ForNode.IS_FOR_EACH) != 0) {
1968                     throw error(AbstractParser.message("for.each.without.in"), token);
1969                 }
1970 
1971                 expect(SEMICOLON);
1972                 if (type != SEMICOLON) {
1973                     test = joinPredecessorExpression();
1974                 }
1975                 expect(SEMICOLON);
1976                 if (type != RPAREN) {
1977                     modify = joinPredecessorExpression();
1978                 }
1979                 break;
1980 
1981             case IDENT:
1982                 if (env._es6 && "of".equals(getValue())) {
1983                     isForOf = true;
1984                     // fall through
1985                 } else {
1986                     expect(SEMICOLON); // fail with expected message
1987                     break;
1988                 }
1989             case IN:
1990                 flags |= isForOf ? ForNode.IS_FOR_OF : ForNode.IS_FOR_IN;
1991                 test = new JoinPredecessorExpression();
1992                 if (varDeclList != null) {
1993                     // for (var|let|const ForBinding in|of expression)
1994                     if (varDeclList.secondBinding != null) {
1995                         // for (var i, j in obj) is invalid
1996                         throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), varDeclList.secondBinding.getToken());
1997                     }
1998                     if (varDeclList.declarationWithInitializerToken != 0 && (isStrictMode || type != TokenType.IN || varType != VAR || varDeclList.init != null)) {
1999                         // ES5 legacy: for (var i = AssignmentExpressionNoIn in Expression)
2000                         // Invalid in ES6, but allow it in non-strict mode if no ES6 features used,
2001                         // i.e., error if strict, for-of, let/const, or destructuring
2002                         throw error(AbstractParser.message("for.in.loop.initializer", isForOf ? "of" : "in"), varDeclList.declarationWithInitializerToken);
2003                     }
2004                     init = varDeclList.firstBinding;
2005                     assert init instanceof IdentNode || isDestructuringLhs(init);
2006                 } else {
2007                     // for (expr in obj)
2008                     assert init != null : "for..in/of init expression can not be null here";
2009 
2010                     // check if initial expression is a valid L-value
2011                     if (!checkValidLValue(init, isForOf ? "for-of iterator" : "for-in iterator")) {
2012                         throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
2013                     }
2014                 }
2015 
2016                 next();
2017 
2018                 // For-of only allows AssignmentExpression.
2019                 modify = isForOf ? new JoinPredecessorExpression(assignmentExpression(false)) : joinPredecessorExpression();
2020                 break;
2021 
2022             default:
2023                 expect(SEMICOLON);
2024                 break;
2025             }
2026 
2027             expect(RPAREN);
2028 
2029             // Set the for body.
2030             body = getStatement();
2031         } finally {
2032             lc.pop(forNode);
2033 
2034             for (final Statement var : forNode.getStatements()) {
2035                 assert var instanceof VarNode;
2036                 appendStatement(var);
2037             }
2038             if (body != null) {
2039                 appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
2040             }
2041             if (outer != null) {
2042                 restoreBlock(outer);
2043                 if (body != null) {
2044                     appendStatement(new BlockStatement(forLine, new Block(
2045                                     outer.getToken(),
2046                                     body.getFinish(),
2047                                     outer.getStatements())));
2048                 }
2049             }
2050         }
2051     }
2052 
2053     private boolean checkValidLValue(final Expression init, final String contextString) {
2054         if (init instanceof IdentNode) {
2055             if (!checkIdentLValue((IdentNode)init)) {
2056                 return false;
2057             }
2058             verifyIdent((IdentNode)init, contextString);
2059             return true;
2060         } else if (init instanceof AccessNode || init instanceof IndexNode) {
2061             return true;
2062         } else if (isDestructuringLhs(init)) {
2063             verifyDestructuringAssignmentPattern(init, contextString);
2064             return true;
2065         } else {
2066             return false;
2067         }
2068     }
2069 
2070     @SuppressWarnings("fallthrough")
2071     private boolean lookaheadIsLetDeclaration(final boolean ofContextualKeyword) {
2072         assert type == LET;
2073         for (int i = 1;; i++) {
2074             final TokenType t = T(k + i);
2075             switch (t) {
2076             case EOL:
2077             case COMMENT:
2078                 continue;
2079             case IDENT:
2080                 if (ofContextualKeyword && isES6() && "of".equals(getValue(getToken(k + i)))) {
2081                     return false;
2082                 }
2083                 // fall through
2084             case LBRACKET:
2085             case LBRACE:
2086                 return true;
2087             default:
2088                 // accept future strict tokens in non-strict mode (including LET)
2089                 if (!isStrictMode && t.getKind() == TokenKind.FUTURESTRICT) {
2090                     return true;
2091                 }
2092                 return false;
2093             }
2094         }
2095     }
2096 
2097     /**
2098      * ...IterationStatement :
2099      *           ...
2100      *           while ( Expression ) Statement
2101      *           ...
2102      *
2103      * See 12.6
2104      *
2105      * Parse while statement.
2106      */
2107     private void whileStatement() {
2108         // Capture WHILE token.
2109         final long whileToken = token;
2110         final int whileLine = line;
2111         // WHILE tested in caller.
2112         next();
2113 
2114         final ParserContextLoopNode whileNode = new ParserContextLoopNode();
2115         lc.push(whileNode);
2116 
2117         JoinPredecessorExpression test = null;
2118         Block body = null;
2119 
2120         try {
2121             expect(LPAREN);
2122             test = joinPredecessorExpression();
2123             expect(RPAREN);
2124             body = getStatement();
2125         } finally {
2126             lc.pop(whileNode);
2127         }
2128 
2129         if (body != null) {
2130             appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
2131         }
2132     }
2133 
2134     /**
2135      * ...IterationStatement :
2136      *           ...
2137      *           do Statement while( Expression ) ;
2138      *           ...
2139      *
2140      * See 12.6
2141      *
2142      * Parse DO WHILE statement.
2143      */
2144     private void doStatement() {
2145         // Capture DO token.
2146         final long doToken = token;
2147         int doLine = 0;
2148         // DO tested in the caller.
2149         next();
2150 
2151         final ParserContextLoopNode doWhileNode = new ParserContextLoopNode();
2152         lc.push(doWhileNode);
2153 
2154         Block body = null;
2155         JoinPredecessorExpression test = null;
2156 
2157         try {
2158            // Get DO body.
2159             body = getStatement();
2160 
2161             expect(WHILE);
2162             expect(LPAREN);
2163             doLine = line;
2164             test = joinPredecessorExpression();
2165             expect(RPAREN);
2166 
2167             if (type == SEMICOLON) {
2168                 endOfLine();
2169             }
2170         } finally {
2171             lc.pop(doWhileNode);
2172         }
2173 
2174         appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
2175     }
2176 
2177     /**
2178      * ContinueStatement :
2179      *      continue Identifier? ; // [no LineTerminator here]
2180      *
2181      * See 12.7
2182      *
2183      * Parse CONTINUE statement.
2184      */
2185     private void continueStatement() {
2186         // Capture CONTINUE token.
2187         final int  continueLine  = line;
2188         final long continueToken = token;
2189         // CONTINUE tested in caller.
2190         nextOrEOL();
2191 
2192         ParserContextLabelNode labelNode = null;
2193 
2194         // SEMICOLON or label.
2195         switch (type) {
2196         case RBRACE:
2197         case SEMICOLON:
2198         case EOL:
2199         case EOF:
2200             break;
2201 
2202         default:
2203             final IdentNode ident = getIdent();
2204             labelNode = lc.findLabel(ident.getName());
2205 
2206             if (labelNode == null) {
2207                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
2208             }
2209 
2210             break;
2211         }
2212 
2213         final String labelName = labelNode == null ? null : labelNode.getLabelName();
2214         final ParserContextLoopNode targetNode = lc.getContinueTo(labelName);
2215 
2216         if (targetNode == null) {
2217             throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
2218         }
2219 
2220         endOfLine();
2221 
2222         // Construct and add CONTINUE node.
2223         appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
2224     }
2225 
2226     /**
2227      * BreakStatement :
2228      *      break Identifier? ; // [no LineTerminator here]
2229      *
2230      * See 12.8
2231      *
2232      */
2233     private void breakStatement() {
2234         // Capture BREAK token.
2235         final int  breakLine  = line;
2236         final long breakToken = token;
2237         // BREAK tested in caller.
2238         nextOrEOL();
2239 
2240         ParserContextLabelNode labelNode = null;
2241 
2242         // SEMICOLON or label.
2243         switch (type) {
2244         case RBRACE:
2245         case SEMICOLON:
2246         case EOL:
2247         case EOF:
2248             break;
2249 
2250         default:
2251             final IdentNode ident = getIdent();
2252             labelNode = lc.findLabel(ident.getName());
2253 
2254             if (labelNode == null) {
2255                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
2256             }
2257 
2258             break;
2259         }
2260 
2261         //either an explicit label - then get its node or just a "break" - get first breakable
2262         //targetNode is what we are breaking out from.
2263         final String labelName = labelNode == null ? null : labelNode.getLabelName();
2264         final ParserContextBreakableNode targetNode = lc.getBreakable(labelName);
2265         if (targetNode == null) {
2266             throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
2267         }
2268 
2269         endOfLine();
2270 
2271         // Construct and add BREAK node.
2272         appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
2273     }
2274 
2275     /**
2276      * ReturnStatement :
2277      *      return Expression? ; // [no LineTerminator here]
2278      *
2279      * See 12.9
2280      *
2281      * Parse RETURN statement.
2282      */
2283     private void returnStatement() {
2284         // check for return outside function
2285         if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT || lc.getCurrentFunction().getKind() == FunctionNode.Kind.MODULE) {
2286             throw error(AbstractParser.message("invalid.return"));
2287         }
2288 
2289         // Capture RETURN token.
2290         final int  returnLine  = line;
2291         final long returnToken = token;
2292         // RETURN tested in caller.
2293         nextOrEOL();
2294 
2295         Expression expression = null;
2296 
2297         // SEMICOLON or expression.
2298         switch (type) {
2299         case RBRACE:
2300         case SEMICOLON:
2301         case EOL:
2302         case EOF:
2303             break;
2304 
2305         default:
2306             expression = expression();
2307             break;
2308         }
2309 
2310         endOfLine();
2311 
2312         // Construct and add RETURN node.
2313         appendStatement(new ReturnNode(returnLine, returnToken, finish, expression));
2314     }
2315 
2316     /**
2317      * Parse YieldExpression.
2318      *
2319      * YieldExpression[In] :
2320      *   yield
2321      *   yield [no LineTerminator here] AssignmentExpression[?In, Yield]
2322      *   yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
2323      */
2324     @SuppressWarnings("fallthrough")
2325     private Expression yieldExpression(final boolean noIn) {
2326         assert inGeneratorFunction();
2327         // Capture YIELD token.
2328         long yieldToken = token;
2329         // YIELD tested in caller.
2330         assert type == YIELD;
2331         nextOrEOL();
2332 
2333         Expression expression = null;
2334 
2335         boolean yieldAsterisk = false;
2336         if (type == MUL) {
2337             yieldAsterisk = true;
2338             yieldToken = Token.recast(yieldToken, YIELD_STAR);
2339             next();
2340         }
2341 
2342         switch (type) {
2343         case RBRACE:
2344         case SEMICOLON:
2345         case EOL:
2346         case EOF:
2347         case COMMARIGHT:
2348         case RPAREN:
2349         case RBRACKET:
2350         case COLON:
2351             if (!yieldAsterisk) {
2352                 // treat (yield) as (yield void 0)
2353                 expression = newUndefinedLiteral(yieldToken, finish);
2354                 if (type == EOL) {
2355                     next();
2356                 }
2357                 break;
2358             } else {
2359                 // AssignmentExpression required, fall through
2360             }
2361 
2362         default:
2363             expression = assignmentExpression(noIn);
2364             break;
2365         }
2366 
2367         // Construct and add YIELD node.
2368         return new UnaryNode(yieldToken, expression);
2369     }
2370 
2371     private static UnaryNode newUndefinedLiteral(final long token, final int finish) {
2372         return new UnaryNode(Token.recast(token, VOID), LiteralNode.newInstance(token, finish, 0));
2373     }
2374 
2375     /**
2376      * WithStatement :
2377      *      with ( Expression ) Statement
2378      *
2379      * See 12.10
2380      *
2381      * Parse WITH statement.
2382      */
2383     private void withStatement() {
2384         // Capture WITH token.
2385         final int  withLine  = line;
2386         final long withToken = token;
2387         // WITH tested in caller.
2388         next();
2389 
2390         // ECMA 12.10.1 strict mode restrictions
2391         if (isStrictMode) {
2392             throw error(AbstractParser.message("strict.no.with"), withToken);
2393         }
2394 
2395         expect(LPAREN);
2396         final Expression expression = expression();
2397         expect(RPAREN);
2398         final Block body = getStatement();
2399 
2400         appendStatement(new WithNode(withLine, withToken, finish, expression, body));
2401     }
2402 
2403     /**
2404      * SwitchStatement :
2405      *      switch ( Expression ) CaseBlock
2406      *
2407      * CaseBlock :
2408      *      { CaseClauses? }
2409      *      { CaseClauses? DefaultClause CaseClauses }
2410      *
2411      * CaseClauses :
2412      *      CaseClause
2413      *      CaseClauses CaseClause
2414      *
2415      * CaseClause :
2416      *      case Expression : StatementList?
2417      *
2418      * DefaultClause :
2419      *      default : StatementList?
2420      *
2421      * See 12.11
2422      *
2423      * Parse SWITCH statement.
2424      */
2425     private void switchStatement() {
2426         final int  switchLine  = line;
2427         final long switchToken = token;
2428 
2429         // Block to capture variables declared inside the switch statement.
2430         final ParserContextBlockNode switchBlock = newBlock();
2431 
2432         // SWITCH tested in caller.
2433         next();
2434 
2435         // Create and add switch statement.
2436         final ParserContextSwitchNode switchNode = new ParserContextSwitchNode();
2437         lc.push(switchNode);
2438 
2439         CaseNode defaultCase = null;
2440         // Prepare to accumulate cases.
2441         final List<CaseNode> cases = new ArrayList<>();
2442 
2443         Expression expression = null;
2444 
2445         try {
2446             expect(LPAREN);
2447             expression = expression();
2448             expect(RPAREN);
2449 
2450             expect(LBRACE);
2451 
2452 
2453             while (type != RBRACE) {
2454                 // Prepare for next case.
2455                 Expression caseExpression = null;
2456                 final long caseToken = token;
2457 
2458                 switch (type) {
2459                 case CASE:
2460                     next();
2461                     caseExpression = expression();
2462                     break;
2463 
2464                 case DEFAULT:
2465                     if (defaultCase != null) {
2466                         throw error(AbstractParser.message("duplicate.default.in.switch"));
2467                     }
2468                     next();
2469                     break;
2470 
2471                 default:
2472                     // Force an error.
2473                     expect(CASE);
2474                     break;
2475                 }
2476 
2477                 expect(COLON);
2478 
2479                 // Get CASE body.
2480                 final Block statements = getBlock(false); // TODO: List<Statement> statements = caseStatementList();
2481                 final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
2482 
2483                 if (caseExpression == null) {
2484                     defaultCase = caseNode;
2485                 }
2486 
2487                 cases.add(caseNode);
2488             }
2489 
2490             next();
2491         } finally {
2492             lc.pop(switchNode);
2493             restoreBlock(switchBlock);
2494         }
2495 
2496         final SwitchNode switchStatement = new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase);
2497         appendStatement(new BlockStatement(switchLine, new Block(switchToken, finish, switchBlock.getFlags() | Block.IS_SYNTHETIC | Block.IS_SWITCH_BLOCK, switchStatement)));
2498     }
2499 
2500     /**
2501      * LabelledStatement :
2502      *      Identifier : Statement
2503      *
2504      * See 12.12
2505      *
2506      * Parse label statement.
2507      */
2508     private void labelStatement() {
2509         // Capture label token.
2510         final long labelToken = token;
2511         // Get label ident.
2512         final IdentNode ident = getIdent();
2513 
2514         expect(COLON);
2515 
2516         if (lc.findLabel(ident.getName()) != null) {
2517             throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
2518         }
2519 
2520         final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName());
2521         Block body = null;
2522         try {
2523             lc.push(labelNode);
2524             body = getStatement(true);
2525         } finally {
2526             assert lc.peek() instanceof ParserContextLabelNode;
2527             lc.pop(labelNode);
2528         }
2529 
2530         appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
2531     }
2532 
2533     /**
2534      * ThrowStatement :
2535      *      throw Expression ; // [no LineTerminator here]
2536      *
2537      * See 12.13
2538      *
2539      * Parse throw statement.
2540      */
2541     private void throwStatement() {
2542         // Capture THROW token.
2543         final int  throwLine  = line;
2544         final long throwToken = token;
2545         // THROW tested in caller.
2546         nextOrEOL();
2547 
2548         Expression expression = null;
2549 
2550         // SEMICOLON or expression.
2551         switch (type) {
2552         case RBRACE:
2553         case SEMICOLON:
2554         case EOL:
2555             break;
2556 
2557         default:
2558             expression = expression();
2559             break;
2560         }
2561 
2562         if (expression == null) {
2563             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2564         }
2565 
2566         endOfLine();
2567 
2568         appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
2569     }
2570 
2571     /**
2572      * TryStatement :
2573      *      try Block Catch
2574      *      try Block Finally
2575      *      try Block Catch Finally
2576      *
2577      * Catch :
2578      *      catch( Identifier if Expression ) Block
2579      *      catch( Identifier ) Block
2580      *
2581      * Finally :
2582      *      finally Block
2583      *
2584      * See 12.14
2585      *
2586      * Parse TRY statement.
2587      */
2588     private void tryStatement() {
2589         // Capture TRY token.
2590         final int  tryLine  = line;
2591         final long tryToken = token;
2592         // TRY tested in caller.
2593         next();
2594 
2595         // Container block needed to act as target for labeled break statements
2596         final int startLine = line;
2597         final ParserContextBlockNode outer = newBlock();
2598         // Create try.
2599 
2600         try {
2601             final Block       tryBody     = getBlock(true);
2602             final List<Block> catchBlocks = new ArrayList<>();
2603 
2604             while (type == CATCH) {
2605                 final int  catchLine  = line;
2606                 final long catchToken = token;
2607                 next();
2608                 expect(LPAREN);
2609 
2610                 // ES6 catch parameter can be a BindingIdentifier or a BindingPattern

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