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                 // FIXME: ES6 catch parameter can be a BindingIdentifier or a BindingPattern
2611                 // We need to generalize this here!
2612                 // http://www.ecma-international.org/ecma-262/6.0/
2613                 final IdentNode exception = getIdent();
2614 









2615                 // ECMA 12.4.1 strict mode restrictions
2616                 verifyStrictIdent(exception, "catch argument");


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