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


5112         final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray);
5113         argumentList.set(0, templateObject);



5114         return optimizeList(argumentList);
5115     }
5116 
5117     private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) {
5118         final long stringToken = token;
5119         final String rawString = lexer.valueOfRawString(stringToken);
5120         final String cookedString = (String) getValue();
5121         next();
5122         rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString));
5123         cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
5124     }
5125 
5126 
5127     /**
5128      * Parse a module.
5129      *
5130      * Module :
5131      *      ModuleBody?
5132      *
5133      * ModuleBody :
5134      *      ModuleItemList
5135      */
5136     private FunctionNode module(final String moduleName) {
5137         final boolean oldStrictMode = isStrictMode;
5138         try {
5139             isStrictMode = true; // Module code is always strict mode code. (ES6 10.2.1)
5140 
5141             // Make a pseudo-token for the script holding its start and length.
5142             final int functionStart = Math.min(Token.descPosition(Token.withDelimiter(token)), finish);
5143             final long functionToken = Token.toDesc(FUNCTION, functionStart, source.getLength() - functionStart);
5144             final int  functionLine  = line;
5145 
5146             final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), moduleName);
5147             final ParserContextFunctionNode script = createParserContextFunctionNode(
5148                             ident,
5149                             functionToken,
5150                             FunctionNode.Kind.MODULE,
5151                             functionLine,
5152                             Collections.<IdentNode>emptyList());
5153             lc.push(script);
5154 
5155             final ParserContextModuleNode module = new ParserContextModuleNode(moduleName);
5156             lc.push(module);
5157 
5158             final ParserContextBlockNode body = newBlock();
5159 
5160             functionDeclarations = new ArrayList<>();
5161             moduleBody();
5162             addFunctionDeclarations(script);
5163             functionDeclarations = null;
5164 
5165             restoreBlock(body);
5166             body.setFlag(Block.NEEDS_SCOPE);
5167             final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
5168             lc.pop(module);
5169             lc.pop(script);
5170             script.setLastToken(token);
5171 
5172             expect(EOF);
5173 
5174             script.setModule(module.createModule());
5175             return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.MODULE, functionLine, programBody);
5176         } finally {
5177             isStrictMode = oldStrictMode;
5178         }
5179     }
5180 
5181     /**
5182      * Parse module body.
5183      *
5184      * ModuleBody :
5185      *      ModuleItemList
5186      *
5187      * ModuleItemList :
5188      *      ModuleItem
5189      *      ModuleItemList ModuleItem
5190      *
5191      * ModuleItem :
5192      *      ImportDeclaration
5193      *      ExportDeclaration
5194      *      StatementListItem
5195      */
5196     private void moduleBody() {
5197         loop:
5198         while (type != EOF) {
5199             switch (type) {
5200             case EOF:
5201                 break loop;
5202             case IMPORT:
5203                 importDeclaration();
5204                 break;
5205             case EXPORT:
5206                 exportDeclaration();
5207                 break;
5208             default:
5209                 // StatementListItem
5210                 statement(true, 0, false, false);
5211                 break;
5212             }
5213         }
5214     }
5215 
5216 
5217     /**
5218      * Parse import declaration.
5219      *
5220      * ImportDeclaration :
5221      *     import ImportClause FromClause ;
5222      *     import ModuleSpecifier ;
5223      * ImportClause :
5224      *     ImportedDefaultBinding
5225      *     NameSpaceImport
5226      *     NamedImports
5227      *     ImportedDefaultBinding , NameSpaceImport
5228      *     ImportedDefaultBinding , NamedImports
5229      * ImportedDefaultBinding :
5230      *     ImportedBinding
5231      * ModuleSpecifier :
5232      *     StringLiteral
5233      * ImportedBinding :
5234      *     BindingIdentifier
5235      */
5236     private void importDeclaration() {
5237         final int startPosition = start;
5238         expect(IMPORT);
5239         final ParserContextModuleNode module = lc.getCurrentModule();
5240         if (type == STRING || type == ESCSTRING) {
5241             // import ModuleSpecifier ;
5242             final IdentNode moduleSpecifier = createIdentNode(token, finish, (String) getValue());
5243             next();
5244             module.addModuleRequest(moduleSpecifier);
5245         } else {
5246             // import ImportClause FromClause ;
5247             List<Module.ImportEntry> importEntries;
5248             if (type == MUL) {
5249                 importEntries = Collections.singletonList(nameSpaceImport(startPosition));
5250             } else if (type == LBRACE) {
5251                 importEntries = namedImports(startPosition);
5252             } else if (isBindingIdentifier()) {
5253                 // ImportedDefaultBinding
5254                 final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding");
5255                 final Module.ImportEntry defaultImport = Module.ImportEntry.importSpecifier(importedDefaultBinding, startPosition, finish);
5256 
5257                 if (type == COMMARIGHT) {
5258                     next();
5259                     importEntries = new ArrayList<>();
5260                     if (type == MUL) {
5261                         importEntries.add(nameSpaceImport(startPosition));
5262                     } else if (type == LBRACE) {
5263                         importEntries.addAll(namedImports(startPosition));
5264                     } else {
5265                         throw error(AbstractParser.message("expected.named.import"));
5266                     }
5267                 } else {
5268                     importEntries = Collections.singletonList(defaultImport);
5269                 }
5270             } else {
5271                 throw error(AbstractParser.message("expected.import"));
5272             }
5273 
5274             final IdentNode moduleSpecifier = fromClause();
5275             module.addModuleRequest(moduleSpecifier);
5276             for (int i = 0; i < importEntries.size(); i++) {
5277                 module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier, finish));
5278             }
5279         }
5280         expect(SEMICOLON);
5281     }
5282 
5283     /**
5284      * NameSpaceImport :
5285      *     * as ImportedBinding
5286      *
5287      * @param startPosition the start of the import declaration
5288      * @return imported binding identifier
5289      */
5290     private Module.ImportEntry nameSpaceImport(final int startPosition) {
5291         assert type == MUL;
5292         final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
5293         next();
5294         final long asToken = token;
5295         final String as = (String) expectValue(IDENT);
5296         if (!"as".equals(as)) {
5297             throw error(AbstractParser.message("expected.as"), asToken);
5298         }
5299         final IdentNode localNameSpace = bindingIdentifier("ImportedBinding");
5300         return Module.ImportEntry.importSpecifier(starName, localNameSpace, startPosition, finish);
5301     }
5302 
5303     /**
5304      * NamedImports :
5305      *     { }
5306      *     { ImportsList }
5307      *     { ImportsList , }
5308      * ImportsList :
5309      *     ImportSpecifier
5310      *     ImportsList , ImportSpecifier
5311      * ImportSpecifier :
5312      *     ImportedBinding
5313      *     IdentifierName as ImportedBinding
5314      * ImportedBinding :
5315      *     BindingIdentifier
5316      */
5317     private List<Module.ImportEntry> namedImports(final int startPosition) {
5318         assert type == LBRACE;
5319         next();
5320         final List<Module.ImportEntry> importEntries = new ArrayList<>();
5321         while (type != RBRACE) {
5322             final boolean bindingIdentifier = isBindingIdentifier();
5323             final long nameToken = token;
5324             final IdentNode importName = getIdentifierName();
5325             if (type == IDENT && "as".equals(getValue())) {
5326                 next();
5327                 final IdentNode localName = bindingIdentifier("ImportedBinding");
5328                 importEntries.add(Module.ImportEntry.importSpecifier(importName, localName, startPosition, finish));
5329             } else if (!bindingIdentifier) {
5330                 throw error(AbstractParser.message("expected.binding.identifier"), nameToken);
5331             } else {
5332                 importEntries.add(Module.ImportEntry.importSpecifier(importName, startPosition, finish));
5333             }
5334             if (type == COMMARIGHT) {
5335                 next();
5336             } else {
5337                 break;
5338             }
5339         }
5340         expect(RBRACE);
5341         return importEntries;
5342     }
5343 
5344     /**
5345      * FromClause :
5346      *     from ModuleSpecifier
5347      */
5348     private IdentNode fromClause() {
5349         final long fromToken = token;
5350         final String name = (String) expectValue(IDENT);
5351         if (!"from".equals(name)) {
5352             throw error(AbstractParser.message("expected.from"), fromToken);
5353         }
5354         if (type == STRING || type == ESCSTRING) {
5355             final IdentNode moduleSpecifier = createIdentNode(Token.recast(token, IDENT), finish, (String) getValue());
5356             next();
5357             return moduleSpecifier;
5358         } else {
5359             throw error(expectMessage(STRING));
5360         }
5361     }
5362 
5363     /**
5364      * Parse export declaration.
5365      *
5366      * ExportDeclaration :
5367      *     export * FromClause ;
5368      *     export ExportClause FromClause ;
5369      *     export ExportClause ;
5370      *     export VariableStatement
5371      *     export Declaration
5372      *     export default HoistableDeclaration[Default]
5373      *     export default ClassDeclaration[Default]
5374      *     export default [lookahead !in {function, class}] AssignmentExpression[In] ;
5375      */
5376     private void exportDeclaration() {
5377         expect(EXPORT);
5378         final int startPosition = start;
5379         final ParserContextModuleNode module = lc.getCurrentModule();
5380         switch (type) {
5381             case MUL: {
5382                 final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
5383                 next();
5384                 final IdentNode moduleRequest = fromClause();
5385                 expect(SEMICOLON);
5386                 module.addModuleRequest(moduleRequest);
5387                 module.addStarExportEntry(Module.ExportEntry.exportStarFrom(starName, moduleRequest, startPosition, finish));
5388                 break;
5389             }
5390             case LBRACE: {
5391                 final List<Module.ExportEntry> exportEntries = exportClause(startPosition);
5392                 if (type == IDENT && "from".equals(getValue())) {
5393                     final IdentNode moduleRequest = fromClause();
5394                     module.addModuleRequest(moduleRequest);
5395                     for (final Module.ExportEntry exportEntry : exportEntries) {
5396                         module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest, finish));
5397                     }
5398                 } else {
5399                     for (final Module.ExportEntry exportEntry : exportEntries) {
5400                         module.addLocalExportEntry(exportEntry);
5401                     }
5402                 }
5403                 expect(SEMICOLON);
5404                 break;
5405             }
5406             case DEFAULT:
5407                 final IdentNode defaultName = createIdentNode(Token.recast(token, IDENT), finish, Module.DEFAULT_NAME);
5408                 next();
5409                 final Expression assignmentExpression;
5410                 IdentNode ident;
5411                 final int lineNumber = line;
5412                 final long rhsToken = token;
5413                 final boolean declaration;
5414                 switch (type) {
5415                     case FUNCTION:
5416                         assignmentExpression = functionExpression(false, true);
5417                         ident = ((FunctionNode) assignmentExpression).getIdent();
5418                         declaration = true;
5419                         break;
5420                     case CLASS:
5421                         assignmentExpression = classDeclaration(true);
5422                         ident = ((ClassNode) assignmentExpression).getIdent();
5423                         declaration = true;
5424                         break;
5425                     default:
5426                         assignmentExpression = assignmentExpression(false);
5427                         ident = null;
5428                         declaration = false;
5429                         break;
5430                 }
5431                 if (ident != null) {
5432                     module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
5433                 } else {
5434                     ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME);
5435                     lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression));
5436                     if (!declaration) {
5437                         expect(SEMICOLON);
5438                     }
5439                     module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
5440                 }
5441                 break;
5442             case VAR:
5443             case LET:
5444             case CONST:
5445                 final List<Statement> statements = lc.getCurrentBlock().getStatements();
5446                 final int previousEnd = statements.size();
5447                 variableStatement(type);
5448                 for (final Statement statement : statements.subList(previousEnd, statements.size())) {
5449                     if (statement instanceof VarNode) {
5450                         module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName(), startPosition, finish));
5451                     }
5452                 }
5453                 break;
5454             case CLASS: {
5455                 final ClassNode classDeclaration = classDeclaration(false);
5456                 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent(), startPosition, finish));
5457                 break;
5458             }
5459             case FUNCTION: {
5460                 final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true);
5461                 module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent(), startPosition, finish));
5462                 break;
5463             }
5464             default:
5465                 throw error(AbstractParser.message("invalid.export"), token);
5466         }
5467     }
5468 
5469     /**
5470      * ExportClause :
5471      *     { }
5472      *     { ExportsList }
5473      *     { ExportsList , }
5474      * ExportsList :
5475      *     ExportSpecifier
5476      *     ExportsList , ExportSpecifier
5477      * ExportSpecifier :
5478      *     IdentifierName
5479      *     IdentifierName as IdentifierName
5480      *
5481      * @return a list of ExportSpecifiers
5482      */
5483     private List<Module.ExportEntry> exportClause(final int startPosition) {
5484         assert type == LBRACE;
5485         next();
5486         final List<Module.ExportEntry> exports = new ArrayList<>();
5487         while (type != RBRACE) {
5488             final IdentNode localName = getIdentifierName();
5489             if (type == IDENT && "as".equals(getValue())) {
5490                 next();
5491                 final IdentNode exportName = getIdentifierName();
5492                 exports.add(Module.ExportEntry.exportSpecifier(exportName, localName, startPosition, finish));
5493             } else {
5494                 exports.add(Module.ExportEntry.exportSpecifier(localName, startPosition, finish));
5495             }
5496             if (type == COMMARIGHT) {
5497                 next();
5498             } else {
5499                 break;
5500             }
5501         }
5502         expect(RBRACE);
5503         return exports;
5504     }
5505 
5506     @Override
5507     public String toString() {
5508         return "'JavaScript Parsing'";
5509     }
5510 
5511     private static void markEval(final ParserContext lc) {
5512         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5513         boolean flaggedCurrentFn = false;
5514         while (iter.hasNext()) {
5515             final ParserContextFunctionNode fn = iter.next();
5516             if (!flaggedCurrentFn) {
5517                 fn.setFlag(FunctionNode.HAS_EVAL);
5518                 flaggedCurrentFn = true;
5519                 if (fn.getKind() == FunctionNode.Kind.ARROW) {
5520                     // possible use of this in an eval that's nested in an arrow function, e.g.:
5521                     // function fun(){ return (() => eval("this"))(); };
5522                     markThis(lc);
5523                     markNewTarget(lc);
5524                 }
5525             } else {
5526                 fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
5527             }
5528             final ParserContextBlockNode body = lc.getFunctionBody(fn);
5529             // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
5530             // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
5531             // this method when the parser skips a nested function.
5532             body.setFlag(Block.NEEDS_SCOPE);
5533             fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
5534         }
5535     }
5536 
5537     private void prependStatement(final Statement statement) {
5538         lc.prependStatementToCurrentNode(statement);
5539     }
5540 
5541     private void appendStatement(final Statement statement) {
5542         lc.appendStatementToCurrentNode(statement);
5543     }
5544 
5545     private static void markSuperCall(final ParserContext lc) {
5546         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5547         while (iter.hasNext()) {
5548             final ParserContextFunctionNode fn = iter.next();
5549             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5550                 assert fn.isSubclassConstructor();
5551                 fn.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
5552                 break;
5553             }
5554         }
5555     }
5556 
5557     private ParserContextFunctionNode getCurrentNonArrowFunction() {
5558         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5559         while (iter.hasNext()) {
5560             final ParserContextFunctionNode fn = iter.next();
5561             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5562                 return fn;
5563             }
5564         }
5565         return null;
5566     }
5567 
5568     private static void markThis(final ParserContext lc) {
5569         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5570         while (iter.hasNext()) {
5571             final ParserContextFunctionNode fn = iter.next();
5572             fn.setFlag(FunctionNode.USES_THIS);
5573             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5574                 break;
5575             }
5576         }
5577     }
5578 
5579     private static void markNewTarget(final ParserContext lc) {
5580         final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5581         while (iter.hasNext()) {
5582             final ParserContextFunctionNode fn = iter.next();
5583             if (fn.getKind() != FunctionNode.Kind.ARROW) {
5584                 if (!fn.isProgram()) {
5585                     fn.setFlag(FunctionNode.ES6_USES_NEW_TARGET);
5586                 }
5587                 break;
5588             }
5589         }
5590     }
5591 
5592     private boolean inGeneratorFunction() {
5593         return lc.getCurrentFunction().getKind() == FunctionNode.Kind.GENERATOR;
5594     }
5595 }
--- EOF ---