1 /*
   2  * Copyright (c) 2010, 2017, 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         checkEscapedKeyword(ident);
1476     }
1477 
1478     /**
1479      * Make sure that in strict mode, the identifier name used is allowed.
1480      *
1481      * @param ident         Identifier that is verified
1482      * @param contextString String used in error message to give context to the user
1483      */
1484     private void verifyStrictIdent(final IdentNode ident, final String contextString) {
1485         if (isStrictMode) {
1486             switch (ident.getName()) {
1487             case "eval":
1488             case "arguments":
1489                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1490             default:
1491                 break;
1492             }
1493 
1494             if (ident.isFutureStrictName()) {
1495                 throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1496             }
1497         }
1498     }
1499 
1500     /**
1501      * ES6 11.6.2: A code point in a ReservedWord cannot be expressed by a | UnicodeEscapeSequence.
1502      */
1503     private void checkEscapedKeyword(final IdentNode ident) {
1504         if (isES6() && ident.containsEscapes()) {
1505             final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length());
1506             if (tokenType != IDENT && !(tokenType.getKind() == TokenKind.FUTURESTRICT && !isStrictMode)) {
1507                 throw error(AbstractParser.message("keyword.escaped.character"), ident.getToken());
1508             }
1509         }
1510     }
1511 
1512     /*
1513      * VariableStatement :
1514      *      var VariableDeclarationList ;
1515      *
1516      * VariableDeclarationList :
1517      *      VariableDeclaration
1518      *      VariableDeclarationList , VariableDeclaration
1519      *
1520      * VariableDeclaration :
1521      *      Identifier Initializer?
1522      *
1523      * Initializer :
1524      *      = AssignmentExpression
1525      *
1526      * See 12.2
1527      *
1528      * Parse a VAR statement.
1529      * @param isStatement True if a statement (not used in a FOR.)
1530      */
1531     private void variableStatement(final TokenType varType) {
1532         variableDeclarationList(varType, true, -1);
1533     }
1534 
1535     private static final class ForVariableDeclarationListResult {
1536         /** First missing const or binding pattern initializer. */
1537         Expression missingAssignment;
1538         /** First declaration with an initializer. */
1539         long declarationWithInitializerToken;
1540         /** Destructuring assignments. */
1541         Expression init;
1542         Expression firstBinding;
1543         Expression secondBinding;
1544 
1545         void recordMissingAssignment(final Expression binding) {
1546             if (missingAssignment == null) {
1547                 missingAssignment = binding;
1548             }
1549         }
1550 
1551         void recordDeclarationWithInitializer(final long token) {
1552             if (declarationWithInitializerToken == 0L) {
1553                 declarationWithInitializerToken = token;
1554             }
1555         }
1556 
1557         void addBinding(final Expression binding) {
1558             if (firstBinding == null) {
1559                 firstBinding = binding;
1560             } else if (secondBinding == null)  {
1561                 secondBinding = binding;
1562             }
1563             // ignore the rest
1564         }
1565 
1566         void addAssignment(final Expression assignment) {
1567             if (init == null) {
1568                 init = assignment;
1569             } else {
1570                 init = new BinaryNode(Token.recast(init.getToken(), COMMARIGHT), init, assignment);
1571             }
1572         }
1573     }
1574 
1575     /**
1576      * @param isStatement {@code true} if a VariableStatement, {@code false} if a {@code for} loop VariableDeclarationList
1577      */
1578     private ForVariableDeclarationListResult variableDeclarationList(final TokenType varType, final boolean isStatement, final int sourceOrder) {
1579         // VAR tested in caller.
1580         assert varType == VAR || varType == LET || varType == CONST;
1581         final int varLine = line;
1582         final long varToken = token;
1583 
1584         next();
1585 
1586         int varFlags = 0;
1587         if (varType == LET) {
1588             varFlags |= VarNode.IS_LET;
1589         } else if (varType == CONST) {
1590             varFlags |= VarNode.IS_CONST;
1591         }
1592 
1593         final ForVariableDeclarationListResult forResult = isStatement ? null : new ForVariableDeclarationListResult();
1594         while (true) {
1595             // Get name of var.
1596             if (type == YIELD && inGeneratorFunction()) {
1597                 expect(IDENT);
1598             }
1599 
1600             final String contextString = "variable name";
1601             final Expression binding = bindingIdentifierOrPattern(contextString);
1602             final boolean isDestructuring = !(binding instanceof IdentNode);
1603             if (isDestructuring) {
1604                 final int finalVarFlags = varFlags;
1605                 verifyDestructuringBindingPattern(binding, new Consumer<IdentNode>() {
1606                     @Override
1607                     public void accept(final IdentNode identNode) {
1608                         verifyIdent(identNode, contextString);
1609                         if (!env._parse_only) {
1610                             // don't bother adding a variable if we are just parsing!
1611                             final VarNode var = new VarNode(varLine, varToken, sourceOrder, identNode.getFinish(), identNode.setIsDeclaredHere(), null, finalVarFlags);
1612                             appendStatement(var);
1613                         }
1614                     }
1615                 });
1616             }
1617 
1618             // Assume no init.
1619             Expression init = null;
1620 
1621             // Look for initializer assignment.
1622             if (type == ASSIGN) {
1623                 if (!isStatement) {
1624                     forResult.recordDeclarationWithInitializer(varToken);
1625                 }
1626                 next();
1627 
1628                 // Get initializer expression. Suppress IN if not statement.
1629                 if (!isDestructuring) {
1630                     defaultNames.push(binding);
1631                 }
1632                 try {
1633                     init = assignmentExpression(!isStatement);
1634                 } finally {
1635                     if (!isDestructuring) {
1636                         defaultNames.pop();
1637                     }
1638                 }
1639             } else if (isStatement) {
1640                 if (isDestructuring) {
1641                     throw error(AbstractParser.message("missing.destructuring.assignment"), token);
1642                 } else if (varType == CONST) {
1643                     throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)binding).getName()));
1644                 }
1645                 // else, if we are in a for loop, delay checking until we know the kind of loop
1646             }
1647 
1648             if (!isDestructuring) {
1649                 assert init != null || varType != CONST || !isStatement;
1650                 final IdentNode ident = (IdentNode)binding;
1651                 if (!isStatement && ident.getName().equals("let")) {
1652                     throw error(AbstractParser.message("let.binding.for")); //ES6 13.7.5.1
1653                 }
1654                 // Only set declaration flag on lexically scoped let/const as it adds runtime overhead.
1655                 final IdentNode name = varType == LET || varType == CONST ? ident.setIsDeclaredHere() : ident;
1656                 if (!isStatement) {
1657                     if (init == null && varType == CONST) {
1658                         forResult.recordMissingAssignment(name);
1659                     }
1660                     forResult.addBinding(new IdentNode(name));
1661                 }
1662                 final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name, init, varFlags);
1663                 appendStatement(var);
1664             } else {
1665                 assert init != null || !isStatement;
1666                 if (init != null) {
1667                     final Expression assignment = verifyAssignment(Token.recast(varToken, ASSIGN), binding, init);
1668                     if (isStatement) {
1669                         appendStatement(new ExpressionStatement(varLine, assignment.getToken(), finish, assignment, varType));
1670                     } else {
1671                         forResult.addAssignment(assignment);
1672                         forResult.addBinding(assignment);
1673                     }
1674                 } else if (!isStatement) {
1675                     forResult.recordMissingAssignment(binding);
1676                     forResult.addBinding(binding);
1677                 }
1678             }
1679 
1680             if (type != COMMARIGHT) {
1681                 break;
1682             }
1683             next();
1684         }
1685 
1686         // If is a statement then handle end of line.
1687         if (isStatement) {
1688             endOfLine();
1689         }
1690 
1691         return forResult;
1692     }
1693 
1694     private boolean isBindingIdentifier() {
1695         return type == IDENT || isNonStrictModeIdent();
1696     }
1697 
1698     private IdentNode bindingIdentifier(final String contextString) {
1699         final IdentNode name = getIdent();
1700         verifyIdent(name, contextString);
1701         return name;
1702     }
1703 
1704     private Expression bindingPattern() {
1705         if (type == LBRACKET) {
1706             return arrayLiteral();
1707         } else if (type == LBRACE) {
1708             return objectLiteral();
1709         } else {
1710             throw error(AbstractParser.message("expected.binding"));
1711         }
1712     }
1713 
1714     private Expression bindingIdentifierOrPattern(final String contextString) {
1715         if (isBindingIdentifier() || !isES6()) {
1716             return bindingIdentifier(contextString);
1717         } else {
1718             return bindingPattern();
1719         }
1720     }
1721 
1722     private abstract class VerifyDestructuringPatternNodeVisitor extends NodeVisitor<LexicalContext> {
1723         VerifyDestructuringPatternNodeVisitor(final LexicalContext lc) {
1724             super(lc);
1725         }
1726 
1727         @Override
1728         public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
1729             if (literalNode.isArray()) {
1730                 if (((LiteralNode.ArrayLiteralNode)literalNode).hasSpread() && ((LiteralNode.ArrayLiteralNode)literalNode).hasTrailingComma()) {
1731                     throw error("Rest element must be last", literalNode.getElementExpressions().get(literalNode.getElementExpressions().size() - 1).getToken());
1732                 }
1733                 boolean restElement = false;
1734                 for (final Expression element : literalNode.getElementExpressions()) {
1735                     if (element != null) {
1736                         if (restElement) {
1737                             throw error("Unexpected element after rest element", element.getToken());
1738                         }
1739                         if (element.isTokenType(SPREAD_ARRAY)) {
1740                             restElement = true;
1741                             final Expression lvalue = ((UnaryNode) element).getExpression();
1742                             verifySpreadElement(lvalue);
1743                         }
1744                         element.accept(this);
1745                     }
1746                 }
1747                 return false;
1748             } else {
1749                 return enterDefault(literalNode);
1750             }
1751         }
1752 
1753         protected abstract void verifySpreadElement(Expression lvalue);
1754 
1755         @Override
1756         public boolean enterObjectNode(final ObjectNode objectNode) {
1757             return true;
1758         }
1759 
1760         @Override
1761         public boolean enterPropertyNode(final PropertyNode propertyNode) {
1762             if (propertyNode.getValue() != null) {
1763                 propertyNode.getValue().accept(this);
1764                 return false;
1765             } else {
1766                 return enterDefault(propertyNode);
1767             }
1768         }
1769 
1770         @Override
1771         public boolean enterBinaryNode(final BinaryNode binaryNode) {
1772             if (binaryNode.isTokenType(ASSIGN)) {
1773                 binaryNode.lhs().accept(this);
1774                 // Initializer(rhs) can be any AssignmentExpression
1775                 return false;
1776             } else {
1777                 return enterDefault(binaryNode);
1778             }
1779         }
1780 
1781         @Override
1782         public boolean enterUnaryNode(final UnaryNode unaryNode) {
1783             if (unaryNode.isTokenType(SPREAD_ARRAY)) {
1784                 // rest element
1785                 return true;
1786             } else {
1787                 return enterDefault(unaryNode);
1788             }
1789         }
1790     }
1791 
1792     /**
1793      * Verify destructuring variable declaration binding pattern and extract bound variable declarations.
1794      */
1795     private void verifyDestructuringBindingPattern(final Expression pattern, final Consumer<IdentNode> identifierCallback) {
1796         assert (pattern instanceof BinaryNode && pattern.isTokenType(ASSIGN)) ||
1797                 pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
1798         pattern.accept(new VerifyDestructuringPatternNodeVisitor(new LexicalContext()) {
1799             @Override
1800             protected void verifySpreadElement(final Expression lvalue) {
1801                 if (lvalue instanceof IdentNode) {
1802                     // checked in identifierCallback
1803                 } else if (isDestructuringLhs(lvalue)) {
1804                     verifyDestructuringBindingPattern(lvalue, identifierCallback);
1805                 } else {
1806                     throw error("Expected a valid binding identifier", lvalue.getToken());
1807                 }
1808             }
1809 
1810             @Override
1811             public boolean enterIdentNode(final IdentNode identNode) {
1812                 identifierCallback.accept(identNode);
1813                 return false;
1814             }
1815 
1816             @Override
1817             protected boolean enterDefault(final Node node) {
1818                 throw error(String.format("unexpected node in BindingPattern: %s", node));
1819             }
1820         });
1821     }
1822 
1823     /**
1824      * EmptyStatement :
1825      *      ;
1826      *
1827      * See 12.3
1828      *
1829      * Parse an empty statement.
1830      */
1831     private void emptyStatement() {
1832         if (env._empty_statements) {
1833             appendStatement(new EmptyNode(line, token, Token.descPosition(token) + Token.descLength(token)));
1834         }
1835 
1836         // SEMICOLON checked in caller.
1837         next();
1838     }
1839 
1840     /**
1841      * ExpressionStatement :
1842      *      Expression ; // [lookahead ~({ or  function )]
1843      *
1844      * See 12.4
1845      *
1846      * Parse an expression used in a statement block.
1847      */
1848     private void expressionStatement() {
1849         // Lookahead checked in caller.
1850         final int  expressionLine  = line;
1851         final long expressionToken = token;
1852 
1853         // Get expression and add as statement.
1854         final Expression expression = expression();
1855 
1856         if (expression != null) {
1857             final ExpressionStatement expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
1858             appendStatement(expressionStatement);
1859         } else {
1860             expect(null);
1861         }
1862 
1863         endOfLine();
1864     }
1865 
1866     /**
1867      * IfStatement :
1868      *      if ( Expression ) Statement else Statement
1869      *      if ( Expression ) Statement
1870      *
1871      * See 12.5
1872      *
1873      * Parse an IF statement.
1874      */
1875     private void ifStatement() {
1876         // Capture IF token.
1877         final int  ifLine  = line;
1878         final long ifToken = token;
1879          // IF tested in caller.
1880         next();
1881 
1882         expect(LPAREN);
1883         final Expression test = expression();
1884         expect(RPAREN);
1885         final Block pass = getStatement();
1886 
1887         Block fail = null;
1888         if (type == ELSE) {
1889             next();
1890             fail = getStatement();
1891         }
1892 
1893         appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1894     }
1895 
1896     /**
1897      * ... IterationStatement:
1898      *           ...
1899      *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1900      *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1901      *           for ( LeftHandSideExpression in Expression ) Statement
1902      *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1903      *
1904      * See 12.6
1905      *
1906      * Parse a FOR statement.
1907      */
1908     @SuppressWarnings("fallthrough")
1909     private void forStatement() {
1910         final long forToken = token;
1911         final int forLine = line;
1912         // start position of this for statement. This is used
1913         // for sort order for variables declared in the initializer
1914         // part of this 'for' statement (if any).
1915         final int forStart = Token.descPosition(forToken);
1916         // When ES6 for-let is enabled we create a container block to capture the LET.
1917         final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1918 
1919         // Create FOR node, capturing FOR token.
1920         final ParserContextLoopNode forNode = new ParserContextLoopNode();
1921         lc.push(forNode);
1922         Block body = null;
1923         Expression init = null;
1924         JoinPredecessorExpression test = null;
1925         JoinPredecessorExpression modify = null;
1926         ForVariableDeclarationListResult varDeclList = null;
1927 
1928         int flags = 0;
1929         boolean isForOf = false;
1930 
1931         try {
1932             // FOR tested in caller.
1933             next();
1934 
1935             // Nashorn extension: for each expression.
1936             // iterate property values rather than property names.
1937             if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1938                 flags |= ForNode.IS_FOR_EACH;
1939                 next();
1940             }
1941 
1942             expect(LPAREN);
1943 
1944             TokenType varType = null;
1945             switch (type) {
1946             case VAR:
1947                 // Var declaration captured in for outer block.
1948                 varDeclList = variableDeclarationList(varType = type, false, forStart);
1949                 break;
1950             case SEMICOLON:
1951                 break;
1952             default:
1953                 if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(true) || type == CONST)) {
1954                     flags |= ForNode.PER_ITERATION_SCOPE;
1955                     // LET/CONST declaration captured in container block created above.
1956                     varDeclList = variableDeclarationList(varType = type, false, forStart);
1957                     break;
1958                 }
1959                 if (env._const_as_var && type == CONST) {
1960                     // Var declaration captured in for outer block.
1961                     varDeclList = variableDeclarationList(varType = TokenType.VAR, false, forStart);
1962                     break;
1963                 }
1964 
1965                 init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1966                 break;
1967             }
1968 
1969             switch (type) {
1970             case SEMICOLON:
1971                 // for (init; test; modify)
1972                 if (varDeclList != null) {
1973                     assert init == null;
1974                     init = varDeclList.init;
1975                     // late check for missing assignment, now we know it's a for (init; test; modify) loop
1976                     if (varDeclList.missingAssignment != null) {
1977                         if (varDeclList.missingAssignment instanceof IdentNode) {
1978                             throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)varDeclList.missingAssignment).getName()));
1979                         } else {
1980                             throw error(AbstractParser.message("missing.destructuring.assignment"), varDeclList.missingAssignment.getToken());
1981                         }
1982                     }
1983                 }
1984 
1985                 // for each (init; test; modify) is invalid
1986                 if ((flags & ForNode.IS_FOR_EACH) != 0) {
1987                     throw error(AbstractParser.message("for.each.without.in"), token);
1988                 }
1989 
1990                 expect(SEMICOLON);
1991                 if (type != SEMICOLON) {
1992                     test = joinPredecessorExpression();
1993                 }
1994                 expect(SEMICOLON);
1995                 if (type != RPAREN) {
1996                     modify = joinPredecessorExpression();
1997                 }
1998                 break;
1999 
2000             case IDENT:
2001                 if (env._es6 && "of".equals(getValue())) {
2002                     isForOf = true;
2003                     // fall through
2004                 } else {
2005                     expect(SEMICOLON); // fail with expected message
2006                     break;
2007                 }
2008             case IN:
2009                 flags |= isForOf ? ForNode.IS_FOR_OF : ForNode.IS_FOR_IN;
2010                 test = new JoinPredecessorExpression();
2011                 if (varDeclList != null) {
2012                     // for (var|let|const ForBinding in|of expression)
2013                     if (varDeclList.secondBinding != null) {
2014                         // for (var i, j in obj) is invalid
2015                         throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), varDeclList.secondBinding.getToken());
2016                     }
2017                     if (varDeclList.declarationWithInitializerToken != 0 && (isStrictMode || type != TokenType.IN || varType != VAR || varDeclList.init != null)) {
2018                         // ES5 legacy: for (var i = AssignmentExpressionNoIn in Expression)
2019                         // Invalid in ES6, but allow it in non-strict mode if no ES6 features used,
2020                         // i.e., error if strict, for-of, let/const, or destructuring
2021                         throw error(AbstractParser.message("for.in.loop.initializer", isForOf ? "of" : "in"), varDeclList.declarationWithInitializerToken);
2022                     }
2023                     init = varDeclList.firstBinding;
2024                     assert init instanceof IdentNode || isDestructuringLhs(init);
2025                 } else {
2026                     // for (expr in obj)
2027                     assert init != null : "for..in/of init expression can not be null here";
2028 
2029                     // check if initial expression is a valid L-value
2030                     if (!checkValidLValue(init, isForOf ? "for-of iterator" : "for-in iterator")) {
2031                         throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
2032                     }
2033                 }
2034 
2035                 next();
2036 
2037                 // For-of only allows AssignmentExpression.
2038                 modify = isForOf ? new JoinPredecessorExpression(assignmentExpression(false)) : joinPredecessorExpression();
2039                 break;
2040 
2041             default:
2042                 expect(SEMICOLON);
2043                 break;
2044             }
2045 
2046             expect(RPAREN);
2047 
2048             // Set the for body.
2049             body = getStatement();
2050         } finally {
2051             lc.pop(forNode);
2052 
2053             for (final Statement var : forNode.getStatements()) {
2054                 assert var instanceof VarNode;
2055                 appendStatement(var);
2056             }
2057             if (body != null) {
2058                 appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
2059             }
2060             if (outer != null) {
2061                 restoreBlock(outer);
2062                 if (body != null) {
2063                     List<Statement> statements = new ArrayList<>();
2064                     for (final Statement var : outer.getStatements()) {
2065                         if(var instanceof VarNode && !((VarNode)var).isBlockScoped()) {
2066                             appendStatement(var);
2067                         }else {
2068                             statements.add(var);
2069                         }
2070                     }
2071                     appendStatement(new BlockStatement(forLine, new Block(
2072                                     outer.getToken(),
2073                                     body.getFinish(),
2074                                     statements)));
2075                 }
2076             }
2077         }
2078     }
2079 
2080     private boolean checkValidLValue(final Expression init, final String contextString) {
2081         if (init instanceof IdentNode) {
2082             if (!checkIdentLValue((IdentNode)init)) {
2083                 return false;
2084             }
2085             verifyIdent((IdentNode)init, contextString);
2086             return true;
2087         } else if (init instanceof AccessNode || init instanceof IndexNode) {
2088             return true;
2089         } else if (isDestructuringLhs(init)) {
2090             verifyDestructuringAssignmentPattern(init, contextString);
2091             return true;
2092         } else {
2093             return false;
2094         }
2095     }
2096 
2097     @SuppressWarnings("fallthrough")
2098     private boolean lookaheadIsLetDeclaration(final boolean ofContextualKeyword) {
2099         assert type == LET;
2100         for (int i = 1;; i++) {
2101             final TokenType t = T(k + i);
2102             switch (t) {
2103             case EOL:
2104             case COMMENT:
2105                 continue;
2106             case IDENT:
2107                 if (ofContextualKeyword && isES6() && "of".equals(getValue(getToken(k + i)))) {
2108                     return false;
2109                 }
2110                 // fall through
2111             case LBRACKET:
2112             case LBRACE:
2113                 return true;
2114             default:
2115                 // accept future strict tokens in non-strict mode (including LET)
2116                 if (!isStrictMode && t.getKind() == TokenKind.FUTURESTRICT) {
2117                     return true;
2118                 }
2119                 return false;
2120             }
2121         }
2122     }
2123 
2124     /**
2125      * ...IterationStatement :
2126      *           ...
2127      *           while ( Expression ) Statement
2128      *           ...
2129      *
2130      * See 12.6
2131      *
2132      * Parse while statement.
2133      */
2134     private void whileStatement() {
2135         // Capture WHILE token.
2136         final long whileToken = token;
2137         final int whileLine = line;
2138         // WHILE tested in caller.
2139         next();
2140 
2141         final ParserContextLoopNode whileNode = new ParserContextLoopNode();
2142         lc.push(whileNode);
2143 
2144         JoinPredecessorExpression test = null;
2145         Block body = null;
2146 
2147         try {
2148             expect(LPAREN);
2149             test = joinPredecessorExpression();
2150             expect(RPAREN);
2151             body = getStatement();
2152         } finally {
2153             lc.pop(whileNode);
2154         }
2155 
2156         if (body != null) {
2157             appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
2158         }
2159     }
2160 
2161     /**
2162      * ...IterationStatement :
2163      *           ...
2164      *           do Statement while( Expression ) ;
2165      *           ...
2166      *
2167      * See 12.6
2168      *
2169      * Parse DO WHILE statement.
2170      */
2171     private void doStatement() {
2172         // Capture DO token.
2173         final long doToken = token;
2174         int doLine = 0;
2175         // DO tested in the caller.
2176         next();
2177 
2178         final ParserContextLoopNode doWhileNode = new ParserContextLoopNode();
2179         lc.push(doWhileNode);
2180 
2181         Block body = null;
2182         JoinPredecessorExpression test = null;
2183 
2184         try {
2185            // Get DO body.
2186             body = getStatement();
2187 
2188             expect(WHILE);
2189             expect(LPAREN);
2190             doLine = line;
2191             test = joinPredecessorExpression();
2192             expect(RPAREN);
2193 
2194             if (type == SEMICOLON) {
2195                 endOfLine();
2196             }
2197         } finally {
2198             lc.pop(doWhileNode);
2199         }
2200 
2201         appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
2202     }
2203 
2204     /**
2205      * ContinueStatement :
2206      *      continue Identifier? ; // [no LineTerminator here]
2207      *
2208      * See 12.7
2209      *
2210      * Parse CONTINUE statement.
2211      */
2212     private void continueStatement() {
2213         // Capture CONTINUE token.
2214         final int  continueLine  = line;
2215         final long continueToken = token;
2216         // CONTINUE tested in caller.
2217         nextOrEOL();
2218 
2219         ParserContextLabelNode labelNode = null;
2220 
2221         // SEMICOLON or label.
2222         switch (type) {
2223         case RBRACE:
2224         case SEMICOLON:
2225         case EOL:
2226         case EOF:
2227             break;
2228 
2229         default:
2230             final IdentNode ident = getIdent();
2231             labelNode = lc.findLabel(ident.getName());
2232 
2233             if (labelNode == null) {
2234                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
2235             }
2236 
2237             break;
2238         }
2239 
2240         final String labelName = labelNode == null ? null : labelNode.getLabelName();
2241         final ParserContextLoopNode targetNode = lc.getContinueTo(labelName);
2242 
2243         if (targetNode == null) {
2244             throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
2245         }
2246 
2247         endOfLine();
2248 
2249         // Construct and add CONTINUE node.
2250         appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
2251     }
2252 
2253     /**
2254      * BreakStatement :
2255      *      break Identifier? ; // [no LineTerminator here]
2256      *
2257      * See 12.8
2258      *
2259      */
2260     private void breakStatement() {
2261         // Capture BREAK token.
2262         final int  breakLine  = line;
2263         final long breakToken = token;
2264         // BREAK tested in caller.
2265         nextOrEOL();
2266 
2267         ParserContextLabelNode labelNode = null;
2268 
2269         // SEMICOLON or label.
2270         switch (type) {
2271         case RBRACE:
2272         case SEMICOLON:
2273         case EOL:
2274         case EOF:
2275             break;
2276 
2277         default:
2278             final IdentNode ident = getIdent();
2279             labelNode = lc.findLabel(ident.getName());
2280 
2281             if (labelNode == null) {
2282                 throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
2283             }
2284 
2285             break;
2286         }
2287 
2288         //either an explicit label - then get its node or just a "break" - get first breakable
2289         //targetNode is what we are breaking out from.
2290         final String labelName = labelNode == null ? null : labelNode.getLabelName();
2291         final ParserContextBreakableNode targetNode = lc.getBreakable(labelName);
2292 
2293         if( targetNode instanceof ParserContextBlockNode) {
2294             targetNode.setFlag(Block.IS_BREAKABLE);
2295         }
2296 
2297         if (targetNode == null) {
2298             throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
2299         }
2300 
2301         endOfLine();
2302 
2303         // Construct and add BREAK node.
2304         appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
2305     }
2306 
2307     /**
2308      * ReturnStatement :
2309      *      return Expression? ; // [no LineTerminator here]
2310      *
2311      * See 12.9
2312      *
2313      * Parse RETURN statement.
2314      */
2315     private void returnStatement() {
2316         // check for return outside function
2317         if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT || lc.getCurrentFunction().getKind() == FunctionNode.Kind.MODULE) {
2318             throw error(AbstractParser.message("invalid.return"));
2319         }
2320 
2321         // Capture RETURN token.
2322         final int  returnLine  = line;
2323         final long returnToken = token;
2324         // RETURN tested in caller.
2325         nextOrEOL();
2326 
2327         Expression expression = null;
2328 
2329         // SEMICOLON or expression.
2330         switch (type) {
2331         case RBRACE:
2332         case SEMICOLON:
2333         case EOL:
2334         case EOF:
2335             break;
2336 
2337         default:
2338             expression = expression();
2339             break;
2340         }
2341 
2342         endOfLine();
2343 
2344         // Construct and add RETURN node.
2345         appendStatement(new ReturnNode(returnLine, returnToken, finish, expression));
2346     }
2347 
2348     /**
2349      * Parse YieldExpression.
2350      *
2351      * YieldExpression[In] :
2352      *   yield
2353      *   yield [no LineTerminator here] AssignmentExpression[?In, Yield]
2354      *   yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
2355      */
2356     @SuppressWarnings("fallthrough")
2357     private Expression yieldExpression(final boolean noIn) {
2358         assert inGeneratorFunction();
2359         // Capture YIELD token.
2360         long yieldToken = token;
2361         // YIELD tested in caller.
2362         assert type == YIELD;
2363         nextOrEOL();
2364 
2365         Expression expression = null;
2366 
2367         boolean yieldAsterisk = false;
2368         if (type == MUL) {
2369             yieldAsterisk = true;
2370             yieldToken = Token.recast(yieldToken, YIELD_STAR);
2371             next();
2372         }
2373 
2374         switch (type) {
2375         case RBRACE:
2376         case SEMICOLON:
2377         case EOL:
2378         case EOF:
2379         case COMMARIGHT:
2380         case RPAREN:
2381         case RBRACKET:
2382         case COLON:
2383             if (!yieldAsterisk) {
2384                 // treat (yield) as (yield void 0)
2385                 expression = newUndefinedLiteral(yieldToken, finish);
2386                 if (type == EOL) {
2387                     next();
2388                 }
2389                 break;
2390             } else {
2391                 // AssignmentExpression required, fall through
2392             }
2393 
2394         default:
2395             expression = assignmentExpression(noIn);
2396             break;
2397         }
2398 
2399         // Construct and add YIELD node.
2400         return new UnaryNode(yieldToken, expression);
2401     }
2402 
2403     private static UnaryNode newUndefinedLiteral(final long token, final int finish) {
2404         return new UnaryNode(Token.recast(token, VOID), LiteralNode.newInstance(token, finish, 0));
2405     }
2406 
2407     /**
2408      * WithStatement :
2409      *      with ( Expression ) Statement
2410      *
2411      * See 12.10
2412      *
2413      * Parse WITH statement.
2414      */
2415     private void withStatement() {
2416         // Capture WITH token.
2417         final int  withLine  = line;
2418         final long withToken = token;
2419         // WITH tested in caller.
2420         next();
2421 
2422         // ECMA 12.10.1 strict mode restrictions
2423         if (isStrictMode) {
2424             throw error(AbstractParser.message("strict.no.with"), withToken);
2425         }
2426 
2427         expect(LPAREN);
2428         final Expression expression = expression();
2429         expect(RPAREN);
2430         final Block body = getStatement();
2431 
2432         appendStatement(new WithNode(withLine, withToken, finish, expression, body));
2433     }
2434 
2435     /**
2436      * SwitchStatement :
2437      *      switch ( Expression ) CaseBlock
2438      *
2439      * CaseBlock :
2440      *      { CaseClauses? }
2441      *      { CaseClauses? DefaultClause CaseClauses }
2442      *
2443      * CaseClauses :
2444      *      CaseClause
2445      *      CaseClauses CaseClause
2446      *
2447      * CaseClause :
2448      *      case Expression : StatementList?
2449      *
2450      * DefaultClause :
2451      *      default : StatementList?
2452      *
2453      * See 12.11
2454      *
2455      * Parse SWITCH statement.
2456      */
2457     private void switchStatement() {
2458         final int  switchLine  = line;
2459         final long switchToken = token;
2460 
2461         // Block to capture variables declared inside the switch statement.
2462         final ParserContextBlockNode switchBlock = newBlock();
2463 
2464         // SWITCH tested in caller.
2465         next();
2466 
2467         // Create and add switch statement.
2468         final ParserContextSwitchNode switchNode = new ParserContextSwitchNode();
2469         lc.push(switchNode);
2470 
2471         CaseNode defaultCase = null;
2472         // Prepare to accumulate cases.
2473         final List<CaseNode> cases = new ArrayList<>();
2474 
2475         Expression expression = null;
2476 
2477         try {
2478             expect(LPAREN);
2479             expression = expression();
2480             expect(RPAREN);
2481 
2482             expect(LBRACE);
2483 
2484 
2485             while (type != RBRACE) {
2486                 // Prepare for next case.
2487                 Expression caseExpression = null;
2488                 final long caseToken = token;
2489 
2490                 switch (type) {
2491                 case CASE:
2492                     next();
2493                     caseExpression = expression();
2494                     break;
2495 
2496                 case DEFAULT:
2497                     if (defaultCase != null) {
2498                         throw error(AbstractParser.message("duplicate.default.in.switch"));
2499                     }
2500                     next();
2501                     break;
2502 
2503                 default:
2504                     // Force an error.
2505                     expect(CASE);
2506                     break;
2507                 }
2508 
2509                 expect(COLON);
2510 
2511                 // Get CASE body.
2512                 final Block statements = getBlock(false); // TODO: List<Statement> statements = caseStatementList();
2513                 final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
2514 
2515                 if (caseExpression == null) {
2516                     defaultCase = caseNode;
2517                 }
2518 
2519                 cases.add(caseNode);
2520             }
2521 
2522             next();
2523         } finally {
2524             lc.pop(switchNode);
2525             restoreBlock(switchBlock);
2526         }
2527 
2528         final SwitchNode switchStatement = new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase);
2529         appendStatement(new BlockStatement(switchLine, new Block(switchToken, finish, switchBlock.getFlags() | Block.IS_SYNTHETIC | Block.IS_SWITCH_BLOCK, switchStatement)));
2530     }
2531 
2532     /**
2533      * LabelledStatement :
2534      *      Identifier : Statement
2535      *
2536      * See 12.12
2537      *
2538      * Parse label statement.
2539      */
2540     private void labelStatement() {
2541         // Capture label token.
2542         final long labelToken = token;
2543         // Get label ident.
2544         final IdentNode ident = getIdent();
2545 
2546         expect(COLON);
2547 
2548         if (lc.findLabel(ident.getName()) != null) {
2549             throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
2550         }
2551 
2552         final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName());
2553         Block body = null;
2554         try {
2555             lc.push(labelNode);
2556             body = getStatement(true);
2557         } finally {
2558             assert lc.peek() instanceof ParserContextLabelNode;
2559             lc.pop(labelNode);
2560         }
2561 
2562         appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
2563     }
2564 
2565     /**
2566      * ThrowStatement :
2567      *      throw Expression ; // [no LineTerminator here]
2568      *
2569      * See 12.13
2570      *
2571      * Parse throw statement.
2572      */
2573     private void throwStatement() {
2574         // Capture THROW token.
2575         final int  throwLine  = line;
2576         final long throwToken = token;
2577         // THROW tested in caller.
2578         nextOrEOL();
2579 
2580         Expression expression = null;
2581 
2582         // SEMICOLON or expression.
2583         switch (type) {
2584         case RBRACE:
2585         case SEMICOLON:
2586         case EOL:
2587             break;
2588 
2589         default:
2590             expression = expression();
2591             break;
2592         }
2593 
2594         if (expression == null) {
2595             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2596         }
2597 
2598         endOfLine();
2599 
2600         appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
2601     }
2602 
2603     /**
2604      * TryStatement :
2605      *      try Block Catch
2606      *      try Block Finally
2607      *      try Block Catch Finally
2608      *
2609      * Catch :
2610      *      catch( Identifier if Expression ) Block
2611      *      catch( Identifier ) Block
2612      *
2613      * Finally :
2614      *      finally Block
2615      *
2616      * See 12.14
2617      *
2618      * Parse TRY statement.
2619      */
2620     private void tryStatement() {
2621         // Capture TRY token.
2622         final int  tryLine  = line;
2623         final long tryToken = token;
2624         // TRY tested in caller.
2625         next();
2626 
2627         // Container block needed to act as target for labeled break statements
2628         final int startLine = line;
2629         final ParserContextBlockNode outer = newBlock();
2630         // Create try.
2631 
2632         try {
2633             final Block       tryBody     = getBlock(true);
2634             final List<Block> catchBlocks = new ArrayList<>();
2635 
2636             while (type == CATCH) {
2637                 final int  catchLine  = line;
2638                 final long catchToken = token;
2639                 next();
2640                 expect(LPAREN);
2641 
2642                 // ES6 catch parameter can be a BindingIdentifier or a BindingPattern
2643                 // http://www.ecma-international.org/ecma-262/6.0/
2644                 final String contextString = "catch argument";
2645                 final Expression exception = bindingIdentifierOrPattern(contextString);
2646                 final boolean isDestructuring = !(exception instanceof IdentNode);
2647                 if (isDestructuring) {
2648                     verifyDestructuringBindingPattern(exception, new Consumer<IdentNode>() {
2649                         @Override
2650                         public void accept(final IdentNode identNode) {
2651                             verifyIdent(identNode, contextString);
2652                         }
2653                     });
2654                 } else {
2655                     // ECMA 12.4.1 strict mode restrictions
2656                     verifyIdent((IdentNode) exception, "catch argument");
2657                 }
2658 
2659 
2660                 // Nashorn extension: catch clause can have optional
2661                 // condition. So, a single try can have more than one
2662                 // catch clause each with it's own condition.
2663                 final Expression ifExpression;
2664                 if (!env._no_syntax_extensions && type == IF) {
2665                     next();
2666                     // Get the exception condition.
2667                     ifExpression = expression();
2668                 } else {
2669                     ifExpression = null;
2670                 }
2671 
2672                 expect(RPAREN);
2673 
2674                 final ParserContextBlockNode catchBlock = newBlock();
2675                 try {
2676                     // Get CATCH body.
2677                     final Block catchBody = getBlock(true);
2678                     final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
2679                     appendStatement(catchNode);
2680                 } finally {
2681                     restoreBlock(catchBlock);
2682                     catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements()));
2683                 }
2684 
2685                 // If unconditional catch then should to be the end.
2686                 if (ifExpression == null) {
2687                     break;
2688                 }
2689             }
2690 
2691             // Prepare to capture finally statement.
2692             Block finallyStatements = null;
2693 
2694             if (type == FINALLY) {
2695                 next();
2696                 finallyStatements = getBlock(true);
2697             }
2698 
2699             // Need at least one catch or a finally.
2700             if (catchBlocks.isEmpty() && finallyStatements == null) {
2701                 throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
2702             }
2703 
2704             final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
2705             // Add try.
2706             assert lc.peek() == outer;
2707             appendStatement(tryNode);
2708         } finally {
2709             restoreBlock(outer);
2710         }
2711 
2712         appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements())));
2713     }
2714 
2715     /**
2716      * DebuggerStatement :
2717      *      debugger ;
2718      *
2719      * See 12.15
2720      *
2721      * Parse debugger statement.
2722      */
2723     private void  debuggerStatement() {
2724         // Capture DEBUGGER token.
2725         final int  debuggerLine  = line;
2726         final long debuggerToken = token;
2727         // DEBUGGER tested in caller.
2728         next();
2729         endOfLine();
2730         appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish));
2731     }
2732 
2733     /**
2734      * PrimaryExpression :
2735      *      this
2736      *      IdentifierReference
2737      *      Literal
2738      *      ArrayLiteral
2739      *      ObjectLiteral
2740      *      RegularExpressionLiteral
2741      *      TemplateLiteral
2742      *      CoverParenthesizedExpressionAndArrowParameterList
2743      *
2744      * CoverParenthesizedExpressionAndArrowParameterList :
2745      *      ( Expression )
2746      *      ( )
2747      *      ( ... BindingIdentifier )
2748      *      ( Expression , ... BindingIdentifier )
2749      *
2750      * Parse primary expression.
2751      * @return Expression node.
2752      */
2753     @SuppressWarnings("fallthrough")
2754     private Expression primaryExpression() {
2755         // Capture first token.
2756         final int  primaryLine  = line;
2757         final long primaryToken = token;
2758 
2759         switch (type) {
2760         case THIS:
2761             final String name = type.getName();
2762             next();
2763             markThis(lc);
2764             return new IdentNode(primaryToken, finish, name);
2765         case IDENT:
2766             final IdentNode ident = getIdent();
2767             if (ident == null) {
2768                 break;
2769             }
2770             detectSpecialProperty(ident);
2771             checkEscapedKeyword(ident);
2772             return ident;
2773         case OCTAL_LEGACY:
2774             if (isStrictMode) {
2775                throw error(AbstractParser.message("strict.no.octal"), token);
2776             }
2777         case STRING:
2778         case ESCSTRING:
2779         case DECIMAL:
2780         case HEXADECIMAL:
2781         case OCTAL:
2782         case BINARY_NUMBER:
2783         case FLOATING:
2784         case REGEX:
2785         case XML:
2786             return getLiteral();
2787         case EXECSTRING:
2788             return execString(primaryLine, primaryToken);
2789         case FALSE:
2790             next();
2791             return LiteralNode.newInstance(primaryToken, finish, false);
2792         case TRUE:
2793             next();
2794             return LiteralNode.newInstance(primaryToken, finish, true);
2795         case NULL:
2796             next();
2797             return LiteralNode.newInstance(primaryToken, finish);
2798         case LBRACKET:
2799             return arrayLiteral();
2800         case LBRACE:
2801             return objectLiteral();
2802         case LPAREN:
2803             next();
2804 
2805             if (isES6()) {
2806                 if (type == RPAREN) {
2807                     // ()
2808                     nextOrEOL();
2809                     expectDontAdvance(ARROW);
2810                     return new ExpressionList(primaryToken, finish, Collections.emptyList());
2811                 } else if (type == ELLIPSIS) {
2812                     // (...rest)
2813                     final IdentNode restParam = formalParameterList(false).get(0);
2814                     expectDontAdvance(RPAREN);
2815                     nextOrEOL();
2816                     expectDontAdvance(ARROW);
2817                     return new ExpressionList(primaryToken, finish, Collections.singletonList(restParam));
2818                 }
2819             }
2820 
2821             final Expression expression = expression();
2822 
2823             expect(RPAREN);
2824 
2825             return expression;
2826         case TEMPLATE:
2827         case TEMPLATE_HEAD:
2828             return templateLiteral();
2829 
2830         default:
2831             // In this context some operator tokens mark the start of a literal.
2832             if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
2833                 next();
2834                 return getLiteral();
2835             }
2836             if (isNonStrictModeIdent()) {
2837                 return getIdent();
2838             }
2839             break;
2840         }
2841 
2842         return null;
2843     }
2844 
2845     /**
2846      * Convert execString to a call to $EXEC.
2847      *
2848      * @param primaryToken Original string token.
2849      * @return callNode to $EXEC.
2850      */
2851     CallNode execString(final int primaryLine, final long primaryToken) {
2852         // Synthesize an ident to call $EXEC.
2853         final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
2854         // Skip over EXECSTRING.
2855         next();
2856         // Set up argument list for call.
2857         // Skip beginning of edit string expression.
2858         expect(LBRACE);
2859         // Add the following expression to arguments.
2860         final List<Expression> arguments = Collections.singletonList(expression());
2861         // Skip ending of edit string expression.
2862         expect(RBRACE);
2863 
2864         return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
2865     }
2866 
2867     /**
2868      * ArrayLiteral :
2869      *      [ Elision? ]
2870      *      [ ElementList ]
2871      *      [ ElementList , Elision? ]
2872      *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
2873      *
2874      * ElementList : Elision? AssignmentExpression
2875      *      ElementList , Elision? AssignmentExpression
2876      *
2877      * Elision :
2878      *      ,
2879      *      Elision ,
2880      *
2881      * See 12.1.4
2882      * JavaScript 1.8
2883      *
2884      * Parse array literal.
2885      * @return Expression node.
2886      */
2887     @SuppressWarnings("fallthrough")
2888     private LiteralNode<Expression[]> arrayLiteral() {
2889         // Capture LBRACKET token.
2890         final long arrayToken = token;
2891         // LBRACKET tested in caller.
2892         next();
2893 
2894         // Prepare to accumulate elements.
2895         final List<Expression> elements = new ArrayList<>();
2896         // Track elisions.
2897         boolean elision = true;
2898         boolean hasSpread = false;
2899         loop:
2900         while (true) {
2901             long spreadToken = 0;
2902             switch (type) {
2903             case RBRACKET:
2904                 next();
2905 
2906                 break loop;
2907 
2908             case COMMARIGHT:
2909                 next();
2910 
2911                 // If no prior expression
2912                 if (elision) {
2913                     elements.add(null);
2914                 }
2915 
2916                 elision = true;
2917 
2918                 break;
2919 
2920             case ELLIPSIS:
2921                 if (isES6()) {
2922                     hasSpread = true;
2923                     spreadToken = token;
2924                     next();
2925                 }
2926                 // fall through
2927 
2928             default:
2929                 if (!elision) {
2930                     throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2931                 }
2932 
2933                 // Add expression element.
2934                 Expression expression = assignmentExpression(false);
2935                 if (expression != null) {
2936                     if (spreadToken != 0) {
2937                         expression = new UnaryNode(Token.recast(spreadToken, SPREAD_ARRAY), expression);
2938                     }
2939                     elements.add(expression);
2940                 } else {
2941                     expect(RBRACKET);
2942                 }
2943 
2944                 elision = false;
2945                 break;
2946             }
2947         }
2948 
2949         return LiteralNode.newInstance(arrayToken, finish, elements, hasSpread, elision);
2950     }
2951 
2952     /**
2953      * ObjectLiteral :
2954      *      { }
2955      *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2956      *
2957      * PropertyNameAndValueList :
2958      *      PropertyAssignment
2959      *      PropertyNameAndValueList , PropertyAssignment
2960      *
2961      * See 11.1.5
2962      *
2963      * Parse an object literal.
2964      * @return Expression node.
2965      */
2966     private ObjectNode objectLiteral() {
2967         // Capture LBRACE token.
2968         final long objectToken = token;
2969         // LBRACE tested in caller.
2970         next();
2971 
2972         // Object context.
2973         // Prepare to accumulate elements.
2974         final List<PropertyNode> elements = new ArrayList<>();
2975         final Map<String, Integer> map = new HashMap<>();
2976 
2977         // Create a block for the object literal.
2978         boolean commaSeen = true;
2979         loop:
2980         while (true) {
2981             switch (type) {
2982                 case RBRACE:
2983                     next();
2984                     break loop;
2985 
2986                 case COMMARIGHT:
2987                     if (commaSeen) {
2988                         throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2989                     }
2990                     next();
2991                     commaSeen = true;
2992                     break;
2993 
2994                 default:
2995                     if (!commaSeen) {
2996                         throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2997                     }
2998 
2999                     commaSeen = false;
3000                     // Get and add the next property.
3001                     final PropertyNode property = propertyAssignment();
3002 
3003                     if (property.isComputed()) {
3004                         elements.add(property);
3005                         break;
3006                     }
3007 
3008                     final String key = property.getKeyName();
3009                     final Integer existing = map.get(key);
3010 
3011                     if (existing == null) {
3012                         map.put(key, elements.size());
3013                         elements.add(property);
3014                         break;
3015                     }
3016 
3017                     final PropertyNode existingProperty = elements.get(existing);
3018 
3019                     // ECMA section 11.1.5 Object Initialiser
3020                     // point # 4 on property assignment production
3021                     final Expression   value  = property.getValue();
3022                     final FunctionNode getter = property.getGetter();
3023                     final FunctionNode setter = property.getSetter();
3024 
3025                     final Expression   prevValue  = existingProperty.getValue();
3026                     final FunctionNode prevGetter = existingProperty.getGetter();
3027                     final FunctionNode prevSetter = existingProperty.getSetter();
3028 
3029                     if (!isES6()) {
3030                         checkPropertyRedefinition(property, value, getter, setter, prevValue, prevGetter, prevSetter);
3031                     } else {
3032                         if (property.getKey() instanceof IdentNode && ((IdentNode)property.getKey()).isProtoPropertyName() &&
3033                                         existingProperty.getKey() instanceof IdentNode && ((IdentNode)existingProperty.getKey()).isProtoPropertyName()) {
3034                             throw error(AbstractParser.message("multiple.proto.key"), property.getToken());
3035                         }
3036                     }
3037 
3038                     if (value != null || prevValue != null) {
3039                         map.put(key, elements.size());
3040                         elements.add(property);
3041                     } else if (getter != null) {
3042                         assert prevGetter != null || prevSetter != null;
3043                         elements.set(existing, existingProperty.setGetter(getter));
3044                     } else if (setter != null) {
3045                         assert prevGetter != null || prevSetter != null;
3046                         elements.set(existing, existingProperty.setSetter(setter));
3047                     }
3048                     break;
3049             }
3050         }
3051 
3052         return new ObjectNode(objectToken, finish, elements);
3053     }
3054 
3055     private void checkPropertyRedefinition(final PropertyNode property, final Expression value, final FunctionNode getter, final FunctionNode setter, final Expression prevValue, final FunctionNode prevGetter, final FunctionNode prevSetter) {
3056         // ECMA 11.1.5 strict mode restrictions
3057         if (isStrictMode && value != null && prevValue != null) {
3058             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3059         }
3060 
3061         final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
3062         final boolean isAccessor     = getter != null     || setter != null;
3063 
3064         // data property redefined as accessor property
3065         if (prevValue != null && isAccessor) {
3066             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3067         }
3068 
3069         // accessor property redefined as data
3070         if (isPrevAccessor && value != null) {
3071             throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3072         }
3073 
3074         if (isAccessor && isPrevAccessor) {
3075             if (getter != null && prevGetter != null ||
3076                     setter != null && prevSetter != null) {
3077                 throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3078             }
3079         }
3080     }
3081 
3082     /**
3083      * LiteralPropertyName :
3084      *      IdentifierName
3085      *      StringLiteral
3086      *      NumericLiteral
3087      *
3088      * @return PropertyName node
3089      */
3090     @SuppressWarnings("fallthrough")
3091     private PropertyKey literalPropertyName() {
3092         switch (type) {
3093         case IDENT:
3094             return getIdent().setIsPropertyName();
3095         case OCTAL_LEGACY:
3096             if (isStrictMode) {
3097                 throw error(AbstractParser.message("strict.no.octal"), token);
3098             }
3099         case STRING:
3100         case ESCSTRING:
3101         case DECIMAL:
3102         case HEXADECIMAL:
3103         case OCTAL:
3104         case BINARY_NUMBER:
3105         case FLOATING:
3106             return getLiteral();
3107         default:
3108             return getIdentifierName().setIsPropertyName();
3109         }
3110     }
3111 
3112     /**
3113      * ComputedPropertyName :
3114      *      AssignmentExpression
3115      *
3116      * @return PropertyName node
3117      */
3118     private Expression computedPropertyName() {
3119         expect(LBRACKET);
3120         final Expression expression = assignmentExpression(false);
3121         expect(RBRACKET);
3122         return expression;
3123     }
3124 
3125     /**
3126      * PropertyName :
3127      *      LiteralPropertyName
3128      *      ComputedPropertyName
3129      *
3130      * @return PropertyName node
3131      */
3132     private Expression propertyName() {
3133         if (type == LBRACKET && isES6()) {
3134             return computedPropertyName();
3135         } else {
3136             return (Expression)literalPropertyName();
3137         }
3138     }
3139 
3140     /**
3141      * PropertyAssignment :
3142      *      PropertyName : AssignmentExpression
3143      *      get PropertyName ( ) { FunctionBody }
3144      *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
3145      *
3146      * PropertySetParameterList :
3147      *      Identifier
3148      *
3149      * PropertyName :
3150      *      IdentifierName
3151      *      StringLiteral
3152      *      NumericLiteral
3153      *
3154      * See 11.1.5
3155      *
3156      * Parse an object literal property.
3157      * @return Property or reference node.
3158      */
3159     private PropertyNode propertyAssignment() {
3160         // Capture firstToken.
3161         final long propertyToken = token;
3162         final int  functionLine  = line;
3163 
3164         final Expression propertyName;
3165         final boolean isIdentifier;
3166 
3167         boolean generator = false;
3168         if (type == MUL && isES6()) {
3169             generator = true;
3170             next();
3171         }
3172 
3173         final boolean computed = type == LBRACKET;
3174         if (type == IDENT) {
3175             // Get IDENT.
3176             final String ident = (String)expectValue(IDENT);
3177 
3178             if (type != COLON && (type != LPAREN || !isES6())) {
3179                 final long getSetToken = propertyToken;
3180 
3181                 switch (ident) {
3182                 case GET_NAME:
3183                     final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
3184                     return new PropertyNode(propertyToken, finish, getter.key, null, getter.functionNode, null, false, getter.computed);
3185 
3186                 case SET_NAME:
3187                     final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
3188                     return new PropertyNode(propertyToken, finish, setter.key, null, null, setter.functionNode, false, setter.computed);
3189                 default:
3190                     break;
3191                 }
3192             }
3193 
3194             isIdentifier = true;
3195             IdentNode identNode = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
3196             if (type == COLON && ident.equals("__proto__")) {
3197                 identNode = identNode.setIsProtoPropertyName();
3198             }
3199             propertyName = identNode;
3200         } else {
3201             isIdentifier = isNonStrictModeIdent();
3202             propertyName = propertyName();
3203         }
3204 
3205         Expression propertyValue;
3206 
3207         if (generator) {
3208             expectDontAdvance(LPAREN);
3209         }
3210 
3211         if (type == LPAREN && isES6()) {
3212             propertyValue = propertyMethodFunction(propertyName, propertyToken, functionLine, generator, FunctionNode.ES6_IS_METHOD, computed).functionNode;
3213         } else if (isIdentifier && (type == COMMARIGHT || type == RBRACE || type == ASSIGN) && isES6()) {
3214             propertyValue = createIdentNode(propertyToken, finish, ((IdentNode) propertyName).getPropertyName());
3215             if (type == ASSIGN && isES6()) {
3216                 // TODO if not destructuring, this is a SyntaxError
3217                 final long assignToken = token;
3218                 next();
3219                 final Expression rhs = assignmentExpression(false);
3220                 propertyValue = verifyAssignment(assignToken, propertyValue, rhs);
3221             }
3222         } else {
3223             expect(COLON);
3224 
3225             defaultNames.push(propertyName);
3226             try {
3227                 propertyValue = assignmentExpression(false);
3228             } finally {
3229                 defaultNames.pop();
3230             }
3231         }
3232 
3233         return new PropertyNode(propertyToken, finish, propertyName, propertyValue, null, null, false, computed);
3234     }
3235 
3236     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
3237         return propertyGetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
3238     }
3239 
3240     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine, final int flags) {
3241         final boolean computed = type == LBRACKET;
3242         final Expression propertyName = propertyName();
3243         final String getterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
3244         final IdentNode getNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("get " + getterName));
3245         expect(LPAREN);
3246         expect(RPAREN);
3247 
3248         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
3249         functionNode.setFlag(flags);
3250         if (computed) {
3251             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3252         }
3253         lc.push(functionNode);
3254 
3255         Block functionBody;
3256 
3257 
3258         try {
3259             functionBody = functionBody(functionNode);
3260         } finally {
3261             lc.pop(functionNode);
3262         }
3263 
3264         final FunctionNode  function = createFunctionNode(
3265                 functionNode,
3266                 getSetToken,
3267                 getNameNode,
3268                 Collections.<IdentNode>emptyList(),
3269                 FunctionNode.Kind.GETTER,
3270                 functionLine,
3271                 functionBody);
3272 
3273         return new PropertyFunction(propertyName, function, computed);
3274     }
3275 
3276     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
3277         return propertySetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
3278     }
3279 
3280     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine, final int flags) {
3281         final boolean computed = type == LBRACKET;
3282         final Expression propertyName = propertyName();
3283         final String setterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
3284         final IdentNode setNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("set " + setterName));
3285         expect(LPAREN);
3286         // be sloppy and allow missing setter parameter even though
3287         // spec does not permit it!
3288         final IdentNode argIdent;
3289         if (isBindingIdentifier()) {
3290             argIdent = getIdent();
3291             verifyIdent(argIdent, "setter argument");
3292         } else {
3293             argIdent = null;
3294         }
3295         expect(RPAREN);
3296         final List<IdentNode> parameters = new ArrayList<>();
3297         if (argIdent != null) {
3298             parameters.add(argIdent);
3299         }
3300 
3301 
3302         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
3303         functionNode.setFlag(flags);
3304         if (computed) {
3305             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3306         }
3307         lc.push(functionNode);
3308 
3309         Block functionBody;
3310         try {
3311             functionBody = functionBody(functionNode);
3312         } finally {
3313             lc.pop(functionNode);
3314         }
3315 
3316 
3317         final FunctionNode  function = createFunctionNode(
3318                 functionNode,
3319                 getSetToken,
3320                 setNameNode,
3321                 parameters,
3322                 FunctionNode.Kind.SETTER,
3323                 functionLine,
3324                 functionBody);
3325 
3326         return new PropertyFunction(propertyName, function, computed);
3327     }
3328 
3329     private PropertyFunction propertyMethodFunction(final Expression key, final long methodToken, final int methodLine, final boolean generator, final int flags, final boolean computed) {
3330         final String methodName = key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : getDefaultValidFunctionName(methodLine, false);
3331         final IdentNode methodNameNode = createIdentNode(((Node)key).getToken(), finish, methodName);
3332 
3333         final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
3334         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(methodNameNode, methodToken, functionKind, methodLine, null);
3335         functionNode.setFlag(flags);
3336         if (computed) {
3337             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3338         }
3339         lc.push(functionNode);
3340 
3341         try {
3342             final ParserContextBlockNode parameterBlock = newBlock();
3343             final List<IdentNode> parameters;
3344             try {
3345                 expect(LPAREN);
3346                 parameters = formalParameterList(generator);
3347                 functionNode.setParameters(parameters);
3348                 expect(RPAREN);
3349             } finally {
3350                 restoreBlock(parameterBlock);
3351             }
3352 
3353             Block functionBody = functionBody(functionNode);
3354 
3355             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
3356 
3357             final FunctionNode  function = createFunctionNode(
3358                             functionNode,
3359                             methodToken,
3360                             methodNameNode,
3361                             parameters,
3362                             functionKind,
3363                             methodLine,
3364                             functionBody);
3365             return new PropertyFunction(key, function, computed);
3366         } finally {
3367             lc.pop(functionNode);
3368         }
3369     }
3370 
3371     private static class PropertyFunction {
3372         final Expression key;
3373         final FunctionNode functionNode;
3374         final boolean computed;
3375 
3376         PropertyFunction(final Expression key, final FunctionNode function, final boolean computed) {
3377             this.key = key;
3378             this.functionNode = function;
3379             this.computed = computed;
3380         }
3381     }
3382 
3383     /**
3384      * LeftHandSideExpression :
3385      *      NewExpression
3386      *      CallExpression
3387      *
3388      * CallExpression :
3389      *      MemberExpression Arguments
3390      *      SuperCall
3391      *      CallExpression Arguments
3392      *      CallExpression [ Expression ]
3393      *      CallExpression . IdentifierName
3394      *
3395      * SuperCall :
3396      *      super Arguments
3397      *
3398      * See 11.2
3399      *
3400      * Parse left hand side expression.
3401      * @return Expression node.
3402      */
3403     private Expression leftHandSideExpression() {
3404         int  callLine  = line;
3405         long callToken = token;
3406 
3407         Expression lhs = memberExpression();
3408 
3409         if (type == LPAREN) {
3410             final List<Expression> arguments = optimizeList(argumentList());
3411 
3412             // Catch special functions.
3413             if (lhs instanceof IdentNode) {
3414                 detectSpecialFunction((IdentNode)lhs);
3415                 checkEscapedKeyword((IdentNode)lhs);
3416             }
3417 
3418             lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3419         }
3420 
3421         loop:
3422         while (true) {
3423             // Capture token.
3424             callLine  = line;
3425             callToken = token;
3426 
3427             switch (type) {
3428             case LPAREN: {
3429                 // Get NEW or FUNCTION arguments.
3430                 final List<Expression> arguments = optimizeList(argumentList());
3431 
3432                 // Create call node.
3433                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3434 
3435                 break;
3436             }
3437             case LBRACKET: {
3438                 next();
3439 
3440                 // Get array index.
3441                 final Expression rhs = expression();
3442 
3443                 expect(RBRACKET);
3444 
3445                 // Create indexing node.
3446                 lhs = new IndexNode(callToken, finish, lhs, rhs);
3447 
3448                 break;
3449             }
3450             case PERIOD: {
3451                 next();
3452 
3453                 final IdentNode property = getIdentifierName();
3454 
3455                 // Create property access node.
3456                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
3457 
3458                 break;
3459             }
3460             case TEMPLATE:
3461             case TEMPLATE_HEAD: {
3462                 // tagged template literal
3463                 final List<Expression> arguments = templateLiteralArgumentList();
3464 
3465                 // Create call node.
3466                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3467 
3468                 break;
3469             }
3470             default:
3471                 break loop;
3472             }
3473         }
3474 
3475         return lhs;
3476     }
3477 
3478     /**
3479      * NewExpression :
3480      *      MemberExpression
3481      *      new NewExpression
3482      *
3483      * See 11.2
3484      *
3485      * Parse new expression.
3486      * @return Expression node.
3487      */
3488     private Expression newExpression() {
3489         final long newToken = token;
3490         // NEW is tested in caller.
3491         next();
3492 
3493         if (type == PERIOD && isES6()) {
3494             next();
3495             if (type == IDENT && "target".equals(getValue())) {
3496                 if (lc.getCurrentFunction().isProgram()) {
3497                     throw error(AbstractParser.message("new.target.in.function"), token);
3498                 }
3499                 next();
3500                 markNewTarget(lc);
3501                 return new IdentNode(newToken, finish, "new.target");
3502             } else {
3503                 throw error(AbstractParser.message("expected.target"), token);
3504             }
3505         }
3506 
3507         // Get function base.
3508         final int  callLine    = line;
3509         final Expression constructor = memberExpression();
3510         if (constructor == null) {
3511             return null;
3512         }
3513         // Get arguments.
3514         ArrayList<Expression> arguments;
3515 
3516         // Allow for missing arguments.
3517         if (type == LPAREN) {
3518             arguments = argumentList();
3519         } else {
3520             arguments = new ArrayList<>();
3521         }
3522 
3523         // Nashorn extension: This is to support the following interface implementation
3524         // syntax:
3525         //
3526         //     var r = new java.lang.Runnable() {
3527         //         run: function() { println("run"); }
3528         //     };
3529         //
3530         // The object literal following the "new Constructor()" expression
3531         // is passed as an additional (last) argument to the constructor.
3532         if (!env._no_syntax_extensions && type == LBRACE) {
3533             arguments.add(objectLiteral());
3534         }
3535 
3536         final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
3537 
3538         return new UnaryNode(newToken, callNode);
3539     }
3540 
3541     /**
3542      * MemberExpression :
3543      *      PrimaryExpression
3544      *        FunctionExpression
3545      *        ClassExpression
3546      *        GeneratorExpression
3547      *      MemberExpression [ Expression ]
3548      *      MemberExpression . IdentifierName
3549      *      MemberExpression TemplateLiteral
3550      *      SuperProperty
3551      *      MetaProperty
3552      *      new MemberExpression Arguments
3553      *
3554      * SuperProperty :
3555      *      super [ Expression ]
3556      *      super . IdentifierName
3557      *
3558      * MetaProperty :
3559      *      NewTarget
3560      *
3561      * Parse member expression.
3562      * @return Expression node.
3563      */
3564     @SuppressWarnings("fallthrough")
3565     private Expression memberExpression() {
3566         // Prepare to build operation.
3567         Expression lhs;
3568         boolean isSuper = false;
3569 
3570         switch (type) {
3571         case NEW:
3572             // Get new expression.
3573             lhs = newExpression();
3574             break;
3575 
3576         case FUNCTION:
3577             // Get function expression.
3578             lhs = functionExpression(false, false);
3579             break;
3580 
3581         case CLASS:
3582             if (isES6()) {
3583                 lhs = classExpression(false);
3584                 break;
3585             } else {
3586                 // fall through
3587             }
3588 
3589         case SUPER:
3590             if (isES6()) {
3591                 final ParserContextFunctionNode currentFunction = getCurrentNonArrowFunction();
3592                 if (currentFunction.isMethod()) {
3593                     final long identToken = Token.recast(token, IDENT);
3594                     next();
3595                     lhs = createIdentNode(identToken, finish, SUPER.getName());
3596 
3597                     switch (type) {
3598                         case LBRACKET:
3599                         case PERIOD:
3600                             getCurrentNonArrowFunction().setFlag(FunctionNode.ES6_USES_SUPER);
3601                             isSuper = true;
3602                             break;
3603                         case LPAREN:
3604                             if (currentFunction.isSubclassConstructor()) {
3605                                 lhs = ((IdentNode)lhs).setIsDirectSuper();
3606                                 break;
3607                             } else {
3608                                 // fall through to throw error
3609                             }
3610                         default:
3611                             throw error(AbstractParser.message("invalid.super"), identToken);
3612                     }
3613                     break;
3614                 } else {
3615                     // fall through
3616                 }
3617             } else {
3618                 // fall through
3619             }
3620 
3621         default:
3622             // Get primary expression.
3623             lhs = primaryExpression();
3624             break;
3625         }
3626 
3627         loop:
3628         while (true) {
3629             // Capture token.
3630             final long callToken = token;
3631 
3632             switch (type) {
3633             case LBRACKET: {
3634                 next();
3635 
3636                 // Get array index.
3637                 final Expression index = expression();
3638 
3639                 expect(RBRACKET);
3640 
3641                 // Create indexing node.
3642                 lhs = new IndexNode(callToken, finish, lhs, index);
3643 
3644                 if (isSuper) {
3645                     isSuper = false;
3646                     lhs = ((BaseNode) lhs).setIsSuper();
3647                 }
3648 
3649                 break;
3650             }
3651             case PERIOD: {
3652                 if (lhs == null) {
3653                     throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3654                 }
3655 
3656                 next();
3657 
3658                 final IdentNode property = getIdentifierName();
3659 
3660                 // Create property access node.
3661                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
3662 
3663                 if (isSuper) {
3664                     isSuper = false;
3665                     lhs = ((BaseNode) lhs).setIsSuper();
3666                 }
3667 
3668                 break;
3669             }
3670             case TEMPLATE:
3671             case TEMPLATE_HEAD: {
3672                 // tagged template literal
3673                 final int callLine = line;
3674                 final List<Expression> arguments = templateLiteralArgumentList();
3675 
3676                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3677 
3678                 break;
3679             }
3680             default:
3681                 break loop;
3682             }
3683         }
3684 
3685         return lhs;
3686     }
3687 
3688     /**
3689      * Arguments :
3690      *      ( )
3691      *      ( ArgumentList )
3692      *
3693      * ArgumentList :
3694      *      AssignmentExpression
3695      *      ... AssignmentExpression
3696      *      ArgumentList , AssignmentExpression
3697      *      ArgumentList , ... AssignmentExpression
3698      *
3699      * See 11.2
3700      *
3701      * Parse function call arguments.
3702      * @return Argument list.
3703      */
3704     private ArrayList<Expression> argumentList() {
3705         // Prepare to accumulate list of arguments.
3706         final ArrayList<Expression> nodeList = new ArrayList<>();
3707         // LPAREN tested in caller.
3708         next();
3709 
3710         // Track commas.
3711         boolean first = true;
3712 
3713         while (type != RPAREN) {
3714             // Comma prior to every argument except the first.
3715             if (!first) {
3716                 expect(COMMARIGHT);
3717             } else {
3718                 first = false;
3719             }
3720 
3721             long spreadToken = 0;
3722             if (type == ELLIPSIS && isES6()) {
3723                 spreadToken = token;
3724                 next();
3725             }
3726 
3727             // Get argument expression.
3728             Expression expression = assignmentExpression(false);
3729             if (spreadToken != 0) {
3730                 expression = new UnaryNode(Token.recast(spreadToken, TokenType.SPREAD_ARGUMENT), expression);
3731             }
3732             nodeList.add(expression);
3733         }
3734 
3735         expect(RPAREN);
3736         return nodeList;
3737     }
3738 
3739     private static <T> List<T> optimizeList(final ArrayList<T> list) {
3740         switch(list.size()) {
3741             case 0: {
3742                 return Collections.emptyList();
3743             }
3744             case 1: {
3745                 return Collections.singletonList(list.get(0));
3746             }
3747             default: {
3748                 list.trimToSize();
3749                 return list;
3750             }
3751         }
3752     }
3753 
3754     /**
3755      * FunctionDeclaration :
3756      *      function Identifier ( FormalParameterList? ) { FunctionBody }
3757      *
3758      * FunctionExpression :
3759      *      function Identifier? ( FormalParameterList? ) { FunctionBody }
3760      *
3761      * See 13
3762      *
3763      * Parse function declaration.
3764      * @param isStatement True if for is a statement.
3765      *
3766      * @return Expression node.
3767      */
3768     private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
3769         final long functionToken = token;
3770         final int  functionLine  = line;
3771         // FUNCTION is tested in caller.
3772         assert type == FUNCTION;
3773         next();
3774 
3775         boolean generator = false;
3776         if (type == MUL && isES6()) {
3777             generator = true;
3778             next();
3779         }
3780 
3781         IdentNode name = null;
3782 
3783         if (isBindingIdentifier()) {
3784             if (type == YIELD && ((!isStatement && generator) || (isStatement && inGeneratorFunction()))) {
3785                 // 12.1.1 Early SyntaxError if:
3786                 // GeneratorExpression with BindingIdentifier yield
3787                 // HoistableDeclaration with BindingIdentifier yield in generator function body
3788                 expect(IDENT);
3789             }
3790             name = getIdent();
3791             verifyIdent(name, "function name");
3792         } else if (isStatement) {
3793             // Nashorn extension: anonymous function statements.
3794             // Do not allow anonymous function statement if extensions
3795             // are now allowed. But if we are reparsing then anon function
3796             // statement is possible - because it was used as function
3797             // expression in surrounding code.
3798             if (env._no_syntax_extensions && reparsedFunction == null) {
3799                 expect(IDENT);
3800             }
3801         }
3802 
3803         // name is null, generate anonymous name
3804         boolean isAnonymous = false;
3805         if (name == null) {
3806             final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
3807             name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
3808             isAnonymous = true;
3809         }
3810 
3811         final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
3812         List<IdentNode> parameters = Collections.emptyList();
3813         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, functionKind, functionLine, parameters);
3814         lc.push(functionNode);
3815 
3816         Block functionBody = null;
3817         // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
3818         // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
3819         hideDefaultName();
3820         try {
3821             final ParserContextBlockNode parameterBlock = newBlock();
3822             try {
3823                 expect(LPAREN);
3824                 parameters = formalParameterList(generator);
3825                 functionNode.setParameters(parameters);
3826                 expect(RPAREN);
3827             } finally {
3828                 restoreBlock(parameterBlock);
3829             }
3830 
3831             functionBody = functionBody(functionNode);
3832 
3833             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
3834         } finally {
3835             defaultNames.pop();
3836             lc.pop(functionNode);
3837         }
3838 
3839         if (isStatement) {
3840             if (topLevel || useBlockScope() || (!isStrictMode && env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ACCEPT)) {
3841                 functionNode.setFlag(FunctionNode.IS_DECLARED);
3842             } else if (isStrictMode) {
3843                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
3844             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
3845                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
3846             } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
3847                 warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
3848             }
3849             if (isArguments(name)) {
3850                lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
3851             }
3852         }
3853 
3854         if (isAnonymous) {
3855             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3856         }
3857 
3858         verifyParameterList(parameters, functionNode);
3859 
3860         final FunctionNode function = createFunctionNode(
3861                 functionNode,
3862                 functionToken,
3863                 name,
3864                 parameters,
3865                 functionKind,
3866                 functionLine,
3867                 functionBody);
3868 
3869         if (isStatement) {
3870             if (isAnonymous) {
3871                 appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function));
3872                 return function;
3873             }
3874 
3875             // mark ES6 block functions as lexically scoped
3876             final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
3877             final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
3878             if (topLevel) {
3879                 functionDeclarations.add(varNode);
3880             } else if (useBlockScope()) {
3881                 prependStatement(varNode); // Hoist to beginning of current block
3882             } else {
3883                 appendStatement(varNode);
3884             }
3885         }
3886 
3887         return function;
3888     }
3889 
3890     private void verifyParameterList(final List<IdentNode> parameters, final ParserContextFunctionNode functionNode) {
3891         final IdentNode duplicateParameter = functionNode.getDuplicateParameterBinding();
3892         if (duplicateParameter != null) {
3893             if (functionNode.isStrict() || functionNode.getKind() == FunctionNode.Kind.ARROW || !functionNode.isSimpleParameterList()) {
3894                 throw error(AbstractParser.message("strict.param.redefinition", duplicateParameter.getName()), duplicateParameter.getToken());
3895             }
3896 
3897             final int arity = parameters.size();
3898             final HashSet<String> parametersSet = new HashSet<>(arity);
3899 
3900             for (int i = arity - 1; i >= 0; i--) {
3901                 final IdentNode parameter = parameters.get(i);
3902                 String parameterName = parameter.getName();
3903 
3904                 if (parametersSet.contains(parameterName)) {
3905                     // redefinition of parameter name, rename in non-strict mode
3906                     parameterName = functionNode.uniqueName(parameterName);
3907                     final long parameterToken = parameter.getToken();
3908                     parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
3909                 }
3910                 parametersSet.add(parameterName);
3911             }
3912         }
3913     }
3914 
3915     private static Block maybeWrapBodyInParameterBlock(final Block functionBody, final ParserContextBlockNode parameterBlock) {
3916         assert functionBody.isFunctionBody();
3917         if (!parameterBlock.getStatements().isEmpty()) {
3918             parameterBlock.appendStatement(new BlockStatement(functionBody));
3919             return new Block(parameterBlock.getToken(), functionBody.getFinish(), (functionBody.getFlags() | Block.IS_PARAMETER_BLOCK) & ~Block.IS_BODY, parameterBlock.getStatements());
3920         }
3921         return functionBody;
3922     }
3923 
3924     private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
3925         final String defaultFunctionName = getDefaultFunctionName();
3926         if (isValidIdentifier(defaultFunctionName)) {
3927             if (isStatement) {
3928                 // The name will be used as the LHS of a symbol assignment. We add the anonymous function
3929                 // prefix to ensure that it can't clash with another variable.
3930                 return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
3931             }
3932             return defaultFunctionName;
3933         }
3934         return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
3935     }
3936 
3937     private static boolean isValidIdentifier(final String name) {
3938         if (name == null || name.isEmpty()) {
3939             return false;
3940         }
3941         if (!Character.isJavaIdentifierStart(name.charAt(0))) {
3942             return false;
3943         }
3944         for (int i = 1; i < name.length(); ++i) {
3945             if (!Character.isJavaIdentifierPart(name.charAt(i))) {
3946                 return false;
3947             }
3948         }
3949         return true;
3950     }
3951 
3952     private String getDefaultFunctionName() {
3953         if (!defaultNames.isEmpty()) {
3954             final Object nameExpr = defaultNames.peek();
3955             if (nameExpr instanceof PropertyKey) {
3956                 markDefaultNameUsed();
3957                 return ((PropertyKey)nameExpr).getPropertyName();
3958             } else if (nameExpr instanceof AccessNode) {
3959                 markDefaultNameUsed();
3960                 return ((AccessNode)nameExpr).getProperty();
3961             }
3962         }
3963         return null;
3964     }
3965 
3966     private void markDefaultNameUsed() {
3967         defaultNames.pop();
3968         hideDefaultName();
3969     }
3970 
3971     private void hideDefaultName() {
3972         // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
3973         // from. Can't be null
3974         defaultNames.push("");
3975     }
3976 
3977     /**
3978      * FormalParameterList :
3979      *      Identifier
3980      *      FormalParameterList , Identifier
3981      *
3982      * See 13
3983      *
3984      * Parse function parameter list.
3985      * @return List of parameter nodes.
3986      */
3987     private List<IdentNode> formalParameterList(final boolean yield) {
3988         return formalParameterList(RPAREN, yield);
3989     }
3990 
3991     /**
3992      * Same as the other method of the same name - except that the end
3993      * token type expected is passed as argument to this method.
3994      *
3995      * FormalParameterList :
3996      *      Identifier
3997      *      FormalParameterList , Identifier
3998      *
3999      * See 13
4000      *
4001      * Parse function parameter list.
4002      * @return List of parameter nodes.
4003      */
4004     private List<IdentNode> formalParameterList(final TokenType endType, final boolean yield) {
4005         // Prepare to gather parameters.
4006         final ArrayList<IdentNode> parameters = new ArrayList<>();
4007         // Track commas.
4008         boolean first = true;
4009 
4010         while (type != endType) {
4011             // Comma prior to every argument except the first.
4012             if (!first) {
4013                 expect(COMMARIGHT);
4014             } else {
4015                 first = false;
4016             }
4017 
4018             boolean restParameter = false;
4019             if (type == ELLIPSIS && isES6()) {
4020                 next();
4021                 restParameter = true;
4022             }
4023 
4024             if (type == YIELD && yield) {
4025                 expect(IDENT);
4026             }
4027 
4028             final long paramToken = token;
4029             final int paramLine = line;
4030             final String contextString = "function parameter";
4031             IdentNode ident;
4032             if (isBindingIdentifier() || restParameter || !isES6()) {
4033                 ident = bindingIdentifier(contextString);
4034 
4035                 if (restParameter) {
4036                     ident = ident.setIsRestParameter();
4037                     // rest parameter must be last
4038                     expectDontAdvance(endType);
4039                     parameters.add(ident);
4040                     break;
4041                 } else if (type == ASSIGN && isES6()) {
4042                     next();
4043                     ident = ident.setIsDefaultParameter();
4044 
4045                     if (type == YIELD && yield) {
4046                         // error: yield in default expression
4047                         expect(IDENT);
4048                     }
4049 
4050                     // default parameter
4051                     final Expression initializer = assignmentExpression(false);
4052 
4053                     final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4054                     if (currentFunction != null) {
4055                         if (env._parse_only) {
4056                             // keep what is seen in source "as is" and save it as parameter expression
4057                             final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, initializer);
4058                             currentFunction.addParameterExpression(ident, assignment);
4059                         } else {
4060                             // desugar to: param = (param === undefined) ? initializer : param;
4061                             // possible alternative: if (param === undefined) param = initializer;
4062                             final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4063                             final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4064                             final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
4065                             lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4066                         }
4067                     }
4068                 }
4069 
4070                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4071                 if (currentFunction != null) {
4072                     currentFunction.addParameterBinding(ident);
4073                     if (ident.isRestParameter() || ident.isDefaultParameter()) {
4074                         currentFunction.setSimpleParameterList(false);
4075                     }
4076                 }
4077             } else {
4078                 final Expression pattern = bindingPattern();
4079                 // Introduce synthetic temporary parameter to capture the object to be destructured.
4080                 ident = createIdentNode(paramToken, pattern.getFinish(), String.format("arguments[%d]", parameters.size())).setIsDestructuredParameter();
4081                 verifyDestructuringParameterBindingPattern(pattern, paramToken, paramLine, contextString);
4082 
4083                 Expression value = ident;
4084                 if (type == ASSIGN) {
4085                     next();
4086                     ident = ident.setIsDefaultParameter();
4087 
4088                     // binding pattern with initializer. desugar to: (param === undefined) ? initializer : param
4089                     final Expression initializer = assignmentExpression(false);
4090 
4091                     if (env._parse_only) {
4092                         // we don't want the synthetic identifier in parse only mode
4093                         value = initializer;
4094                     } else {
4095                         // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list)
4096                         final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4097                         value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4098                     }
4099                 }
4100 
4101                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4102                 if (currentFunction != null) {
4103                     // destructuring assignment
4104                     final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), pattern, value);
4105                     if (env._parse_only) {
4106                         // in parse-only mode, represent source tree "as is"
4107                         if (ident.isDefaultParameter()) {
4108                             currentFunction.addParameterExpression(ident, assignment);
4109                         } else {
4110                             currentFunction.addParameterExpression(ident, pattern);
4111                         }
4112                     } else {
4113                         lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4114                     }
4115                 }
4116             }
4117             parameters.add(ident);
4118         }
4119 
4120         parameters.trimToSize();
4121         return parameters;
4122     }
4123 
4124     private void verifyDestructuringParameterBindingPattern(final Expression pattern, final long paramToken, final int paramLine, final String contextString) {
4125         verifyDestructuringBindingPattern(pattern, new Consumer<IdentNode>() {
4126             public void accept(final IdentNode identNode) {
4127                 verifyIdent(identNode, contextString);
4128 
4129                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4130                 if (currentFunction != null) {
4131                     // declare function-scope variables for destructuring bindings
4132                     if (!env._parse_only) {
4133                         lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null));
4134                     }
4135                     // detect duplicate bounds names in parameter list
4136                     currentFunction.addParameterBinding(identNode);
4137                     currentFunction.setSimpleParameterList(false);
4138                 }
4139             }
4140         });
4141     }
4142 
4143     /**
4144      * FunctionBody :
4145      *      SourceElements?
4146      *
4147      * See 13
4148      *
4149      * Parse function body.
4150      * @return function node (body.)
4151      */
4152     private Block functionBody(final ParserContextFunctionNode functionNode) {
4153         long lastToken = 0L;
4154         ParserContextBlockNode body = null;
4155         final long bodyToken = token;
4156         Block functionBody;
4157         int bodyFinish = 0;
4158 
4159         final boolean parseBody;
4160         Object endParserState = null;
4161         try {
4162             // Create a new function block.
4163             body = newBlock();
4164             if (env._debug_scopes) {
4165                 // debug scope options forces everything to be in scope
4166                 markEval(lc);
4167             }
4168             assert functionNode != null;
4169             final int functionId = functionNode.getId();
4170             parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
4171             // Nashorn extension: expression closures
4172             if ((!env._no_syntax_extensions || functionNode.getKind() == FunctionNode.Kind.ARROW) && type != LBRACE) {
4173                 /*
4174                  * Example:
4175                  *
4176                  * function square(x) x * x;
4177                  * print(square(3));
4178                  */
4179 
4180                 // just expression as function body
4181                 final Expression expr = assignmentExpression(false);
4182                 lastToken = previousToken;
4183                 functionNode.setLastToken(previousToken);
4184                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
4185                 // EOL uses length field to store the line number
4186                 final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
4187                 // Only create the return node if we aren't skipping nested functions. Note that we aren't
4188                 // skipping parsing of these extended functions; they're considered to be small anyway. Also,
4189                 // they don't end with a single well known token, so it'd be very hard to get correctly (see
4190                 // the note below for reasoning on skipping happening before instead of after RBRACE for
4191                 // details).
4192                 if (parseBody) {
4193                     functionNode.setFlag(FunctionNode.HAS_EXPRESSION_BODY);
4194                     final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
4195                     appendStatement(returnNode);
4196                 }
4197                 // bodyFinish = finish;
4198             } else {
4199                 expectDontAdvance(LBRACE);
4200                 if (parseBody || !skipFunctionBody(functionNode)) {
4201                     next();
4202                     // Gather the function elements.
4203                     final List<Statement> prevFunctionDecls = functionDeclarations;
4204                     functionDeclarations = new ArrayList<>();
4205                     try {
4206                         sourceElements(0);
4207                         addFunctionDeclarations(functionNode);
4208                     } finally {
4209                         functionDeclarations = prevFunctionDecls;
4210                     }
4211 
4212                     lastToken = token;
4213                     if (parseBody) {
4214                         // Since the lexer can read ahead and lexify some number of tokens in advance and have
4215                         // them buffered in the TokenStream, we need to produce a lexer state as it was just
4216                         // before it lexified RBRACE, and not whatever is its current (quite possibly well read
4217                         // ahead) state.
4218                         endParserState = new ParserState(Token.descPosition(token), line, linePosition);
4219 
4220                         // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
4221                         // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
4222                         // state after it. The reason is that RBRACE is a well-known token that we can expect and
4223                         // will never involve us getting into a weird lexer state, and as such is a great reparse
4224                         // point. Typical example of a weird lexer state after RBRACE would be:
4225                         //     function this_is_skipped() { ... } "use strict";
4226                         // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
4227                         // of compensating for the possibility of a string literal (or similar) after RBRACE,
4228                         // we'll rather just restart parsing from this well-known, friendly token instead.
4229                     }
4230                 }
4231                 bodyFinish = finish;
4232                 functionNode.setLastToken(token);
4233                 expect(RBRACE);
4234             }
4235         } finally {
4236             restoreBlock(body);
4237         }
4238 
4239         // NOTE: we can only do alterations to the function node after restoreFunctionNode.
4240 
4241         if (parseBody) {
4242             functionNode.setEndParserState(endParserState);
4243         } else if (!body.getStatements().isEmpty()){
4244             // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
4245             // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
4246             // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
4247             // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
4248             // nested bodies early if we were supposed to skip 'em.
4249             body.setStatements(Collections.<Statement>emptyList());
4250         }
4251 
4252         if (reparsedFunction != null) {
4253             // We restore the flags stored in the function's ScriptFunctionData that we got when we first
4254             // eagerly parsed the code. We're doing it because some flags would be set based on the
4255             // content of the function, or even content of its nested functions, most of which are normally
4256             // skipped during an on-demand compilation.
4257             final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
4258             if (data != null) {
4259                 // Data can be null if when we originally parsed the file, we removed the function declaration
4260                 // as it was dead code.
4261                 functionNode.setFlag(data.getFunctionFlags());
4262                 // This compensates for missing markEval() in case the function contains an inner function
4263                 // that contains eval(), that now we didn't discover since we skipped the inner function.
4264                 if (functionNode.hasNestedEval()) {
4265                     assert functionNode.hasScopeBlock();
4266                     body.setFlag(Block.NEEDS_SCOPE);
4267                 }
4268             }
4269         }
4270         functionBody = new Block(bodyToken, bodyFinish, body.getFlags() | Block.IS_BODY, body.getStatements());
4271         return functionBody;
4272     }
4273 
4274     private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
4275         if (reparsedFunction == null) {
4276             // Not reparsing, so don't skip any function body.
4277             return false;
4278         }
4279         // Skip to the RBRACE of this function, and continue parsing from there.
4280         final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
4281         if (data == null) {
4282             // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
4283             // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
4284             // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
4285             return false;
4286         }
4287         final ParserState parserState = (ParserState)data.getEndParserState();
4288         assert parserState != null;
4289 
4290         if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) {
4291             // RBRACE is already in the token stream, so fast forward to it
4292             for (; k < stream.last(); k++) {
4293                 final long nextToken = stream.get(k + 1);
4294                 if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) {
4295                     token = stream.get(k);
4296                     type = Token.descType(token);
4297                     next();
4298                     assert type == RBRACE && start == parserState.position;
4299                     return true;
4300                 }
4301             }
4302         }
4303 
4304         stream.reset();
4305         lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
4306         line = parserState.line;
4307         linePosition = parserState.linePosition;
4308         // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
4309         // the RBRACE.
4310         type = SEMICOLON;
4311         scanFirstToken();
4312 
4313         return true;
4314     }
4315 
4316     /**
4317      * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
4318      * for resuming parsing after skipping a function body.
4319      */
4320     private static class ParserState implements Serializable {
4321         private final int position;
4322         private final int line;
4323         private final int linePosition;
4324 
4325         private static final long serialVersionUID = -2382565130754093694L;
4326 
4327         ParserState(final int position, final int line, final int linePosition) {
4328             this.position = position;
4329             this.line = line;
4330             this.linePosition = linePosition;
4331         }
4332 
4333         Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
4334             final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
4335             newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
4336             return newLexer;
4337         }
4338     }
4339 
4340     private void printAST(final FunctionNode functionNode) {
4341         if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) {
4342             env.getErr().println(new ASTWriter(functionNode));
4343         }
4344 
4345         if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) {
4346             env.getErr().println(new PrintVisitor(functionNode, true, false));
4347         }
4348     }
4349 
4350     private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
4351         VarNode lastDecl = null;
4352         for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
4353             Statement decl = functionDeclarations.get(i);
4354             if (lastDecl == null && decl instanceof VarNode) {
4355                 decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
4356                 functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
4357             }
4358             prependStatement(decl);
4359         }
4360     }
4361 
4362     private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
4363         if (env._parse_only || earlyError) {
4364             throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
4365         }
4366         final ArrayList<Expression> args = new ArrayList<>();
4367         args.add(lhs);
4368         if (rhs == null) {
4369             args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
4370         } else {
4371             args.add(rhs);
4372         }
4373         args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
4374         return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
4375     }
4376 
4377     /**
4378      * PostfixExpression :
4379      *      LeftHandSideExpression
4380      *      LeftHandSideExpression ++ // [no LineTerminator here]
4381      *      LeftHandSideExpression -- // [no LineTerminator here]
4382      *
4383      * See 11.3
4384      *
4385      * UnaryExpression :
4386      *      PostfixExpression
4387      *      delete UnaryExpression
4388      *      void UnaryExpression
4389      *      typeof UnaryExpression
4390      *      ++ UnaryExpression
4391      *      -- UnaryExpression
4392      *      + UnaryExpression
4393      *      - UnaryExpression
4394      *      ~ UnaryExpression
4395      *      ! UnaryExpression
4396      *
4397      * See 11.4
4398      *
4399      * Parse unary expression.
4400      * @return Expression node.
4401      */
4402     private Expression unaryExpression() {
4403         final int  unaryLine  = line;
4404         final long unaryToken = token;
4405 
4406         switch (type) {
4407         case ADD:
4408         case SUB: {
4409             final TokenType opType = type;
4410             next();
4411             final Expression expr = unaryExpression();
4412             return new UnaryNode(Token.recast(unaryToken, (opType == TokenType.ADD) ? TokenType.POS : TokenType.NEG), expr);
4413         }
4414         case DELETE:
4415         case VOID:
4416         case TYPEOF:
4417         case BIT_NOT:
4418         case NOT:
4419             next();
4420             final Expression expr = unaryExpression();
4421             return new UnaryNode(unaryToken, expr);
4422 
4423         case INCPREFIX:
4424         case DECPREFIX:
4425             final TokenType opType = type;
4426             next();
4427 
4428             final Expression lhs = leftHandSideExpression();
4429             // ++, -- without operand..
4430             if (lhs == null) {
4431                 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
4432             }
4433 
4434             return verifyIncDecExpression(unaryToken, opType, lhs, false);
4435 
4436         default:
4437             break;
4438         }
4439 
4440         final Expression expression = leftHandSideExpression();
4441 
4442         if (last != EOL) {
4443             switch (type) {
4444             case INCPREFIX:
4445             case DECPREFIX:
4446                 final long opToken = token;
4447                 final TokenType opType = type;
4448                 final Expression lhs = expression;
4449                 // ++, -- without operand..
4450                 if (lhs == null) {
4451                     throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
4452                 }
4453                 next();
4454 
4455                 return verifyIncDecExpression(opToken, opType, lhs, true);
4456             default:
4457                 break;
4458             }
4459         }
4460 
4461         if (expression == null) {
4462             throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
4463         }
4464 
4465         return expression;
4466     }
4467 
4468     private Expression verifyIncDecExpression(final long unaryToken, final TokenType opType, final Expression lhs, final boolean isPostfix) {
4469         assert lhs != null;
4470 
4471         if (!(lhs instanceof AccessNode ||
4472               lhs instanceof IndexNode ||
4473               lhs instanceof IdentNode)) {
4474             return referenceError(lhs, null, env._early_lvalue_error);
4475         }
4476 
4477         if (lhs instanceof IdentNode) {
4478             if (!checkIdentLValue((IdentNode)lhs)) {
4479                 return referenceError(lhs, null, false);
4480             }
4481             verifyIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
4482         }
4483 
4484         return incDecExpression(unaryToken, opType, lhs, isPostfix);
4485     }
4486 
4487     /**
4488      * {@code
4489      * MultiplicativeExpression :
4490      *      UnaryExpression
4491      *      MultiplicativeExpression * UnaryExpression
4492      *      MultiplicativeExpression / UnaryExpression
4493      *      MultiplicativeExpression % UnaryExpression
4494      *
4495      * See 11.5
4496      *
4497      * AdditiveExpression :
4498      *      MultiplicativeExpression
4499      *      AdditiveExpression + MultiplicativeExpression
4500      *      AdditiveExpression - MultiplicativeExpression
4501      *
4502      * See 11.6
4503      *
4504      * ShiftExpression :
4505      *      AdditiveExpression
4506      *      ShiftExpression << AdditiveExpression
4507      *      ShiftExpression >> AdditiveExpression
4508      *      ShiftExpression >>> AdditiveExpression
4509      *
4510      * See 11.7
4511      *
4512      * RelationalExpression :
4513      *      ShiftExpression
4514      *      RelationalExpression < ShiftExpression
4515      *      RelationalExpression > ShiftExpression
4516      *      RelationalExpression <= ShiftExpression
4517      *      RelationalExpression >= ShiftExpression
4518      *      RelationalExpression instanceof ShiftExpression
4519      *      RelationalExpression in ShiftExpression // if !noIf
4520      *
4521      * See 11.8
4522      *
4523      *      RelationalExpression
4524      *      EqualityExpression == RelationalExpression
4525      *      EqualityExpression != RelationalExpression
4526      *      EqualityExpression === RelationalExpression
4527      *      EqualityExpression !== RelationalExpression
4528      *
4529      * See 11.9
4530      *
4531      * BitwiseANDExpression :
4532      *      EqualityExpression
4533      *      BitwiseANDExpression & EqualityExpression
4534      *
4535      * BitwiseXORExpression :
4536      *      BitwiseANDExpression
4537      *      BitwiseXORExpression ^ BitwiseANDExpression
4538      *
4539      * BitwiseORExpression :
4540      *      BitwiseXORExpression
4541      *      BitwiseORExpression | BitwiseXORExpression
4542      *
4543      * See 11.10
4544      *
4545      * LogicalANDExpression :
4546      *      BitwiseORExpression
4547      *      LogicalANDExpression && BitwiseORExpression
4548      *
4549      * LogicalORExpression :
4550      *      LogicalANDExpression
4551      *      LogicalORExpression || LogicalANDExpression
4552      *
4553      * See 11.11
4554      *
4555      * ConditionalExpression :
4556      *      LogicalORExpression
4557      *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
4558      *
4559      * See 11.12
4560      *
4561      * AssignmentExpression :
4562      *      ConditionalExpression
4563      *      LeftHandSideExpression AssignmentOperator AssignmentExpression
4564      *
4565      * AssignmentOperator :
4566      *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
4567      *
4568      * See 11.13
4569      *
4570      * Expression :
4571      *      AssignmentExpression
4572      *      Expression , AssignmentExpression
4573      *
4574      * See 11.14
4575      * }
4576      *
4577      * Parse expression.
4578      * @return Expression node.
4579      */
4580     protected Expression expression() {
4581         // This method is protected so that subclass can get details
4582         // at expression start point!
4583 
4584         // Include commas in expression parsing.
4585         return expression(false);
4586     }
4587 
4588     private Expression expression(final boolean noIn) {
4589         Expression assignmentExpression = assignmentExpression(noIn);
4590         while (type == COMMARIGHT) {
4591             final long commaToken = token;
4592             next();
4593 
4594             boolean rhsRestParameter = false;
4595             if (type == ELLIPSIS && isES6()) {
4596                 // (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).
4597                 // 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.
4598                 if (isRestParameterEndOfArrowFunctionParameterList()) {
4599                     next();
4600                     rhsRestParameter = true;
4601                 }
4602             }
4603 
4604             Expression rhs = assignmentExpression(noIn);
4605 
4606             if (rhsRestParameter) {
4607                 rhs = ((IdentNode)rhs).setIsRestParameter();
4608                 // Our only valid move is to end Expression here and continue with ArrowFunction.
4609                 // We've already checked that this is the parameter list of an arrow function (see above).
4610                 // RPAREN is next, so we'll finish the binary expression and drop out of the loop.
4611                 assert type == RPAREN;
4612             }
4613 
4614             assignmentExpression = new BinaryNode(commaToken, assignmentExpression, rhs);
4615         }
4616         return assignmentExpression;
4617     }
4618 
4619     private Expression expression(final int minPrecedence, final boolean noIn) {
4620         return expression(unaryExpression(), minPrecedence, noIn);
4621     }
4622 
4623     private JoinPredecessorExpression joinPredecessorExpression() {
4624         return new JoinPredecessorExpression(expression());
4625     }
4626 
4627     private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
4628         // Get the precedence of the next operator.
4629         int precedence = type.getPrecedence();
4630         Expression lhs = exprLhs;
4631 
4632         // While greater precedence.
4633         while (type.isOperator(noIn) && precedence >= minPrecedence) {
4634             // Capture the operator token.
4635             final long op = token;
4636 
4637             if (type == TERNARY) {
4638                 // Skip operator.
4639                 next();
4640 
4641                 // Pass expression. Middle expression of a conditional expression can be a "in"
4642                 // expression - even in the contexts where "in" is not permitted.
4643                 final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
4644 
4645                 expect(COLON);
4646 
4647                 // Fail expression.
4648                 final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
4649 
4650                 // Build up node.
4651                 lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
4652             } else {
4653                 // Skip operator.
4654                 next();
4655 
4656                  // Get the next primary expression.
4657                 Expression rhs;
4658                 final boolean isAssign = Token.descType(op) == ASSIGN;
4659                 if(isAssign) {
4660                     defaultNames.push(lhs);
4661                 }
4662                 try {
4663                     rhs = unaryExpression();
4664                     // Get precedence of next operator.
4665                     int nextPrecedence = type.getPrecedence();
4666 
4667                     // Subtask greater precedence.
4668                     while (type.isOperator(noIn) &&
4669                            (nextPrecedence > precedence ||
4670                            nextPrecedence == precedence && !type.isLeftAssociative())) {
4671                         rhs = expression(rhs, nextPrecedence, noIn);
4672                         nextPrecedence = type.getPrecedence();
4673                     }
4674                 } finally {
4675                     if(isAssign) {
4676                         defaultNames.pop();
4677                     }
4678                 }
4679                 lhs = verifyAssignment(op, lhs, rhs);
4680             }
4681 
4682             precedence = type.getPrecedence();
4683         }
4684 
4685         return lhs;
4686     }
4687 
4688     /**
4689      * AssignmentExpression.
4690      *
4691      * AssignmentExpression[In, Yield] :
4692      *   ConditionalExpression[?In, ?Yield]
4693      *   [+Yield] YieldExpression[?In]
4694      *   ArrowFunction[?In, ?Yield]
4695      *   LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield]
4696      *   LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield]
4697      *
4698      * @param noIn {@code true} if IN operator should be ignored.
4699      * @return the assignment expression
4700      */
4701     protected Expression assignmentExpression(final boolean noIn) {
4702         // This method is protected so that subclass can get details
4703         // at assignment expression start point!
4704 
4705         if (type == YIELD && inGeneratorFunction() && isES6()) {
4706             return yieldExpression(noIn);
4707         }
4708 
4709         final long startToken = token;
4710         final int startLine = line;
4711         final Expression exprLhs = conditionalExpression(noIn);
4712 
4713         if (type == ARROW && isES6()) {
4714             if (checkNoLineTerminator()) {
4715                 final Expression paramListExpr;
4716                 if (exprLhs instanceof ExpressionList) {
4717                     paramListExpr = (((ExpressionList)exprLhs).getExpressions().isEmpty() ? null : ((ExpressionList)exprLhs).getExpressions().get(0));
4718                 } else {
4719                     paramListExpr = exprLhs;
4720                 }
4721                 return arrowFunction(startToken, startLine, paramListExpr);
4722             }
4723         }
4724         assert !(exprLhs instanceof ExpressionList);
4725 
4726         if (isAssignmentOperator(type)) {
4727             final boolean isAssign = type == ASSIGN;
4728             if (isAssign) {
4729                 defaultNames.push(exprLhs);
4730             }
4731             try {
4732                 final long assignToken = token;
4733                 next();
4734                 final Expression exprRhs = assignmentExpression(noIn);
4735                 return verifyAssignment(assignToken, exprLhs, exprRhs);
4736             } finally {
4737                 if (isAssign) {
4738                     defaultNames.pop();
4739                 }
4740             }
4741         } else {
4742             return exprLhs;
4743         }
4744     }
4745 
4746     /**
4747      * Is type one of {@code = *= /= %= += -= <<= >>= >>>= &= ^= |=}?
4748      */
4749     private static boolean isAssignmentOperator(final TokenType type) {
4750         switch (type) {
4751         case ASSIGN:
4752         case ASSIGN_ADD:
4753         case ASSIGN_BIT_AND:
4754         case ASSIGN_BIT_OR:
4755         case ASSIGN_BIT_XOR:
4756         case ASSIGN_DIV:
4757         case ASSIGN_MOD:
4758         case ASSIGN_MUL:
4759         case ASSIGN_SAR:
4760         case ASSIGN_SHL:
4761         case ASSIGN_SHR:
4762         case ASSIGN_SUB:
4763             return true;
4764         }
4765         return false;
4766     }
4767 
4768     /**
4769      * ConditionalExpression.
4770      */
4771     private Expression conditionalExpression(final boolean noIn) {
4772         return expression(TERNARY.getPrecedence(), noIn);
4773     }
4774 
4775     /**
4776      * ArrowFunction.
4777      *
4778      * @param startToken start token of the ArrowParameters expression
4779      * @param functionLine start line of the arrow function
4780      * @param paramListExpr ArrowParameters expression or {@code null} for {@code ()} (empty list)
4781      */
4782     private Expression arrowFunction(final long startToken, final int functionLine, final Expression paramListExpr) {
4783         // caller needs to check that there's no LineTerminator between parameter list and arrow
4784         assert type != ARROW || checkNoLineTerminator();
4785         expect(ARROW);
4786 
4787         final long functionToken = Token.recast(startToken, ARROW);
4788         final IdentNode name = new IdentNode(functionToken, Token.descPosition(functionToken), NameCodec.encode("=>:") + functionLine);
4789         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.ARROW, functionLine, null);
4790         functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
4791 
4792         lc.push(functionNode);
4793         try {
4794             final ParserContextBlockNode parameterBlock = newBlock();
4795             final List<IdentNode> parameters;
4796             try {
4797                 parameters = convertArrowFunctionParameterList(paramListExpr, functionLine);
4798                 functionNode.setParameters(parameters);
4799 
4800                 if (!functionNode.isSimpleParameterList()) {
4801                     markEvalInArrowParameterList(parameterBlock);
4802                 }
4803             } finally {
4804                 restoreBlock(parameterBlock);
4805             }
4806             Block functionBody = functionBody(functionNode);
4807 
4808             functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
4809 
4810             verifyParameterList(parameters, functionNode);
4811 
4812             final FunctionNode function = createFunctionNode(
4813                             functionNode,
4814                             functionToken,
4815                             name,
4816                             parameters,
4817                             FunctionNode.Kind.ARROW,
4818                             functionLine,
4819                             functionBody);
4820             return function;
4821         } finally {
4822             lc.pop(functionNode);
4823         }
4824     }
4825 
4826     private void markEvalInArrowParameterList(final ParserContextBlockNode parameterBlock) {
4827         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
4828         final ParserContextFunctionNode current = iter.next();
4829         final ParserContextFunctionNode parent = iter.next();
4830 
4831         if (parent.getFlag(FunctionNode.HAS_EVAL) != 0) {
4832             // we might have flagged has-eval in the parent function during parsing the parameter list,
4833             // if the parameter list contains eval; must tag arrow function as has-eval.
4834             for (final Statement st : parameterBlock.getStatements()) {
4835                 st.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
4836                     @Override
4837                     public boolean enterCallNode(final CallNode callNode) {
4838                         if (callNode.getFunction() instanceof IdentNode && ((IdentNode) callNode.getFunction()).getName().equals("eval")) {
4839                             current.setFlag(FunctionNode.HAS_EVAL);
4840                         }
4841                         return true;
4842                     }
4843                 });
4844             }
4845             // TODO: function containing the arrow function should not be flagged has-eval
4846         }
4847     }
4848 
4849     private List<IdentNode> convertArrowFunctionParameterList(final Expression paramListExpr, final int functionLine) {
4850         final List<IdentNode> parameters;
4851         if (paramListExpr == null) {
4852             // empty parameter list, i.e. () =>
4853             parameters = Collections.emptyList();
4854         } else if (paramListExpr instanceof IdentNode || paramListExpr.isTokenType(ASSIGN) || isDestructuringLhs(paramListExpr)) {
4855             parameters = Collections.singletonList(verifyArrowParameter(paramListExpr, 0, functionLine));
4856         } else if (paramListExpr instanceof BinaryNode && Token.descType(paramListExpr.getToken()) == COMMARIGHT) {
4857             parameters = new ArrayList<>();
4858             Expression car = paramListExpr;
4859             do {
4860                 final Expression cdr = ((BinaryNode) car).rhs();
4861                 parameters.add(0, verifyArrowParameter(cdr, parameters.size(), functionLine));
4862                 car = ((BinaryNode) car).lhs();
4863             } while (car instanceof BinaryNode && Token.descType(car.getToken()) == COMMARIGHT);
4864             parameters.add(0, verifyArrowParameter(car, parameters.size(), functionLine));
4865         } else {
4866             throw error(AbstractParser.message("expected.arrow.parameter"), paramListExpr.getToken());
4867         }
4868         return parameters;
4869     }
4870 
4871     private IdentNode verifyArrowParameter(final Expression param, final int index, final int paramLine) {
4872         final String contextString = "function parameter";
4873         if (param instanceof IdentNode) {
4874             final IdentNode ident = (IdentNode)param;
4875             verifyIdent(ident, contextString);
4876             final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4877             if (currentFunction != null) {
4878                 currentFunction.addParameterBinding(ident);
4879             }
4880             return ident;
4881         }
4882 
4883         if (param.isTokenType(ASSIGN)) {
4884             final Expression lhs = ((BinaryNode) param).lhs();
4885             final long paramToken = lhs.getToken();
4886             final Expression initializer = ((BinaryNode) param).rhs();
4887             if (lhs instanceof IdentNode) {
4888                 // default parameter
4889                 final IdentNode ident = (IdentNode) lhs;
4890 
4891                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4892                 if (currentFunction != null) {
4893                     if (env._parse_only) {
4894                         currentFunction.addParameterExpression(ident, param);
4895                     } else {
4896                         final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4897                         final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4898                         final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
4899                         lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4900                     }
4901 
4902                     currentFunction.addParameterBinding(ident);
4903                     currentFunction.setSimpleParameterList(false);
4904                 }
4905                 return ident;
4906             } else if (isDestructuringLhs(lhs)) {
4907                 // binding pattern with initializer
4908                 // Introduce synthetic temporary parameter to capture the object to be destructured.
4909                 final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter().setIsDefaultParameter();
4910                 verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
4911 
4912                 final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4913                 if (currentFunction != null) {
4914                     if (env._parse_only) {
4915                         currentFunction.addParameterExpression(ident, param);
4916                     } else {
4917                         final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4918                         final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4919                         final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value);
4920                         lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4921                     }
4922                 }
4923                 return ident;
4924             }
4925         } else if (isDestructuringLhs(param)) {
4926             // binding pattern
4927             final long paramToken = param.getToken();
4928 
4929             // Introduce synthetic temporary parameter to capture the object to be destructured.
4930             final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter();
4931             verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
4932 
4933             final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4934             if (currentFunction != null) {
4935                 if (env._parse_only) {
4936                     currentFunction.addParameterExpression(ident, param);
4937                 } else {
4938                     final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident);
4939                     lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4940                 }
4941             }
4942             return ident;
4943         }
4944         throw error(AbstractParser.message("invalid.arrow.parameter"), param.getToken());
4945     }
4946 
4947     private boolean checkNoLineTerminator() {
4948         assert type == ARROW;
4949         if (last == RPAREN) {
4950             return true;
4951         } else if (last == IDENT) {
4952             return true;
4953         }
4954         for (int i = k - 1; i >= 0; i--) {
4955             final TokenType t = T(i);
4956             switch (t) {
4957             case RPAREN:
4958             case IDENT:
4959                 return true;
4960             case EOL:
4961                 return false;
4962             case COMMENT:
4963                 continue;
4964             default:
4965                 if (t.getKind() == TokenKind.FUTURESTRICT) {
4966                     return true;
4967                 }
4968                 return false;
4969             }
4970         }
4971         return false;
4972     }
4973 
4974     /**
4975      * Peek ahead to see if what follows after the ellipsis is a rest parameter
4976      * at the end of an arrow function parameter list.
4977      */
4978     private boolean isRestParameterEndOfArrowFunctionParameterList() {
4979         assert type == ELLIPSIS;
4980         // find IDENT, RPAREN, ARROW, in that order, skipping over EOL (where allowed) and COMMENT
4981         int i = 1;
4982         for (;;) {
4983             final TokenType t = T(k + i++);
4984             if (t == IDENT) {
4985                 break;
4986             } else if (t == EOL || t == COMMENT) {
4987                 continue;
4988             } else {
4989                 return false;
4990             }
4991         }
4992         for (;;) {
4993             final TokenType t = T(k + i++);
4994             if (t == RPAREN) {
4995                 break;
4996             } else if (t == EOL || t == COMMENT) {
4997                 continue;
4998             } else {
4999                 return false;
5000             }
5001         }
5002         for (;;) {
5003             final TokenType t = T(k + i++);
5004             if (t == ARROW) {
5005                 break;
5006             } else if (t == COMMENT) {
5007                 continue;
5008             } else {
5009                 return false;
5010             }
5011         }
5012         return true;
5013     }
5014 
5015     /**
5016      * Parse an end of line.
5017      */
5018     private void endOfLine() {
5019         switch (type) {
5020         case SEMICOLON:
5021         case EOL:
5022             next();
5023             break;
5024         case RPAREN:
5025         case RBRACKET:
5026         case RBRACE:
5027         case EOF:
5028             break;
5029         default:
5030             if (last != EOL) {
5031                 expect(SEMICOLON);
5032             }
5033             break;
5034         }
5035     }
5036 
5037     /**
5038      * Parse untagged template literal as string concatenation.
5039      */
5040     private Expression templateLiteral() {
5041         assert type == TEMPLATE || type == TEMPLATE_HEAD;
5042         final boolean noSubstitutionTemplate = type == TEMPLATE;
5043         long lastLiteralToken = token;
5044         LiteralNode<?> literal = getLiteral();
5045         if (noSubstitutionTemplate) {
5046             return literal;
5047         }
5048 
5049         if (env._parse_only) {
5050             final List<Expression> exprs = new ArrayList<>();
5051             exprs.add(literal);
5052             TokenType lastLiteralType;
5053             do {
5054                 final Expression expression = expression();
5055                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5056                     throw error(AbstractParser.message("unterminated.template.expression"), token);
5057                 }
5058                 exprs.add(expression);
5059                 lastLiteralType = type;
5060                 literal = getLiteral();
5061                 exprs.add(literal);
5062             } while (lastLiteralType == TEMPLATE_MIDDLE);
5063             return new TemplateLiteral(exprs);
5064         } else {
5065             Expression concat = literal;
5066             TokenType lastLiteralType;
5067             do {
5068                 final Expression expression = expression();
5069                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5070                     throw error(AbstractParser.message("unterminated.template.expression"), token);
5071                 }
5072                 concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression);
5073                 lastLiteralType = type;
5074                 lastLiteralToken = token;
5075                 literal = getLiteral();
5076                 concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal);
5077             } while (lastLiteralType == TEMPLATE_MIDDLE);
5078             return concat;
5079         }
5080     }
5081 
5082     /**
5083      * Parse tagged template literal as argument list.
5084      * @return argument list for a tag function call (template object, ...substitutions)
5085      */
5086     private List<Expression> templateLiteralArgumentList() {
5087         assert type == TEMPLATE || type == TEMPLATE_HEAD;
5088         final ArrayList<Expression> argumentList = new ArrayList<>();
5089         final ArrayList<Expression> rawStrings = new ArrayList<>();
5090         final ArrayList<Expression> cookedStrings = new ArrayList<>();
5091         argumentList.add(null); // filled at the end
5092 
5093         final long templateToken = token;
5094         final boolean hasSubstitutions = type == TEMPLATE_HEAD;
5095         addTemplateLiteralString(rawStrings, cookedStrings);
5096 
5097         if (hasSubstitutions) {
5098             TokenType lastLiteralType;
5099             do {
5100                 final Expression expression = expression();
5101                 if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5102                     throw error(AbstractParser.message("unterminated.template.expression"), token);
5103                 }
5104                 argumentList.add(expression);
5105 
5106                 lastLiteralType = type;
5107                 addTemplateLiteralString(rawStrings, cookedStrings);
5108             } while (lastLiteralType == TEMPLATE_MIDDLE);
5109         }
5110 
5111         final LiteralNode<Expression[]> rawStringArray = LiteralNode.newInstance(templateToken, finish, rawStrings);
5112         final LiteralNode<Expression[]> cookedStringArray = LiteralNode.newInstance(templateToken, finish, cookedStrings);
5113 
5114         if (!env._parse_only) {
5115             final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray);
5116             argumentList.set(0, templateObject);
5117         } else {
5118             argumentList.set(0, rawStringArray);
5119         }
5120         return optimizeList(argumentList);
5121     }
5122 
5123     private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) {
5124         final long stringToken = token;
5125         final String rawString = lexer.valueOfRawString(stringToken);
5126         final String cookedString = (String) getValue();
5127         next();
5128         rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString));
5129         cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
5130     }
5131 
5132 
5133     /**
5134      * Parse a module.
5135      *
5136      * Module :
5137      *      ModuleBody?
5138      *
5139      * ModuleBody :
5140      *      ModuleItemList
5141      */
5142     private FunctionNode module(final String moduleName) {
5143         final boolean oldStrictMode = isStrictMode;
5144         try {
5145             isStrictMode = true; // Module code is always strict mode code. (ES6 10.2.1)
5146 
5147             // Make a pseudo-token for the script holding its start and length.
5148             final int functionStart = Math.min(Token.descPosition(Token.withDelimiter(token)), finish);
5149             final long functionToken = Token.toDesc(FUNCTION, functionStart, source.getLength() - functionStart);
5150             final int  functionLine  = line;
5151 
5152             final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), moduleName);
5153             final ParserContextFunctionNode script = createParserContextFunctionNode(
5154                             ident,
5155                             functionToken,
5156                             FunctionNode.Kind.MODULE,
5157                             functionLine,
5158                             Collections.<IdentNode>emptyList());
5159             lc.push(script);
5160 
5161             final ParserContextModuleNode module = new ParserContextModuleNode(moduleName);
5162             lc.push(module);
5163 
5164             final ParserContextBlockNode body = newBlock();
5165 
5166             functionDeclarations = new ArrayList<>();
5167             moduleBody();
5168             addFunctionDeclarations(script);
5169             functionDeclarations = null;
5170 
5171             restoreBlock(body);
5172             body.setFlag(Block.NEEDS_SCOPE);
5173             final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
5174             lc.pop(module);
5175             lc.pop(script);
5176             script.setLastToken(token);
5177 
5178             expect(EOF);
5179 
5180             script.setModule(module.createModule());
5181             return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.MODULE, functionLine, programBody);
5182         } finally {
5183             isStrictMode = oldStrictMode;
5184         }
5185     }
5186 
5187     /**
5188      * Parse module body.
5189      *
5190      * ModuleBody :
5191      *      ModuleItemList
5192      *
5193      * ModuleItemList :
5194      *      ModuleItem
5195      *      ModuleItemList ModuleItem
5196      *
5197      * ModuleItem :
5198      *      ImportDeclaration
5199      *      ExportDeclaration
5200      *      StatementListItem
5201      */
5202     private void moduleBody() {
5203         loop:
5204         while (type != EOF) {
5205             switch (type) {
5206             case EOF:
5207                 break loop;
5208             case IMPORT:
5209                 importDeclaration();
5210                 break;
5211             case EXPORT:
5212                 exportDeclaration();
5213                 break;
5214             default:
5215                 // StatementListItem
5216                 statement(true, 0, false, false);
5217                 break;
5218             }
5219         }
5220     }
5221 
5222 
5223     /**
5224      * Parse import declaration.
5225      *
5226      * ImportDeclaration :
5227      *     import ImportClause FromClause ;
5228      *     import ModuleSpecifier ;
5229      * ImportClause :
5230      *     ImportedDefaultBinding
5231      *     NameSpaceImport
5232      *     NamedImports
5233      *     ImportedDefaultBinding , NameSpaceImport
5234      *     ImportedDefaultBinding , NamedImports
5235      * ImportedDefaultBinding :
5236      *     ImportedBinding
5237      * ModuleSpecifier :
5238      *     StringLiteral
5239      * ImportedBinding :
5240      *     BindingIdentifier
5241      */
5242     private void importDeclaration() {
5243         final int startPosition = start;
5244         expect(IMPORT);
5245         final ParserContextModuleNode module = lc.getCurrentModule();
5246         if (type == STRING || type == ESCSTRING) {
5247             // import ModuleSpecifier ;
5248             final IdentNode moduleSpecifier = createIdentNode(token, finish, (String) getValue());
5249             next();
5250             module.addModuleRequest(moduleSpecifier);
5251         } else {
5252             // import ImportClause FromClause ;
5253             List<Module.ImportEntry> importEntries;
5254             if (type == MUL) {
5255                 importEntries = Collections.singletonList(nameSpaceImport(startPosition));
5256             } else if (type == LBRACE) {
5257                 importEntries = namedImports(startPosition);
5258             } else if (isBindingIdentifier()) {
5259                 // ImportedDefaultBinding
5260                 final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding");
5261                 final Module.ImportEntry defaultImport = Module.ImportEntry.importSpecifier(importedDefaultBinding, startPosition, finish);
5262 
5263                 if (type == COMMARIGHT) {
5264                     next();
5265                     importEntries = new ArrayList<>();
5266                     if (type == MUL) {
5267                         importEntries.add(nameSpaceImport(startPosition));
5268                     } else if (type == LBRACE) {
5269                         importEntries.addAll(namedImports(startPosition));
5270                     } else {
5271                         throw error(AbstractParser.message("expected.named.import"));
5272                     }
5273                 } else {
5274                     importEntries = Collections.singletonList(defaultImport);
5275                 }
5276             } else {
5277                 throw error(AbstractParser.message("expected.import"));
5278             }
5279 
5280             final IdentNode moduleSpecifier = fromClause();
5281             module.addModuleRequest(moduleSpecifier);
5282             for (int i = 0; i < importEntries.size(); i++) {
5283                 module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier, finish));
5284             }
5285         }
5286         expect(SEMICOLON);
5287     }
5288 
5289     /**
5290      * NameSpaceImport :
5291      *     * as ImportedBinding
5292      *
5293      * @param startPosition the start of the import declaration
5294      * @return imported binding identifier
5295      */
5296     private Module.ImportEntry nameSpaceImport(final int startPosition) {
5297         assert type == MUL;
5298         final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
5299         next();
5300         final long asToken = token;
5301         final String as = (String) expectValue(IDENT);
5302         if (!"as".equals(as)) {
5303             throw error(AbstractParser.message("expected.as"), asToken);
5304         }
5305         final IdentNode localNameSpace = bindingIdentifier("ImportedBinding");
5306         return Module.ImportEntry.importSpecifier(starName, localNameSpace, startPosition, finish);
5307     }
5308 
5309     /**
5310      * NamedImports :
5311      *     { }
5312      *     { ImportsList }
5313      *     { ImportsList , }
5314      * ImportsList :
5315      *     ImportSpecifier
5316      *     ImportsList , ImportSpecifier
5317      * ImportSpecifier :
5318      *     ImportedBinding
5319      *     IdentifierName as ImportedBinding
5320      * ImportedBinding :
5321      *     BindingIdentifier
5322      */
5323     private List<Module.ImportEntry> namedImports(final int startPosition) {
5324         assert type == LBRACE;
5325         next();
5326         final List<Module.ImportEntry> importEntries = new ArrayList<>();
5327         while (type != RBRACE) {
5328             final boolean bindingIdentifier = isBindingIdentifier();
5329             final long nameToken = token;
5330             final IdentNode importName = getIdentifierName();
5331             if (type == IDENT && "as".equals(getValue())) {
5332                 next();
5333                 final IdentNode localName = bindingIdentifier("ImportedBinding");
5334                 importEntries.add(Module.ImportEntry.importSpecifier(importName, localName, startPosition, finish));
5335             } else if (!bindingIdentifier) {
5336                 throw error(AbstractParser.message("expected.binding.identifier"), nameToken);
5337             } else {
5338                 importEntries.add(Module.ImportEntry.importSpecifier(importName, startPosition, finish));
5339             }
5340             if (type == COMMARIGHT) {
5341                 next();
5342             } else {
5343                 break;
5344             }
5345         }
5346         expect(RBRACE);
5347         return importEntries;
5348     }
5349 
5350     /**
5351      * FromClause :
5352      *     from ModuleSpecifier
5353      */
5354     private IdentNode fromClause() {
5355         final long fromToken = token;
5356         final String name = (String) expectValue(IDENT);
5357         if (!"from".equals(name)) {
5358             throw error(AbstractParser.message("expected.from"), fromToken);
5359         }
5360         if (type == STRING || type == ESCSTRING) {
5361             final IdentNode moduleSpecifier = createIdentNode(Token.recast(token, IDENT), finish, (String) getValue());
5362             next();
5363             return moduleSpecifier;
5364         } else {
5365             throw error(expectMessage(STRING));
5366         }
5367     }
5368 
5369     /**
5370      * Parse export declaration.
5371      *
5372      * ExportDeclaration :
5373      *     export * FromClause ;
5374      *     export ExportClause FromClause ;
5375      *     export ExportClause ;
5376      *     export VariableStatement
5377      *     export Declaration
5378      *     export default HoistableDeclaration[Default]
5379      *     export default ClassDeclaration[Default]
5380      *     export default [lookahead !in {function, class}] AssignmentExpression[In] ;
5381      */
5382     private void exportDeclaration() {
5383         expect(EXPORT);
5384         final int startPosition = start;
5385         final ParserContextModuleNode module = lc.getCurrentModule();
5386         switch (type) {
5387             case MUL: {
5388                 final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
5389                 next();
5390                 final IdentNode moduleRequest = fromClause();
5391                 expect(SEMICOLON);
5392                 module.addModuleRequest(moduleRequest);
5393                 module.addStarExportEntry(Module.ExportEntry.exportStarFrom(starName, moduleRequest, startPosition, finish));
5394                 break;
5395             }
5396             case LBRACE: {
5397                 final List<Module.ExportEntry> exportEntries = exportClause(startPosition);
5398                 if (type == IDENT && "from".equals(getValue())) {
5399                     final IdentNode moduleRequest = fromClause();
5400                     module.addModuleRequest(moduleRequest);
5401                     for (final Module.ExportEntry exportEntry : exportEntries) {
5402                         module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest, finish));
5403                     }
5404                 } else {
5405                     for (final Module.ExportEntry exportEntry : exportEntries) {
5406                         module.addLocalExportEntry(exportEntry);
5407                     }
5408                 }
5409                 expect(SEMICOLON);
5410                 break;
5411             }
5412             case DEFAULT:
5413                 final IdentNode defaultName = createIdentNode(Token.recast(token, IDENT), finish, Module.DEFAULT_NAME);
5414                 next();
5415                 final Expression assignmentExpression;
5416                 IdentNode ident;
5417                 final int lineNumber = line;
5418                 final long rhsToken = token;
5419                 final boolean declaration;
5420                 switch (type) {
5421                     case FUNCTION:
5422                         assignmentExpression = functionExpression(false, true);
5423                         ident = ((FunctionNode) assignmentExpression).getIdent();
5424                         declaration = true;
5425                         break;
5426                     case CLASS:
5427                         assignmentExpression = classDeclaration(true);
5428                         ident = ((ClassNode) assignmentExpression).getIdent();
5429                         declaration = true;
5430                         break;
5431                     default:
5432                         assignmentExpression = assignmentExpression(false);
5433                         ident = null;
5434                         declaration = false;
5435                         break;
5436                 }
5437                 if (ident != null) {
5438                     module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
5439                 } else {
5440                     ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME);
5441                     lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression));
5442                     if (!declaration) {
5443                         expect(SEMICOLON);
5444                     }
5445                     module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
5446                 }
5447                 break;
5448             case VAR:
5449             case LET:
5450             case CONST:
5451                 final List<Statement> statements = lc.getCurrentBlock().getStatements();
5452                 final int previousEnd = statements.size();
5453                 variableStatement(type);
5454                 for (final Statement statement : statements.subList(previousEnd, statements.size())) {
5455                     if (statement instanceof VarNode) {
5456                         module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName(), startPosition, finish));
5457                     }
5458                 }
5459                 break;
5460             case CLASS: {
5461                 final ClassNode classDeclaration = classDeclaration(false);
5462                 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent(), startPosition, finish));
5463                 break;
5464             }
5465             case FUNCTION: {
5466                 final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true);
5467                 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent(), startPosition, finish));
5468                 break;
5469             }
5470             default:
5471                 throw error(AbstractParser.message("invalid.export"), token);
5472         }
5473     }
5474 
5475     /**
5476      * ExportClause :
5477      *     { }
5478      *     { ExportsList }
5479      *     { ExportsList , }
5480      * ExportsList :
5481      *     ExportSpecifier
5482      *     ExportsList , ExportSpecifier
5483      * ExportSpecifier :
5484      *     IdentifierName
5485      *     IdentifierName as IdentifierName
5486      *
5487      * @return a list of ExportSpecifiers
5488      */
5489     private List<Module.ExportEntry> exportClause(final int startPosition) {
5490         assert type == LBRACE;
5491         next();
5492         final List<Module.ExportEntry> exports = new ArrayList<>();
5493         while (type != RBRACE) {
5494             final IdentNode localName = getIdentifierName();
5495             if (type == IDENT && "as".equals(getValue())) {
5496                 next();
5497                 final IdentNode exportName = getIdentifierName();
5498                 exports.add(Module.ExportEntry.exportSpecifier(exportName, localName, startPosition, finish));
5499             } else {
5500                 exports.add(Module.ExportEntry.exportSpecifier(localName, startPosition, finish));
5501             }
5502             if (type == COMMARIGHT) {
5503                 next();
5504             } else {
5505                 break;
5506             }
5507         }
5508         expect(RBRACE);
5509         return exports;
5510     }
5511 
5512     @Override
5513     public String toString() {
5514         return "'JavaScript Parsing'";
5515     }
5516 
5517     private static void markEval(final ParserContext lc) {
5518         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5519         boolean flaggedCurrentFn = false;
5520         while (iter.hasNext()) {
5521             final ParserContextFunctionNode fn = iter.next();
5522             if (!flaggedCurrentFn) {
5523                 fn.setFlag(FunctionNode.HAS_EVAL);
5524                 flaggedCurrentFn = true;
5525                 if (fn.getKind() == FunctionNode.Kind.ARROW) {
5526                     // possible use of this in an eval that's nested in an arrow function, e.g.:
5527                     // function fun(){ return (() => eval("this"))(); };
5528                     markThis(lc);
5529                     markNewTarget(lc);
5530                 }
5531             } else {
5532                 fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
5533             }
5534             final ParserContextBlockNode body = lc.getFunctionBody(fn);
5535             // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
5536             // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
5537             // this method when the parser skips a nested function.
5538             body.setFlag(Block.NEEDS_SCOPE);
5539             fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
5540         }
5541     }
5542 
5543     private void prependStatement(final Statement statement) {
5544         lc.prependStatementToCurrentNode(statement);
5545     }
5546 
5547     private void appendStatement(final Statement statement) {
5548         lc.appendStatementToCurrentNode(statement);
5549     }
5550 
5551     private static void markSuperCall(final ParserContext lc) {
5552         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5553         while (iter.hasNext()) {
5554             final ParserContextFunctionNode fn = iter.next();
5555             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5556                 assert fn.isSubclassConstructor();
5557                 fn.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
5558                 break;
5559             }
5560         }
5561     }
5562 
5563     private ParserContextFunctionNode getCurrentNonArrowFunction() {
5564         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5565         while (iter.hasNext()) {
5566             final ParserContextFunctionNode fn = iter.next();
5567             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5568                 return fn;
5569             }
5570         }
5571         return null;
5572     }
5573 
5574     private static void markThis(final ParserContext lc) {
5575         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5576         while (iter.hasNext()) {
5577             final ParserContextFunctionNode fn = iter.next();
5578             fn.setFlag(FunctionNode.USES_THIS);
5579             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5580                 break;
5581             }
5582         }
5583     }
5584 
5585     private static void markNewTarget(final ParserContext lc) {
5586         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5587         while (iter.hasNext()) {
5588             final ParserContextFunctionNode fn = iter.next();
5589             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5590                 if (!fn.isProgram()) {
5591                     fn.setFlag(FunctionNode.ES6_USES_NEW_TARGET);
5592                 }
5593                 break;
5594             }
5595         }
5596     }
5597 
5598     private boolean inGeneratorFunction() {
5599         return lc.getCurrentFunction().getKind() == FunctionNode.Kind.GENERATOR;
5600     }
5601 }