Parser.java revision 1978:9133969febb5
1/*
2 * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.nashorn.internal.parser;
27
28import static jdk.nashorn.internal.codegen.CompilerConstants.ANON_FUNCTION_PREFIX;
29import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
30import static jdk.nashorn.internal.codegen.CompilerConstants.PROGRAM;
31import static jdk.nashorn.internal.parser.TokenType.ARROW;
32import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
33import static jdk.nashorn.internal.parser.TokenType.CASE;
34import static jdk.nashorn.internal.parser.TokenType.CATCH;
35import static jdk.nashorn.internal.parser.TokenType.CLASS;
36import static jdk.nashorn.internal.parser.TokenType.COLON;
37import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
38import static jdk.nashorn.internal.parser.TokenType.COMMENT;
39import static jdk.nashorn.internal.parser.TokenType.CONST;
40import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
41import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
42import static jdk.nashorn.internal.parser.TokenType.ELLIPSIS;
43import static jdk.nashorn.internal.parser.TokenType.ELSE;
44import static jdk.nashorn.internal.parser.TokenType.EOF;
45import static jdk.nashorn.internal.parser.TokenType.EOL;
46import static jdk.nashorn.internal.parser.TokenType.EQ_STRICT;
47import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
48import static jdk.nashorn.internal.parser.TokenType.EXPORT;
49import static jdk.nashorn.internal.parser.TokenType.EXTENDS;
50import static jdk.nashorn.internal.parser.TokenType.FINALLY;
51import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
52import static jdk.nashorn.internal.parser.TokenType.IDENT;
53import static jdk.nashorn.internal.parser.TokenType.IF;
54import static jdk.nashorn.internal.parser.TokenType.IMPORT;
55import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
56import static jdk.nashorn.internal.parser.TokenType.LBRACE;
57import static jdk.nashorn.internal.parser.TokenType.LBRACKET;
58import static jdk.nashorn.internal.parser.TokenType.LET;
59import static jdk.nashorn.internal.parser.TokenType.LPAREN;
60import static jdk.nashorn.internal.parser.TokenType.MUL;
61import static jdk.nashorn.internal.parser.TokenType.PERIOD;
62import static jdk.nashorn.internal.parser.TokenType.RBRACE;
63import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
64import static jdk.nashorn.internal.parser.TokenType.RPAREN;
65import static jdk.nashorn.internal.parser.TokenType.SEMICOLON;
66import static jdk.nashorn.internal.parser.TokenType.SPREAD_ARRAY;
67import static jdk.nashorn.internal.parser.TokenType.STATIC;
68import static jdk.nashorn.internal.parser.TokenType.STRING;
69import static jdk.nashorn.internal.parser.TokenType.SUPER;
70import static jdk.nashorn.internal.parser.TokenType.TEMPLATE;
71import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_HEAD;
72import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_MIDDLE;
73import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_TAIL;
74import static jdk.nashorn.internal.parser.TokenType.TERNARY;
75import static jdk.nashorn.internal.parser.TokenType.VAR;
76import static jdk.nashorn.internal.parser.TokenType.VOID;
77import static jdk.nashorn.internal.parser.TokenType.WHILE;
78import static jdk.nashorn.internal.parser.TokenType.YIELD;
79import static jdk.nashorn.internal.parser.TokenType.YIELD_STAR;
80
81import java.io.Serializable;
82import java.util.ArrayDeque;
83import java.util.ArrayList;
84import java.util.Collections;
85import java.util.Deque;
86import java.util.HashMap;
87import java.util.HashSet;
88import java.util.Iterator;
89import java.util.List;
90import java.util.Map;
91import java.util.Objects;
92import java.util.function.Consumer;
93import jdk.nashorn.internal.codegen.CompilerConstants;
94import jdk.nashorn.internal.codegen.Namespace;
95import jdk.nashorn.internal.ir.AccessNode;
96import jdk.nashorn.internal.ir.BaseNode;
97import jdk.nashorn.internal.ir.BinaryNode;
98import jdk.nashorn.internal.ir.Block;
99import jdk.nashorn.internal.ir.BlockStatement;
100import jdk.nashorn.internal.ir.BreakNode;
101import jdk.nashorn.internal.ir.CallNode;
102import jdk.nashorn.internal.ir.CaseNode;
103import jdk.nashorn.internal.ir.CatchNode;
104import jdk.nashorn.internal.ir.ClassNode;
105import jdk.nashorn.internal.ir.ContinueNode;
106import jdk.nashorn.internal.ir.DebuggerNode;
107import jdk.nashorn.internal.ir.EmptyNode;
108import jdk.nashorn.internal.ir.ErrorNode;
109import jdk.nashorn.internal.ir.Expression;
110import jdk.nashorn.internal.ir.ExpressionList;
111import jdk.nashorn.internal.ir.ExpressionStatement;
112import jdk.nashorn.internal.ir.ForNode;
113import jdk.nashorn.internal.ir.FunctionNode;
114import jdk.nashorn.internal.ir.IdentNode;
115import jdk.nashorn.internal.ir.IfNode;
116import jdk.nashorn.internal.ir.IndexNode;
117import jdk.nashorn.internal.ir.JoinPredecessorExpression;
118import jdk.nashorn.internal.ir.LabelNode;
119import jdk.nashorn.internal.ir.LexicalContext;
120import jdk.nashorn.internal.ir.LiteralNode;
121import jdk.nashorn.internal.ir.Module;
122import jdk.nashorn.internal.ir.Node;
123import jdk.nashorn.internal.ir.ObjectNode;
124import jdk.nashorn.internal.ir.PropertyKey;
125import jdk.nashorn.internal.ir.PropertyNode;
126import jdk.nashorn.internal.ir.ReturnNode;
127import jdk.nashorn.internal.ir.RuntimeNode;
128import jdk.nashorn.internal.ir.Statement;
129import jdk.nashorn.internal.ir.SwitchNode;
130import jdk.nashorn.internal.ir.TemplateLiteral;
131import jdk.nashorn.internal.ir.TernaryNode;
132import jdk.nashorn.internal.ir.ThrowNode;
133import jdk.nashorn.internal.ir.TryNode;
134import jdk.nashorn.internal.ir.UnaryNode;
135import jdk.nashorn.internal.ir.VarNode;
136import jdk.nashorn.internal.ir.WhileNode;
137import jdk.nashorn.internal.ir.WithNode;
138import jdk.nashorn.internal.ir.debug.ASTWriter;
139import jdk.nashorn.internal.ir.debug.PrintVisitor;
140import jdk.nashorn.internal.ir.visitor.NodeVisitor;
141import jdk.nashorn.internal.runtime.Context;
142import jdk.nashorn.internal.runtime.ErrorManager;
143import jdk.nashorn.internal.runtime.JSErrorType;
144import jdk.nashorn.internal.runtime.ParserException;
145import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
146import jdk.nashorn.internal.runtime.ScriptEnvironment;
147import jdk.nashorn.internal.runtime.ScriptFunctionData;
148import jdk.nashorn.internal.runtime.ScriptingFunctions;
149import jdk.nashorn.internal.runtime.Source;
150import jdk.nashorn.internal.runtime.Timing;
151import jdk.nashorn.internal.runtime.linker.NameCodec;
152import jdk.nashorn.internal.runtime.logging.DebugLogger;
153import jdk.nashorn.internal.runtime.logging.Loggable;
154import jdk.nashorn.internal.runtime.logging.Logger;
155
156/**
157 * Builds the IR.
158 */
159@Logger(name="parser")
160public class Parser extends AbstractParser implements Loggable {
161    private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName();
162    private static final String CONSTRUCTOR_NAME = "constructor";
163    private static final String GET_NAME = "get";
164    private static final String SET_NAME = "set";
165
166    /** Current env. */
167    private final ScriptEnvironment env;
168
169    /** Is scripting mode. */
170    private final boolean scripting;
171
172    private List<Statement> functionDeclarations;
173
174    private final ParserContext lc;
175    private final Deque<Object> defaultNames;
176
177    /** Namespace for function names where not explicitly given */
178    private final Namespace namespace;
179
180    private final DebugLogger log;
181
182    /** to receive line information from Lexer when scanning multine literals. */
183    protected final Lexer.LineInfoReceiver lineInfoReceiver;
184
185    private RecompilableScriptFunctionData reparsedFunction;
186
187    /**
188     * Constructor
189     *
190     * @param env     script environment
191     * @param source  source to parse
192     * @param errors  error manager
193     */
194    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors) {
195        this(env, source, errors, env._strict, null);
196    }
197
198    /**
199     * Constructor
200     *
201     * @param env     script environment
202     * @param source  source to parse
203     * @param errors  error manager
204     * @param strict  strict
205     * @param log debug logger if one is needed
206     */
207    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) {
208        this(env, source, errors, strict, 0, log);
209    }
210
211    /**
212     * Construct a parser.
213     *
214     * @param env     script environment
215     * @param source  source to parse
216     * @param errors  error manager
217     * @param strict  parser created with strict mode enabled.
218     * @param lineOffset line offset to start counting lines from
219     * @param log debug logger if one is needed
220     */
221    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) {
222        super(source, errors, strict, lineOffset);
223        this.lc = new ParserContext();
224        this.defaultNames = new ArrayDeque<>();
225        this.env = env;
226        this.namespace = new Namespace(env.getNamespace());
227        this.scripting = env._scripting;
228        if (this.scripting) {
229            this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
230                @Override
231                public void lineInfo(final int receiverLine, final int receiverLinePosition) {
232                    // update the parser maintained line information
233                    Parser.this.line = receiverLine;
234                    Parser.this.linePosition = receiverLinePosition;
235                }
236            };
237        } else {
238            // non-scripting mode script can't have multi-line literals
239            this.lineInfoReceiver = null;
240        }
241
242        this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
243    }
244
245    @Override
246    public DebugLogger getLogger() {
247        return log;
248    }
249
250    @Override
251    public DebugLogger initLogger(final Context context) {
252        return context.getLogger(this.getClass());
253    }
254
255    /**
256     * Sets the name for the first function. This is only used when reparsing anonymous functions to ensure they can
257     * preserve their already assigned name, as that name doesn't appear in their source text.
258     * @param name the name for the first parsed function.
259     */
260    public void setFunctionName(final String name) {
261        defaultNames.push(createIdentNode(0, 0, name));
262    }
263
264    /**
265     * Sets the {@link RecompilableScriptFunctionData} representing the function being reparsed (when this
266     * parser instance is used to reparse a previously parsed function, as part of its on-demand compilation).
267     * This will trigger various special behaviors, such as skipping nested function bodies.
268     * @param reparsedFunction the function being reparsed.
269     */
270    public void setReparsedFunction(final RecompilableScriptFunctionData reparsedFunction) {
271        this.reparsedFunction = reparsedFunction;
272    }
273
274    /**
275     * Execute parse and return the resulting function node.
276     * Errors will be thrown and the error manager will contain information
277     * if parsing should fail
278     *
279     * This is the default parse call, which will name the function node
280     * {code :program} {@link CompilerConstants#PROGRAM}
281     *
282     * @return function node resulting from successful parse
283     */
284    public FunctionNode parse() {
285        return parse(PROGRAM.symbolName(), 0, source.getLength(), 0);
286    }
287
288    /**
289     * Set up first token. Skips opening EOL.
290     */
291    private void scanFirstToken() {
292        k = -1;
293        next();
294    }
295
296    /**
297     * Execute parse and return the resulting function node.
298     * Errors will be thrown and the error manager will contain information
299     * if parsing should fail
300     *
301     * This should be used to create one and only one function node
302     *
303     * @param scriptName name for the script, given to the parsed FunctionNode
304     * @param startPos start position in source
305     * @param len length of parse
306     * @param reparseFlags flags provided by {@link RecompilableScriptFunctionData} as context for
307     * the code being reparsed. This allows us to recognize special forms of functions such
308     * as property getters and setters or instances of ES6 method shorthand in object literals.
309     *
310     * @return function node resulting from successful parse
311     */
312    public FunctionNode parse(final String scriptName, final int startPos, final int len, final int reparseFlags) {
313        final boolean isTimingEnabled = env.isTimingEnabled();
314        final long t0 = isTimingEnabled ? System.nanoTime() : 0L;
315        log.info(this, " begin for '", scriptName, "'");
316
317        try {
318            stream = new TokenStream();
319            lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
320            lexer.line = lexer.pendingLine = lineOffset + 1;
321            line = lineOffset;
322
323            scanFirstToken();
324            // Begin parse.
325            return program(scriptName, reparseFlags);
326        } catch (final Exception e) {
327            handleParseException(e);
328
329            return null;
330        } finally {
331            final String end = this + " end '" + scriptName + "'";
332            if (isTimingEnabled) {
333                env._timing.accumulateTime(toString(), System.nanoTime() - t0);
334                log.info(end, "' in ", Timing.toMillisPrint(System.nanoTime() - t0), " ms");
335            } else {
336                log.info(end);
337            }
338        }
339    }
340
341    /**
342     * Parse and return the resulting module.
343     * Errors will be thrown and the error manager will contain information
344     * if parsing should fail
345     *
346     * @param moduleName name for the module, given to the parsed FunctionNode
347     * @param startPos start position in source
348     * @param len length of parse
349     *
350     * @return function node resulting from successful parse
351     */
352    public FunctionNode parseModule(final String moduleName, final int startPos, final int len) {
353        try {
354            stream = new TokenStream();
355            lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
356            lexer.line = lexer.pendingLine = lineOffset + 1;
357            line = lineOffset;
358
359            scanFirstToken();
360            // Begin parse.
361            return module(moduleName);
362        } catch (final Exception e) {
363            handleParseException(e);
364
365            return null;
366        }
367    }
368
369    /**
370     * Entry point for parsing a module.
371     *
372     * @param moduleName the module name
373     * @return the parsed module
374     */
375    public FunctionNode parseModule(final String moduleName) {
376        return parseModule(moduleName, 0, source.getLength());
377    }
378
379    /**
380     * Parse and return the list of function parameter list. A comma
381     * separated list of function parameter identifiers is expected to be parsed.
382     * Errors will be thrown and the error manager will contain information
383     * if parsing should fail. This method is used to check if parameter Strings
384     * passed to "Function" constructor is a valid or not.
385     *
386     * @return the list of IdentNodes representing the formal parameter list
387     */
388    public List<IdentNode> parseFormalParameterList() {
389        try {
390            stream = new TokenStream();
391            lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
392
393            scanFirstToken();
394
395            return formalParameterList(TokenType.EOF, false);
396        } catch (final Exception e) {
397            handleParseException(e);
398            return null;
399        }
400    }
401
402    /**
403     * Execute parse and return the resulting function node.
404     * Errors will be thrown and the error manager will contain information
405     * if parsing should fail. This method is used to check if code String
406     * passed to "Function" constructor is a valid function body or not.
407     *
408     * @return function node resulting from successful parse
409     */
410    public FunctionNode parseFunctionBody() {
411        try {
412            stream = new TokenStream();
413            lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
414            final int functionLine = line;
415
416            scanFirstToken();
417
418            // Make a fake token for the function.
419            final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
420            // Set up the function to append elements.
421
422            final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName());
423            final ParserContextFunctionNode function = createParserContextFunctionNode(ident, functionToken, FunctionNode.Kind.NORMAL, functionLine, Collections.<IdentNode>emptyList());
424            lc.push(function);
425
426            final ParserContextBlockNode body = newBlock();
427
428            functionDeclarations = new ArrayList<>();
429            sourceElements(0);
430            addFunctionDeclarations(function);
431            functionDeclarations = null;
432
433            restoreBlock(body);
434            body.setFlag(Block.NEEDS_SCOPE);
435
436            final Block functionBody = new Block(functionToken, source.getLength() - 1,
437                body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
438            lc.pop(function);
439
440            expect(EOF);
441
442            final FunctionNode functionNode = createFunctionNode(
443                    function,
444                    functionToken,
445                    ident,
446                    Collections.<IdentNode>emptyList(),
447                    FunctionNode.Kind.NORMAL,
448                    functionLine,
449                    functionBody);
450            printAST(functionNode);
451            return functionNode;
452        } catch (final Exception e) {
453            handleParseException(e);
454            return null;
455        }
456    }
457
458    private void handleParseException(final Exception e) {
459        // Extract message from exception.  The message will be in error
460        // message format.
461        String message = e.getMessage();
462
463        // If empty message.
464        if (message == null) {
465            message = e.toString();
466        }
467
468        // Issue message.
469        if (e instanceof ParserException) {
470            errors.error((ParserException)e);
471        } else {
472            errors.error(message);
473        }
474
475        if (env._dump_on_error) {
476            e.printStackTrace(env.getErr());
477        }
478    }
479
480    /**
481     * Skip to a good parsing recovery point.
482     */
483    private void recover(final Exception e) {
484        if (e != null) {
485            // Extract message from exception.  The message will be in error
486            // message format.
487            String message = e.getMessage();
488
489            // If empty message.
490            if (message == null) {
491                message = e.toString();
492            }
493
494            // Issue message.
495            if (e instanceof ParserException) {
496                errors.error((ParserException)e);
497            } else {
498                errors.error(message);
499            }
500
501            if (env._dump_on_error) {
502                e.printStackTrace(env.getErr());
503            }
504        }
505
506        // Skip to a recovery point.
507        loop:
508        while (true) {
509            switch (type) {
510            case EOF:
511                // Can not go any further.
512                break loop;
513            case EOL:
514            case SEMICOLON:
515            case RBRACE:
516                // Good recovery points.
517                next();
518                break loop;
519            default:
520                // So we can recover after EOL.
521                nextOrEOL();
522                break;
523            }
524        }
525    }
526
527    /**
528     * Set up a new block.
529     *
530     * @return New block.
531     */
532    private ParserContextBlockNode newBlock() {
533        return lc.push(new ParserContextBlockNode(token));
534    }
535
536    private ParserContextFunctionNode createParserContextFunctionNode(final IdentNode ident, final long functionToken, final FunctionNode.Kind kind, final int functionLine, final List<IdentNode> parameters) {
537        // Build function name.
538        final StringBuilder sb = new StringBuilder();
539
540        final ParserContextFunctionNode parentFunction = lc.getCurrentFunction();
541        if (parentFunction != null && !parentFunction.isProgram()) {
542            sb.append(parentFunction.getName()).append(CompilerConstants.NESTED_FUNCTION_SEPARATOR.symbolName());
543        }
544
545        assert ident.getName() != null;
546        sb.append(ident.getName());
547
548        final String name = namespace.uniqueName(sb.toString());
549        assert parentFunction != null || kind == FunctionNode.Kind.MODULE || name.equals(PROGRAM.symbolName()) : "name = " + name;
550
551        int flags = 0;
552        if (isStrictMode) {
553            flags |= FunctionNode.IS_STRICT;
554        }
555        if (parentFunction == null) {
556            flags |= FunctionNode.IS_PROGRAM;
557        }
558
559        final ParserContextFunctionNode functionNode = new ParserContextFunctionNode(functionToken, ident, name, namespace, functionLine, kind, parameters);
560        functionNode.setFlag(flags);
561        return functionNode;
562    }
563
564    private FunctionNode createFunctionNode(final ParserContextFunctionNode function, final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine, final Block body) {
565        // assert body.isFunctionBody() || body.getFlag(Block.IS_PARAMETER_BLOCK) && ((BlockStatement) body.getLastStatement()).getBlock().isFunctionBody();
566        // Start new block.
567        final FunctionNode functionNode =
568            new FunctionNode(
569                source,
570                functionLine,
571                body.getToken(),
572                Token.descPosition(body.getToken()),
573                startToken,
574                function.getLastToken(),
575                namespace,
576                ident,
577                function.getName(),
578                parameters,
579                function.getParameterExpressions(),
580                kind,
581                function.getFlags(),
582                body,
583                function.getEndParserState(),
584                function.getModule(),
585                function.getDebugFlags());
586
587        printAST(functionNode);
588
589        return functionNode;
590    }
591
592    /**
593     * Restore the current block.
594     */
595    private ParserContextBlockNode restoreBlock(final ParserContextBlockNode block) {
596        return lc.pop(block);
597    }
598
599    /**
600     * Get the statements in a block.
601     * @return Block statements.
602     */
603    private Block getBlock(final boolean needsBraces) {
604        final long blockToken = token;
605        final ParserContextBlockNode newBlock = newBlock();
606        try {
607            // Block opening brace.
608            if (needsBraces) {
609                expect(LBRACE);
610            }
611            // Accumulate block statements.
612            statementList();
613
614        } finally {
615            restoreBlock(newBlock);
616        }
617
618        // Block closing brace.
619        if (needsBraces) {
620            expect(RBRACE);
621        }
622
623        final int flags = newBlock.getFlags() | (needsBraces ? 0 : Block.IS_SYNTHETIC);
624        return new Block(blockToken, finish, flags, newBlock.getStatements());
625    }
626
627    /**
628     * Get all the statements generated by a single statement.
629     * @return Statements.
630     */
631    private Block getStatement() {
632        return getStatement(false);
633    }
634
635    private Block getStatement(final boolean labelledStatement) {
636        if (type == LBRACE) {
637            return getBlock(true);
638        }
639        // Set up new block. Captures first token.
640        final ParserContextBlockNode newBlock = newBlock();
641        try {
642            statement(false, 0, true, labelledStatement);
643        } finally {
644            restoreBlock(newBlock);
645        }
646        return new Block(newBlock.getToken(), finish, newBlock.getFlags() | Block.IS_SYNTHETIC, newBlock.getStatements());
647    }
648
649    /**
650     * Detect calls to special functions.
651     * @param ident Called function.
652     */
653    private void detectSpecialFunction(final IdentNode ident) {
654        final String name = ident.getName();
655
656        if (EVAL.symbolName().equals(name)) {
657            markEval(lc);
658        } else if (SUPER.getName().equals(name)) {
659            assert ident.isDirectSuper();
660            markSuperCall(lc);
661        }
662    }
663
664    /**
665     * Detect use of special properties.
666     * @param ident Referenced property.
667     */
668    private void detectSpecialProperty(final IdentNode ident) {
669        if (isArguments(ident)) {
670            // skip over arrow functions, e.g. function f() { return (() => arguments.length)(); }
671            getCurrentNonArrowFunction().setFlag(FunctionNode.USES_ARGUMENTS);
672        }
673    }
674
675    private boolean useBlockScope() {
676        return env._es6;
677    }
678
679    private boolean isES6() {
680        return env._es6;
681    }
682
683    private static boolean isArguments(final String name) {
684        return ARGUMENTS_NAME.equals(name);
685    }
686
687    static boolean isArguments(final IdentNode ident) {
688        return isArguments(ident.getName());
689    }
690
691    /**
692     * Tells whether a IdentNode can be used as L-value of an assignment
693     *
694     * @param ident IdentNode to be checked
695     * @return whether the ident can be used as L-value
696     */
697    private static boolean checkIdentLValue(final IdentNode ident) {
698        return ident.tokenType().getKind() != TokenKind.KEYWORD;
699    }
700
701    /**
702     * Verify an assignment expression.
703     * @param op  Operation token.
704     * @param lhs Left hand side expression.
705     * @param rhs Right hand side expression.
706     * @return Verified expression.
707     */
708    private Expression verifyAssignment(final long op, final Expression lhs, final Expression rhs) {
709        final TokenType opType = Token.descType(op);
710
711        switch (opType) {
712        case ASSIGN:
713        case ASSIGN_ADD:
714        case ASSIGN_BIT_AND:
715        case ASSIGN_BIT_OR:
716        case ASSIGN_BIT_XOR:
717        case ASSIGN_DIV:
718        case ASSIGN_MOD:
719        case ASSIGN_MUL:
720        case ASSIGN_SAR:
721        case ASSIGN_SHL:
722        case ASSIGN_SHR:
723        case ASSIGN_SUB:
724            if (lhs instanceof IdentNode) {
725                if (!checkIdentLValue((IdentNode)lhs)) {
726                    return referenceError(lhs, rhs, false);
727                }
728                verifyIdent((IdentNode)lhs, "assignment");
729                break;
730            } else if (lhs instanceof AccessNode || lhs instanceof IndexNode) {
731                break;
732            } else if (opType == ASSIGN && isDestructuringLhs(lhs)) {
733                verifyDestructuringAssignmentPattern(lhs, "assignment");
734                break;
735            } else {
736                return referenceError(lhs, rhs, env._early_lvalue_error);
737            }
738        default:
739            break;
740        }
741
742        // Build up node.
743        if(BinaryNode.isLogical(opType)) {
744            return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs));
745        }
746        return new BinaryNode(op, lhs, rhs);
747    }
748
749    private boolean isDestructuringLhs(final Expression lhs) {
750        if (lhs instanceof ObjectNode || lhs instanceof LiteralNode.ArrayLiteralNode) {
751            return isES6();
752        }
753        return false;
754    }
755
756    private void verifyDestructuringAssignmentPattern(final Expression pattern, final String contextString) {
757        assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
758        pattern.accept(new VerifyDestructuringPatternNodeVisitor(new LexicalContext()) {
759            @Override
760            protected void verifySpreadElement(final Expression lvalue) {
761                if (!checkValidLValue(lvalue, contextString)) {
762                    throw error(AbstractParser.message("invalid.lvalue"), lvalue.getToken());
763                }
764            }
765
766            @Override
767            public boolean enterIdentNode(final IdentNode identNode) {
768                verifyIdent(identNode, contextString);
769                if (!checkIdentLValue(identNode)) {
770                    referenceError(identNode, null, true);
771                    return false;
772                }
773                return false;
774            }
775
776            @Override
777            public boolean enterAccessNode(final AccessNode accessNode) {
778                return false;
779            }
780
781            @Override
782            public boolean enterIndexNode(final IndexNode indexNode) {
783                return false;
784            }
785
786            @Override
787            protected boolean enterDefault(final Node node) {
788                throw error(String.format("unexpected node in AssignmentPattern: %s", node));
789            }
790        });
791    }
792
793    /**
794     * Reduce increment/decrement to simpler operations.
795     * @param firstToken First token.
796     * @param tokenType  Operation token (INCPREFIX/DEC.)
797     * @param expression Left hand side expression.
798     * @param isPostfix  Prefix or postfix.
799     * @return           Reduced expression.
800     */
801    private static UnaryNode incDecExpression(final long firstToken, final TokenType tokenType, final Expression expression, final boolean isPostfix) {
802        if (isPostfix) {
803            return new UnaryNode(Token.recast(firstToken, tokenType == DECPREFIX ? DECPOSTFIX : INCPOSTFIX), expression.getStart(), Token.descPosition(firstToken) + Token.descLength(firstToken), expression);
804        }
805
806        return new UnaryNode(firstToken, expression);
807    }
808
809    /**
810     * -----------------------------------------------------------------------
811     *
812     * Grammar based on
813     *
814     *      ECMAScript Language Specification
815     *      ECMA-262 5th Edition / December 2009
816     *
817     * -----------------------------------------------------------------------
818     */
819
820    /**
821     * Program :
822     *      SourceElements?
823     *
824     * See 14
825     *
826     * Parse the top level script.
827     */
828    private FunctionNode program(final String scriptName, final int reparseFlags) {
829        // Make a pseudo-token for the script holding its start and length.
830        final long functionToken = Token.toDesc(FUNCTION, Token.descPosition(Token.withDelimiter(token)), source.getLength());
831        final int  functionLine  = line;
832
833        final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), scriptName);
834        final ParserContextFunctionNode script = createParserContextFunctionNode(
835                ident,
836                functionToken,
837                FunctionNode.Kind.SCRIPT,
838                functionLine,
839                Collections.<IdentNode>emptyList());
840        lc.push(script);
841        final ParserContextBlockNode body = newBlock();
842
843        functionDeclarations = new ArrayList<>();
844        sourceElements(reparseFlags);
845        addFunctionDeclarations(script);
846        functionDeclarations = null;
847
848        restoreBlock(body);
849        body.setFlag(Block.NEEDS_SCOPE);
850        final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
851        lc.pop(script);
852        script.setLastToken(token);
853
854        expect(EOF);
855
856        return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.SCRIPT, functionLine, programBody);
857    }
858
859    /**
860     * Directive value or null if statement is not a directive.
861     *
862     * @param stmt Statement to be checked
863     * @return Directive value if the given statement is a directive
864     */
865    private String getDirective(final Node stmt) {
866        if (stmt instanceof ExpressionStatement) {
867            final Node expr = ((ExpressionStatement)stmt).getExpression();
868            if (expr instanceof LiteralNode) {
869                final LiteralNode<?> lit = (LiteralNode<?>)expr;
870                final long litToken = lit.getToken();
871                final TokenType tt = Token.descType(litToken);
872                // A directive is either a string or an escape string
873                if (tt == TokenType.STRING || tt == TokenType.ESCSTRING) {
874                    // Make sure that we don't unescape anything. Return as seen in source!
875                    return source.getString(lit.getStart(), Token.descLength(litToken));
876                }
877            }
878        }
879
880        return null;
881    }
882
883    /**
884     * SourceElements :
885     *      SourceElement
886     *      SourceElements SourceElement
887     *
888     * See 14
889     *
890     * Parse the elements of the script or function.
891     */
892    private void sourceElements(final int reparseFlags) {
893        List<Node>    directiveStmts        = null;
894        boolean       checkDirective        = true;
895        int           functionFlags          = reparseFlags;
896        final boolean oldStrictMode         = isStrictMode;
897
898
899        try {
900            // If is a script, then process until the end of the script.
901            while (type != EOF) {
902                // Break if the end of a code block.
903                if (type == RBRACE) {
904                    break;
905                }
906
907                try {
908                    // Get the next element.
909                    statement(true, functionFlags, false, false);
910                    functionFlags = 0;
911
912                    // check for directive prologues
913                    if (checkDirective) {
914                        // skip any debug statement like line number to get actual first line
915                        final Statement lastStatement = lc.getLastStatement();
916
917                        // get directive prologue, if any
918                        final String directive = getDirective(lastStatement);
919
920                        // If we have seen first non-directive statement,
921                        // no more directive statements!!
922                        checkDirective = directive != null;
923
924                        if (checkDirective) {
925                            if (!oldStrictMode) {
926                                if (directiveStmts == null) {
927                                    directiveStmts = new ArrayList<>();
928                                }
929                                directiveStmts.add(lastStatement);
930                            }
931
932                            // handle use strict directive
933                            if ("use strict".equals(directive)) {
934                                isStrictMode = true;
935                                final ParserContextFunctionNode function = lc.getCurrentFunction();
936                                function.setFlag(FunctionNode.IS_STRICT);
937
938                                // We don't need to check these, if lexical environment is already strict
939                                if (!oldStrictMode && directiveStmts != null) {
940                                    // check that directives preceding this one do not violate strictness
941                                    for (final Node statement : directiveStmts) {
942                                        // the get value will force unescape of preceding
943                                        // escaped string directives
944                                        getValue(statement.getToken());
945                                    }
946
947                                    // verify that function name as well as parameter names
948                                    // satisfy strict mode restrictions.
949                                    verifyIdent(function.getIdent(), "function name");
950                                    for (final IdentNode param : function.getParameters()) {
951                                        verifyIdent(param, "function parameter");
952                                    }
953                                }
954                            } else if (Context.DEBUG) {
955                                final int debugFlag = FunctionNode.getDirectiveFlag(directive);
956                                if (debugFlag != 0) {
957                                    final ParserContextFunctionNode function = lc.getCurrentFunction();
958                                    function.setDebugFlag(debugFlag);
959                                }
960                            }
961                        }
962                    }
963                } catch (final Exception e) {
964                    final int errorLine = line;
965                    final long errorToken = token;
966                    //recover parsing
967                    recover(e);
968                    final ErrorNode errorExpr = new ErrorNode(errorToken, finish);
969                    final ExpressionStatement expressionStatement = new ExpressionStatement(errorLine, errorToken, finish, errorExpr);
970                    appendStatement(expressionStatement);
971                }
972
973                // No backtracking from here on.
974                stream.commit(k);
975            }
976        } finally {
977            isStrictMode = oldStrictMode;
978        }
979    }
980
981    /**
982     * Parse any of the basic statement types.
983     *
984     * Statement :
985     *      BlockStatement
986     *      VariableStatement
987     *      EmptyStatement
988     *      ExpressionStatement
989     *      IfStatement
990     *      BreakableStatement
991     *      ContinueStatement
992     *      BreakStatement
993     *      ReturnStatement
994     *      WithStatement
995     *      LabelledStatement
996     *      ThrowStatement
997     *      TryStatement
998     *      DebuggerStatement
999     *
1000     * BreakableStatement :
1001     *      IterationStatement
1002     *      SwitchStatement
1003     *
1004     * BlockStatement :
1005     *      Block
1006     *
1007     * Block :
1008     *      { StatementList opt }
1009     *
1010     * StatementList :
1011     *      StatementListItem
1012     *      StatementList StatementListItem
1013     *
1014     * StatementItem :
1015     *      Statement
1016     *      Declaration
1017     *
1018     * Declaration :
1019     *     HoistableDeclaration
1020     *     ClassDeclaration
1021     *     LexicalDeclaration
1022     *
1023     * HoistableDeclaration :
1024     *     FunctionDeclaration
1025     *     GeneratorDeclaration
1026     */
1027    private void statement() {
1028        statement(false, 0, false, false);
1029    }
1030
1031    /**
1032     * @param topLevel does this statement occur at the "top level" of a script or a function?
1033     * @param reparseFlags reparse flags to decide whether to allow property "get" and "set" functions or ES6 methods.
1034     * @param singleStatement are we in a single statement context?
1035     */
1036    private void statement(final boolean topLevel, final int reparseFlags, final boolean singleStatement, final boolean labelledStatement) {
1037        switch (type) {
1038        case LBRACE:
1039            block();
1040            break;
1041        case VAR:
1042            variableStatement(type);
1043            break;
1044        case SEMICOLON:
1045            emptyStatement();
1046            break;
1047        case IF:
1048            ifStatement();
1049            break;
1050        case FOR:
1051            forStatement();
1052            break;
1053        case WHILE:
1054            whileStatement();
1055            break;
1056        case DO:
1057            doStatement();
1058            break;
1059        case CONTINUE:
1060            continueStatement();
1061            break;
1062        case BREAK:
1063            breakStatement();
1064            break;
1065        case RETURN:
1066            returnStatement();
1067            break;
1068        case WITH:
1069            withStatement();
1070            break;
1071        case SWITCH:
1072            switchStatement();
1073            break;
1074        case THROW:
1075            throwStatement();
1076            break;
1077        case TRY:
1078            tryStatement();
1079            break;
1080        case DEBUGGER:
1081            debuggerStatement();
1082            break;
1083        case RPAREN:
1084        case RBRACKET:
1085        case EOF:
1086            expect(SEMICOLON);
1087            break;
1088        case FUNCTION:
1089            // As per spec (ECMA section 12), function declarations as arbitrary statement
1090            // is not "portable". Implementation can issue a warning or disallow the same.
1091            if (singleStatement) {
1092                // ES6 B.3.2 Labelled Function Declarations
1093                // It is a Syntax Error if any strict mode source code matches this rule:
1094                // LabelledItem : FunctionDeclaration.
1095                if (!labelledStatement || isStrictMode) {
1096                    throw error(AbstractParser.message("expected.stmt", "function declaration"), token);
1097                }
1098            }
1099            functionExpression(true, topLevel || labelledStatement);
1100            return;
1101        default:
1102            if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(false) || type == CONST)) {
1103                if (singleStatement) {
1104                    throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
1105                }
1106                variableStatement(type);
1107                break;
1108            } else if (type == CLASS && isES6()) {
1109                if (singleStatement) {
1110                    throw error(AbstractParser.message("expected.stmt", "class declaration"), token);
1111                }
1112                classDeclaration(false);
1113                break;
1114            }
1115            if (env._const_as_var && type == CONST) {
1116                variableStatement(TokenType.VAR);
1117                break;
1118            }
1119
1120            if (type == IDENT || isNonStrictModeIdent()) {
1121                if (T(k + 1) == COLON) {
1122                    labelStatement();
1123                    return;
1124                }
1125
1126                if ((reparseFlags & ScriptFunctionData.IS_PROPERTY_ACCESSOR) != 0) {
1127                    final String ident = (String) getValue();
1128                    final long propertyToken = token;
1129                    final int propertyLine = line;
1130                    if (GET_NAME.equals(ident)) {
1131                        next();
1132                        addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
1133                        return;
1134                    } else if (SET_NAME.equals(ident)) {
1135                        next();
1136                        addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
1137                        return;
1138                    }
1139                }
1140            }
1141
1142            if ((reparseFlags & ScriptFunctionData.IS_ES6_METHOD) != 0
1143                    && (type == IDENT || type == LBRACKET || isNonStrictModeIdent())) {
1144                final String ident = (String)getValue();
1145                final long propertyToken = token;
1146                final int propertyLine = line;
1147                final Expression propertyKey = propertyName();
1148
1149                // Code below will need refinement once we fully support ES6 class syntax
1150                final int flags = CONSTRUCTOR_NAME.equals(ident) ? FunctionNode.ES6_IS_CLASS_CONSTRUCTOR : FunctionNode.ES6_IS_METHOD;
1151                addPropertyFunctionStatement(propertyMethodFunction(propertyKey, propertyToken, propertyLine, false, flags, false));
1152                return;
1153            }
1154
1155            expressionStatement();
1156            break;
1157        }
1158    }
1159
1160    private void addPropertyFunctionStatement(final PropertyFunction propertyFunction) {
1161        final FunctionNode fn = propertyFunction.functionNode;
1162        functionDeclarations.add(new ExpressionStatement(fn.getLineNumber(), fn.getToken(), finish, fn));
1163    }
1164
1165    /**
1166     * ClassDeclaration[Yield, Default] :
1167     *   class BindingIdentifier[?Yield] ClassTail[?Yield]
1168     *   [+Default] class ClassTail[?Yield]
1169     */
1170    private ClassNode classDeclaration(final boolean isDefault) {
1171        final int classLineNumber = line;
1172
1173        final ClassNode classExpression = classExpression(!isDefault);
1174
1175        if (!isDefault) {
1176            final VarNode classVar = new VarNode(classLineNumber, classExpression.getToken(), classExpression.getIdent().getFinish(), classExpression.getIdent(), classExpression, VarNode.IS_CONST);
1177            appendStatement(classVar);
1178        }
1179        return classExpression;
1180    }
1181
1182    /**
1183     * ClassExpression[Yield] :
1184     *   class BindingIdentifier[?Yield]opt ClassTail[?Yield]
1185     */
1186    private ClassNode classExpression(final boolean isStatement) {
1187        assert type == CLASS;
1188        final int classLineNumber = line;
1189        final long classToken = token;
1190        next();
1191
1192        IdentNode className = null;
1193        if (isStatement || type == IDENT) {
1194            className = getIdent();
1195        }
1196
1197        return classTail(classLineNumber, classToken, className, isStatement);
1198    }
1199
1200    private static final class ClassElementKey {
1201        private final boolean isStatic;
1202        private final String propertyName;
1203
1204        private ClassElementKey(final boolean isStatic, final String propertyName) {
1205            this.isStatic = isStatic;
1206            this.propertyName = propertyName;
1207        }
1208
1209        @Override
1210        public int hashCode() {
1211            final int prime = 31;
1212            int result = 1;
1213            result = prime * result + (isStatic ? 1231 : 1237);
1214            result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode());
1215            return result;
1216        }
1217
1218        @Override
1219        public boolean equals(final Object obj) {
1220            if (obj instanceof ClassElementKey) {
1221                final ClassElementKey other = (ClassElementKey) obj;
1222                return this.isStatic == other.isStatic && Objects.equals(this.propertyName, other.propertyName);
1223            }
1224            return false;
1225        }
1226    }
1227
1228    /**
1229     * Parse ClassTail and ClassBody.
1230     *
1231     * ClassTail[Yield] :
1232     *   ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
1233     * ClassHeritage[Yield] :
1234     *   extends LeftHandSideExpression[?Yield]
1235     *
1236     * ClassBody[Yield] :
1237     *   ClassElementList[?Yield]
1238     * ClassElementList[Yield] :
1239     *   ClassElement[?Yield]
1240     *   ClassElementList[?Yield] ClassElement[?Yield]
1241     * ClassElement[Yield] :
1242     *   MethodDefinition[?Yield]
1243     *   static MethodDefinition[?Yield]
1244     *   ;
1245     */
1246    private ClassNode classTail(final int classLineNumber, final long classToken,
1247            final IdentNode className, final boolean isStatement) {
1248        final boolean oldStrictMode = isStrictMode;
1249        isStrictMode = true;
1250        try {
1251            Expression classHeritage = null;
1252            if (type == EXTENDS) {
1253                next();
1254                classHeritage = leftHandSideExpression();
1255            }
1256
1257            expect(LBRACE);
1258
1259            PropertyNode constructor = null;
1260            final ArrayList<PropertyNode> classElements = new ArrayList<>();
1261            final Map<ClassElementKey, Integer> keyToIndexMap = new HashMap<>();
1262            for (;;) {
1263                if (type == SEMICOLON) {
1264                    next();
1265                    continue;
1266                }
1267                if (type == RBRACE) {
1268                    break;
1269                }
1270                final long classElementToken = token;
1271                boolean isStatic = false;
1272                if (type == STATIC) {
1273                    isStatic = true;
1274                    next();
1275                }
1276                boolean generator = false;
1277                if (isES6() && type == MUL) {
1278                    generator = true;
1279                    next();
1280                }
1281                final PropertyNode classElement = methodDefinition(isStatic, classHeritage != null, generator);
1282                if (classElement.isComputed()) {
1283                    classElements.add(classElement);
1284                } else if (!classElement.isStatic() && classElement.getKeyName().equals(CONSTRUCTOR_NAME)) {
1285                    if (constructor == null) {
1286                        constructor = classElement;
1287                    } else {
1288                        throw error(AbstractParser.message("multiple.constructors"), classElementToken);
1289                    }
1290                } else {
1291                    // Check for duplicate method definitions and combine accessor methods.
1292                    // In ES6, a duplicate is never an error regardless of strict mode (in consequence of computed property names).
1293
1294                    final ClassElementKey key = new ClassElementKey(classElement.isStatic(), classElement.getKeyName());
1295                    final Integer existing = keyToIndexMap.get(key);
1296
1297                    if (existing == null) {
1298                        keyToIndexMap.put(key, classElements.size());
1299                        classElements.add(classElement);
1300                    } else {
1301                        final PropertyNode existingProperty = classElements.get(existing);
1302
1303                        final Expression   value  = classElement.getValue();
1304                        final FunctionNode getter = classElement.getGetter();
1305                        final FunctionNode setter = classElement.getSetter();
1306
1307                        if (value != null || existingProperty.getValue() != null) {
1308                            keyToIndexMap.put(key, classElements.size());
1309                            classElements.add(classElement);
1310                        } else if (getter != null) {
1311                            assert existingProperty.getGetter() != null || existingProperty.getSetter() != null;
1312                            classElements.set(existing, existingProperty.setGetter(getter));
1313                        } else if (setter != null) {
1314                            assert existingProperty.getGetter() != null || existingProperty.getSetter() != null;
1315                            classElements.set(existing, existingProperty.setSetter(setter));
1316                        }
1317                    }
1318                }
1319            }
1320
1321            final long lastToken = token;
1322            expect(RBRACE);
1323
1324            if (constructor == null) {
1325                constructor = createDefaultClassConstructor(classLineNumber, classToken, lastToken, className, classHeritage != null);
1326            }
1327
1328            classElements.trimToSize();
1329            return new ClassNode(classLineNumber, classToken, finish, className, classHeritage, constructor, classElements, isStatement);
1330        } finally {
1331            isStrictMode = oldStrictMode;
1332        }
1333    }
1334
1335    private PropertyNode createDefaultClassConstructor(final int classLineNumber, final long classToken, final long lastToken, final IdentNode className, final boolean subclass) {
1336        final int ctorFinish = finish;
1337        final List<Statement> statements;
1338        final List<IdentNode> parameters;
1339        final long identToken = Token.recast(classToken, TokenType.IDENT);
1340        if (subclass) {
1341            final IdentNode superIdent = createIdentNode(identToken, ctorFinish, SUPER.getName()).setIsDirectSuper();
1342            final IdentNode argsIdent = createIdentNode(identToken, ctorFinish, "args").setIsRestParameter();
1343            final Expression spreadArgs = new UnaryNode(Token.recast(classToken, TokenType.SPREAD_ARGUMENT), argsIdent);
1344            final CallNode superCall = new CallNode(classLineNumber, classToken, ctorFinish, superIdent, Collections.singletonList(spreadArgs), false);
1345            statements = Collections.singletonList(new ExpressionStatement(classLineNumber, classToken, ctorFinish, superCall));
1346            parameters = Collections.singletonList(argsIdent);
1347        } else {
1348            statements = Collections.emptyList();
1349            parameters = Collections.emptyList();
1350        }
1351
1352        final Block body = new Block(classToken, ctorFinish, Block.IS_BODY, statements);
1353        final IdentNode ctorName = className != null ? className : createIdentNode(identToken, ctorFinish, CONSTRUCTOR_NAME);
1354        final ParserContextFunctionNode function = createParserContextFunctionNode(ctorName, classToken, FunctionNode.Kind.NORMAL, classLineNumber, parameters);
1355        function.setLastToken(lastToken);
1356
1357        function.setFlag(FunctionNode.ES6_IS_METHOD);
1358        function.setFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR);
1359        if (subclass) {
1360            function.setFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR);
1361            function.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
1362        }
1363        if (className == null) {
1364            function.setFlag(FunctionNode.IS_ANONYMOUS);
1365        }
1366
1367        final PropertyNode constructor = new PropertyNode(classToken, ctorFinish, ctorName, createFunctionNode(
1368                        function,
1369                        classToken,
1370                        ctorName,
1371                        parameters,
1372                        FunctionNode.Kind.NORMAL,
1373                        classLineNumber,
1374                        body
1375                        ), null, null, false, false);
1376        return constructor;
1377    }
1378
1379    private PropertyNode methodDefinition(final boolean isStatic, final boolean subclass, final boolean generator) {
1380        final long methodToken = token;
1381        final int methodLine = line;
1382        final boolean computed = type == LBRACKET;
1383        final boolean isIdent = type == IDENT;
1384        final Expression propertyName = propertyName();
1385        int flags = FunctionNode.ES6_IS_METHOD;
1386        if (!computed) {
1387            final String name = ((PropertyKey)propertyName).getPropertyName();
1388            if (!generator && isIdent && type != LPAREN && name.equals(GET_NAME)) {
1389                final PropertyFunction methodDefinition = propertyGetterFunction(methodToken, methodLine, flags);
1390                verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true);
1391                return new PropertyNode(methodToken, finish, methodDefinition.key, null, methodDefinition.functionNode, null, isStatic, methodDefinition.computed);
1392            } else if (!generator && isIdent && type != LPAREN && name.equals(SET_NAME)) {
1393                final PropertyFunction methodDefinition = propertySetterFunction(methodToken, methodLine, flags);
1394                verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true);
1395                return new PropertyNode(methodToken, finish, methodDefinition.key, null, null, methodDefinition.functionNode, isStatic, methodDefinition.computed);
1396            } else {
1397                if (!isStatic && !generator && name.equals(CONSTRUCTOR_NAME)) {
1398                    flags |= FunctionNode.ES6_IS_CLASS_CONSTRUCTOR;
1399                    if (subclass) {
1400                        flags |= FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR;
1401                    }
1402                }
1403                verifyAllowedMethodName(propertyName, isStatic, computed, generator, false);
1404            }
1405        }
1406        final PropertyFunction methodDefinition = propertyMethodFunction(propertyName, methodToken, methodLine, generator, flags, computed);
1407        return new PropertyNode(methodToken, finish, methodDefinition.key, methodDefinition.functionNode, null, null, isStatic, computed);
1408    }
1409
1410    /**
1411     * ES6 14.5.1 Static Semantics: Early Errors.
1412     */
1413    private void verifyAllowedMethodName(final Expression key, final boolean isStatic, final boolean computed, final boolean generator, final boolean accessor) {
1414        if (!computed) {
1415            if (!isStatic && generator && ((PropertyKey) key).getPropertyName().equals(CONSTRUCTOR_NAME)) {
1416                throw error(AbstractParser.message("generator.constructor"), key.getToken());
1417            }
1418            if (!isStatic && accessor && ((PropertyKey) key).getPropertyName().equals(CONSTRUCTOR_NAME)) {
1419                throw error(AbstractParser.message("accessor.constructor"), key.getToken());
1420            }
1421            if (isStatic && ((PropertyKey) key).getPropertyName().equals("prototype")) {
1422                throw error(AbstractParser.message("static.prototype.method"), key.getToken());
1423            }
1424        }
1425    }
1426
1427    /**
1428     * block :
1429     *      { StatementList? }
1430     *
1431     * see 12.1
1432     *
1433     * Parse a statement block.
1434     */
1435    private void block() {
1436        appendStatement(new BlockStatement(line, getBlock(true)));
1437    }
1438
1439    /**
1440     * StatementList :
1441     *      Statement
1442     *      StatementList Statement
1443     *
1444     * See 12.1
1445     *
1446     * Parse a list of statements.
1447     */
1448    private void statementList() {
1449        // Accumulate statements until end of list. */
1450        loop:
1451        while (type != EOF) {
1452            switch (type) {
1453            case EOF:
1454            case CASE:
1455            case DEFAULT:
1456            case RBRACE:
1457                break loop;
1458            default:
1459                break;
1460            }
1461
1462            // Get next statement.
1463            statement();
1464        }
1465    }
1466
1467    /**
1468     * Make sure that the identifier name used is allowed.
1469     *
1470     * @param ident         Identifier that is verified
1471     * @param contextString String used in error message to give context to the user
1472     */
1473    private void verifyIdent(final IdentNode ident, final String contextString) {
1474        verifyStrictIdent(ident, contextString);
1475        if (isES6()) {
1476            final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length());
1477            if (tokenType != IDENT && tokenType.getKind() != TokenKind.FUTURESTRICT) {
1478                throw error(expectMessage(IDENT));
1479            }
1480        }
1481    }
1482
1483    /**
1484     * Make sure that in strict mode, the identifier name used is allowed.
1485     *
1486     * @param ident         Identifier that is verified
1487     * @param contextString String used in error message to give context to the user
1488     */
1489    private void verifyStrictIdent(final IdentNode ident, final String contextString) {
1490        if (isStrictMode) {
1491            switch (ident.getName()) {
1492            case "eval":
1493            case "arguments":
1494                throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1495            default:
1496                break;
1497            }
1498
1499            if (ident.isFutureStrictName()) {
1500                throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1501            }
1502        }
1503    }
1504
1505    /*
1506     * VariableStatement :
1507     *      var VariableDeclarationList ;
1508     *
1509     * VariableDeclarationList :
1510     *      VariableDeclaration
1511     *      VariableDeclarationList , VariableDeclaration
1512     *
1513     * VariableDeclaration :
1514     *      Identifier Initializer?
1515     *
1516     * Initializer :
1517     *      = AssignmentExpression
1518     *
1519     * See 12.2
1520     *
1521     * Parse a VAR statement.
1522     * @param isStatement True if a statement (not used in a FOR.)
1523     */
1524    private void variableStatement(final TokenType varType) {
1525        variableDeclarationList(varType, true, -1);
1526    }
1527
1528    private static final class ForVariableDeclarationListResult {
1529        /** First missing const or binding pattern initializer. */
1530        Expression missingAssignment;
1531        /** First declaration with an initializer. */
1532        long declarationWithInitializerToken;
1533        /** Destructuring assignments. */
1534        Expression init;
1535        Expression firstBinding;
1536        Expression secondBinding;
1537
1538        void recordMissingAssignment(final Expression binding) {
1539            if (missingAssignment == null) {
1540                missingAssignment = binding;
1541            }
1542        }
1543
1544        void recordDeclarationWithInitializer(final long token) {
1545            if (declarationWithInitializerToken == 0L) {
1546                declarationWithInitializerToken = token;
1547            }
1548        }
1549
1550        void addBinding(final Expression binding) {
1551            if (firstBinding == null) {
1552                firstBinding = binding;
1553            } else if (secondBinding == null)  {
1554                secondBinding = binding;
1555            }
1556            // ignore the rest
1557        }
1558
1559        void addAssignment(final Expression assignment) {
1560            if (init == null) {
1561                init = assignment;
1562            } else {
1563                init = new BinaryNode(Token.recast(init.getToken(), COMMARIGHT), init, assignment);
1564            }
1565        }
1566    }
1567
1568    /**
1569     * @param isStatement {@code true} if a VariableStatement, {@code false} if a {@code for} loop VariableDeclarationList
1570     */
1571    private ForVariableDeclarationListResult variableDeclarationList(final TokenType varType, final boolean isStatement, final int sourceOrder) {
1572        // VAR tested in caller.
1573        assert varType == VAR || varType == LET || varType == CONST;
1574        final int varLine = line;
1575        final long varToken = token;
1576
1577        next();
1578
1579        int varFlags = 0;
1580        if (varType == LET) {
1581            varFlags |= VarNode.IS_LET;
1582        } else if (varType == CONST) {
1583            varFlags |= VarNode.IS_CONST;
1584        }
1585
1586        final ForVariableDeclarationListResult forResult = isStatement ? null : new ForVariableDeclarationListResult();
1587        while (true) {
1588            // Get name of var.
1589            if (type == YIELD && inGeneratorFunction()) {
1590                expect(IDENT);
1591            }
1592
1593            final String contextString = "variable name";
1594            final Expression binding = bindingIdentifierOrPattern(contextString);
1595            final boolean isDestructuring = !(binding instanceof IdentNode);
1596            if (isDestructuring) {
1597                final int finalVarFlags = varFlags;
1598                verifyDestructuringBindingPattern(binding, new Consumer<IdentNode>() {
1599                    @Override
1600                    public void accept(final IdentNode identNode) {
1601                        verifyIdent(identNode, contextString);
1602                        if (!env._parse_only) {
1603                            // don't bother adding a variable if we are just parsing!
1604                            final VarNode var = new VarNode(varLine, varToken, sourceOrder, identNode.getFinish(), identNode.setIsDeclaredHere(), null, finalVarFlags);
1605                            appendStatement(var);
1606                        }
1607                    }
1608                });
1609            }
1610
1611            // Assume no init.
1612            Expression init = null;
1613
1614            // Look for initializer assignment.
1615            if (type == ASSIGN) {
1616                if (!isStatement) {
1617                    forResult.recordDeclarationWithInitializer(varToken);
1618                }
1619                next();
1620
1621                // Get initializer expression. Suppress IN if not statement.
1622                if (!isDestructuring) {
1623                    defaultNames.push(binding);
1624                }
1625                try {
1626                    init = assignmentExpression(!isStatement);
1627                } finally {
1628                    if (!isDestructuring) {
1629                        defaultNames.pop();
1630                    }
1631                }
1632            } else if (isStatement) {
1633                if (isDestructuring) {
1634                    throw error(AbstractParser.message("missing.destructuring.assignment"), token);
1635                } else if (varType == CONST) {
1636                    throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)binding).getName()));
1637                }
1638                // else, if we are in a for loop, delay checking until we know the kind of loop
1639            }
1640
1641            if (!isDestructuring) {
1642                assert init != null || varType != CONST || !isStatement;
1643                final IdentNode ident = (IdentNode)binding;
1644                if (!isStatement && ident.getName().equals("let")) {
1645                    throw error(AbstractParser.message("let.binding.for")); //ES6 13.7.5.1
1646                }
1647                // Only set declaration flag on lexically scoped let/const as it adds runtime overhead.
1648                final IdentNode name = varType == LET || varType == CONST ? ident.setIsDeclaredHere() : ident;
1649                if (!isStatement) {
1650                    if (init == null && varType == CONST) {
1651                        forResult.recordMissingAssignment(name);
1652                    }
1653                    forResult.addBinding(new IdentNode(name));
1654                }
1655                final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name, init, varFlags);
1656                appendStatement(var);
1657            } else {
1658                assert init != null || !isStatement;
1659                if (init != null) {
1660                    final Expression assignment = verifyAssignment(Token.recast(varToken, ASSIGN), binding, init);
1661                    if (isStatement) {
1662                        appendStatement(new ExpressionStatement(varLine, assignment.getToken(), finish, assignment, varType));
1663                    } else {
1664                        forResult.addAssignment(assignment);
1665                        forResult.addBinding(assignment);
1666                    }
1667                } else if (!isStatement) {
1668                    forResult.recordMissingAssignment(binding);
1669                    forResult.addBinding(binding);
1670                }
1671            }
1672
1673            if (type != COMMARIGHT) {
1674                break;
1675            }
1676            next();
1677        }
1678
1679        // If is a statement then handle end of line.
1680        if (isStatement) {
1681            endOfLine();
1682        }
1683
1684        return forResult;
1685    }
1686
1687    private boolean isBindingIdentifier() {
1688        return type == IDENT || isNonStrictModeIdent();
1689    }
1690
1691    private IdentNode bindingIdentifier(final String contextString) {
1692        final IdentNode name = getIdent();
1693        verifyIdent(name, contextString);
1694        return name;
1695    }
1696
1697    private Expression bindingPattern() {
1698        if (type == LBRACKET) {
1699            return arrayLiteral();
1700        } else if (type == LBRACE) {
1701            return objectLiteral();
1702        } else {
1703            throw error(AbstractParser.message("expected.binding"));
1704        }
1705    }
1706
1707    private Expression bindingIdentifierOrPattern(final String contextString) {
1708        if (isBindingIdentifier() || !isES6()) {
1709            return bindingIdentifier(contextString);
1710        } else {
1711            return bindingPattern();
1712        }
1713    }
1714
1715    private abstract class VerifyDestructuringPatternNodeVisitor extends NodeVisitor<LexicalContext> {
1716        VerifyDestructuringPatternNodeVisitor(final LexicalContext lc) {
1717            super(lc);
1718        }
1719
1720        @Override
1721        public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
1722            if (literalNode.isArray()) {
1723                if (((LiteralNode.ArrayLiteralNode)literalNode).hasSpread() && ((LiteralNode.ArrayLiteralNode)literalNode).hasTrailingComma()) {
1724                    throw error("Rest element must be last", literalNode.getElementExpressions().get(literalNode.getElementExpressions().size() - 1).getToken());
1725                }
1726                boolean restElement = false;
1727                for (final Expression element : literalNode.getElementExpressions()) {
1728                    if (element != null) {
1729                        if (restElement) {
1730                            throw error("Unexpected element after rest element", element.getToken());
1731                        }
1732                        if (element.isTokenType(SPREAD_ARRAY)) {
1733                            restElement = true;
1734                            final Expression lvalue = ((UnaryNode) element).getExpression();
1735                            verifySpreadElement(lvalue);
1736                        }
1737                        element.accept(this);
1738                    }
1739                }
1740                return false;
1741            } else {
1742                return enterDefault(literalNode);
1743            }
1744        }
1745
1746        protected abstract void verifySpreadElement(Expression lvalue);
1747
1748        @Override
1749        public boolean enterObjectNode(final ObjectNode objectNode) {
1750            return true;
1751        }
1752
1753        @Override
1754        public boolean enterPropertyNode(final PropertyNode propertyNode) {
1755            if (propertyNode.getValue() != null) {
1756                propertyNode.getValue().accept(this);
1757                return false;
1758            } else {
1759                return enterDefault(propertyNode);
1760            }
1761        }
1762
1763        @Override
1764        public boolean enterBinaryNode(final BinaryNode binaryNode) {
1765            if (binaryNode.isTokenType(ASSIGN)) {
1766                binaryNode.lhs().accept(this);
1767                // Initializer(rhs) can be any AssignmentExpression
1768                return false;
1769            } else {
1770                return enterDefault(binaryNode);
1771            }
1772        }
1773
1774        @Override
1775        public boolean enterUnaryNode(final UnaryNode unaryNode) {
1776            if (unaryNode.isTokenType(SPREAD_ARRAY)) {
1777                // rest element
1778                return true;
1779            } else {
1780                return enterDefault(unaryNode);
1781            }
1782        }
1783    }
1784
1785    /**
1786     * Verify destructuring variable declaration binding pattern and extract bound variable declarations.
1787     */
1788    private void verifyDestructuringBindingPattern(final Expression pattern, final Consumer<IdentNode> identifierCallback) {
1789        assert (pattern instanceof BinaryNode && pattern.isTokenType(ASSIGN)) ||
1790                pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
1791        pattern.accept(new VerifyDestructuringPatternNodeVisitor(new LexicalContext()) {
1792            @Override
1793            protected void verifySpreadElement(final Expression lvalue) {
1794                if (lvalue instanceof IdentNode) {
1795                    // checked in identifierCallback
1796                } else if (isDestructuringLhs(lvalue)) {
1797                    verifyDestructuringBindingPattern(lvalue, identifierCallback);
1798                } else {
1799                    throw error("Expected a valid binding identifier", lvalue.getToken());
1800                }
1801            }
1802
1803            @Override
1804            public boolean enterIdentNode(final IdentNode identNode) {
1805                identifierCallback.accept(identNode);
1806                return false;
1807            }
1808
1809            @Override
1810            protected boolean enterDefault(final Node node) {
1811                throw error(String.format("unexpected node in BindingPattern: %s", node));
1812            }
1813        });
1814    }
1815
1816    /**
1817     * EmptyStatement :
1818     *      ;
1819     *
1820     * See 12.3
1821     *
1822     * Parse an empty statement.
1823     */
1824    private void emptyStatement() {
1825        if (env._empty_statements) {
1826            appendStatement(new EmptyNode(line, token, Token.descPosition(token) + Token.descLength(token)));
1827        }
1828
1829        // SEMICOLON checked in caller.
1830        next();
1831    }
1832
1833    /**
1834     * ExpressionStatement :
1835     *      Expression ; // [lookahead ~({ or  function )]
1836     *
1837     * See 12.4
1838     *
1839     * Parse an expression used in a statement block.
1840     */
1841    private void expressionStatement() {
1842        // Lookahead checked in caller.
1843        final int  expressionLine  = line;
1844        final long expressionToken = token;
1845
1846        // Get expression and add as statement.
1847        final Expression expression = expression();
1848
1849        if (expression != null) {
1850            final ExpressionStatement expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
1851            appendStatement(expressionStatement);
1852        } else {
1853            expect(null);
1854        }
1855
1856        endOfLine();
1857    }
1858
1859    /**
1860     * IfStatement :
1861     *      if ( Expression ) Statement else Statement
1862     *      if ( Expression ) Statement
1863     *
1864     * See 12.5
1865     *
1866     * Parse an IF statement.
1867     */
1868    private void ifStatement() {
1869        // Capture IF token.
1870        final int  ifLine  = line;
1871        final long ifToken = token;
1872         // IF tested in caller.
1873        next();
1874
1875        expect(LPAREN);
1876        final Expression test = expression();
1877        expect(RPAREN);
1878        final Block pass = getStatement();
1879
1880        Block fail = null;
1881        if (type == ELSE) {
1882            next();
1883            fail = getStatement();
1884        }
1885
1886        appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1887    }
1888
1889    /**
1890     * ... IterationStatement:
1891     *           ...
1892     *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1893     *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1894     *           for ( LeftHandSideExpression in Expression ) Statement
1895     *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1896     *
1897     * See 12.6
1898     *
1899     * Parse a FOR statement.
1900     */
1901    @SuppressWarnings("fallthrough")
1902    private void forStatement() {
1903        final long forToken = token;
1904        final int forLine = line;
1905        // start position of this for statement. This is used
1906        // for sort order for variables declared in the initializer
1907        // part of this 'for' statement (if any).
1908        final int forStart = Token.descPosition(forToken);
1909        // When ES6 for-let is enabled we create a container block to capture the LET.
1910        final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1911
1912        // Create FOR node, capturing FOR token.
1913        final ParserContextLoopNode forNode = new ParserContextLoopNode();
1914        lc.push(forNode);
1915        Block body = null;
1916        Expression init = null;
1917        JoinPredecessorExpression test = null;
1918        JoinPredecessorExpression modify = null;
1919        ForVariableDeclarationListResult varDeclList = null;
1920
1921        int flags = 0;
1922        boolean isForOf = false;
1923
1924        try {
1925            // FOR tested in caller.
1926            next();
1927
1928            // Nashorn extension: for each expression.
1929            // iterate property values rather than property names.
1930            if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1931                flags |= ForNode.IS_FOR_EACH;
1932                next();
1933            }
1934
1935            expect(LPAREN);
1936
1937            TokenType varType = null;
1938            switch (type) {
1939            case VAR:
1940                // Var declaration captured in for outer block.
1941                varDeclList = variableDeclarationList(varType = type, false, forStart);
1942                break;
1943            case SEMICOLON:
1944                break;
1945            default:
1946                if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(true) || type == CONST)) {
1947                    flags |= ForNode.PER_ITERATION_SCOPE;
1948                    // LET/CONST declaration captured in container block created above.
1949                    varDeclList = variableDeclarationList(varType = type, false, forStart);
1950                    break;
1951                }
1952                if (env._const_as_var && type == CONST) {
1953                    // Var declaration captured in for outer block.
1954                    varDeclList = variableDeclarationList(varType = TokenType.VAR, false, forStart);
1955                    break;
1956                }
1957
1958                init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1959                break;
1960            }
1961
1962            switch (type) {
1963            case SEMICOLON:
1964                // for (init; test; modify)
1965                if (varDeclList != null) {
1966                    assert init == null;
1967                    init = varDeclList.init;
1968                    // late check for missing assignment, now we know it's a for (init; test; modify) loop
1969                    if (varDeclList.missingAssignment != null) {
1970                        if (varDeclList.missingAssignment instanceof IdentNode) {
1971                            throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)varDeclList.missingAssignment).getName()));
1972                        } else {
1973                            throw error(AbstractParser.message("missing.destructuring.assignment"), varDeclList.missingAssignment.getToken());
1974                        }
1975                    }
1976                }
1977
1978                // for each (init; test; modify) is invalid
1979                if ((flags & ForNode.IS_FOR_EACH) != 0) {
1980                    throw error(AbstractParser.message("for.each.without.in"), token);
1981                }
1982
1983                expect(SEMICOLON);
1984                if (type != SEMICOLON) {
1985                    test = joinPredecessorExpression();
1986                }
1987                expect(SEMICOLON);
1988                if (type != RPAREN) {
1989                    modify = joinPredecessorExpression();
1990                }
1991                break;
1992
1993            case IDENT:
1994                if (env._es6 && "of".equals(getValue())) {
1995                    isForOf = true;
1996                    // fall through
1997                } else {
1998                    expect(SEMICOLON); // fail with expected message
1999                    break;
2000                }
2001            case IN:
2002                flags |= isForOf ? ForNode.IS_FOR_OF : ForNode.IS_FOR_IN;
2003                test = new JoinPredecessorExpression();
2004                if (varDeclList != null) {
2005                    // for (var|let|const ForBinding in|of expression)
2006                    if (varDeclList.secondBinding != null) {
2007                        // for (var i, j in obj) is invalid
2008                        throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), varDeclList.secondBinding.getToken());
2009                    }
2010                    if (varDeclList.declarationWithInitializerToken != 0 && (isStrictMode || type != TokenType.IN || varType != VAR || varDeclList.init != null)) {
2011                        // ES5 legacy: for (var i = AssignmentExpressionNoIn in Expression)
2012                        // Invalid in ES6, but allow it in non-strict mode if no ES6 features used,
2013                        // i.e., error if strict, for-of, let/const, or destructuring
2014                        throw error(AbstractParser.message("for.in.loop.initializer", isForOf ? "of" : "in"), varDeclList.declarationWithInitializerToken);
2015                    }
2016                    init = varDeclList.firstBinding;
2017                    assert init instanceof IdentNode || isDestructuringLhs(init);
2018                } else {
2019                    // for (expr in obj)
2020                    assert init != null : "for..in/of init expression can not be null here";
2021
2022                    // check if initial expression is a valid L-value
2023                    if (!checkValidLValue(init, isForOf ? "for-of iterator" : "for-in iterator")) {
2024                        throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
2025                    }
2026                }
2027
2028                next();
2029
2030                // For-of only allows AssignmentExpression.
2031                modify = isForOf ? new JoinPredecessorExpression(assignmentExpression(false)) : joinPredecessorExpression();
2032                break;
2033
2034            default:
2035                expect(SEMICOLON);
2036                break;
2037            }
2038
2039            expect(RPAREN);
2040
2041            // Set the for body.
2042            body = getStatement();
2043        } finally {
2044            lc.pop(forNode);
2045
2046            for (final Statement var : forNode.getStatements()) {
2047                assert var instanceof VarNode;
2048                appendStatement(var);
2049            }
2050            if (body != null) {
2051                appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
2052            }
2053            if (outer != null) {
2054                restoreBlock(outer);
2055                if (body != null) {
2056                    appendStatement(new BlockStatement(forLine, new Block(
2057                                    outer.getToken(),
2058                                    body.getFinish(),
2059                                    outer.getStatements())));
2060                }
2061            }
2062        }
2063    }
2064
2065    private boolean checkValidLValue(final Expression init, final String contextString) {
2066        if (init instanceof IdentNode) {
2067            if (!checkIdentLValue((IdentNode)init)) {
2068                return false;
2069            }
2070            verifyIdent((IdentNode)init, contextString);
2071            return true;
2072        } else if (init instanceof AccessNode || init instanceof IndexNode) {
2073            return true;
2074        } else if (isDestructuringLhs(init)) {
2075            verifyDestructuringAssignmentPattern(init, contextString);
2076            return true;
2077        } else {
2078            return false;
2079        }
2080    }
2081
2082    @SuppressWarnings("fallthrough")
2083    private boolean lookaheadIsLetDeclaration(final boolean ofContextualKeyword) {
2084        assert type == LET;
2085        for (int i = 1;; i++) {
2086            final TokenType t = T(k + i);
2087            switch (t) {
2088            case EOL:
2089            case COMMENT:
2090                continue;
2091            case IDENT:
2092                if (ofContextualKeyword && isES6() && "of".equals(getValue(getToken(k + i)))) {
2093                    return false;
2094                }
2095                // fall through
2096            case LBRACKET:
2097            case LBRACE:
2098                return true;
2099            default:
2100                // accept future strict tokens in non-strict mode (including LET)
2101                if (!isStrictMode && t.getKind() == TokenKind.FUTURESTRICT) {
2102                    return true;
2103                }
2104                return false;
2105            }
2106        }
2107    }
2108
2109    /**
2110     * ...IterationStatement :
2111     *           ...
2112     *           while ( Expression ) Statement
2113     *           ...
2114     *
2115     * See 12.6
2116     *
2117     * Parse while statement.
2118     */
2119    private void whileStatement() {
2120        // Capture WHILE token.
2121        final long whileToken = token;
2122        final int whileLine = line;
2123        // WHILE tested in caller.
2124        next();
2125
2126        final ParserContextLoopNode whileNode = new ParserContextLoopNode();
2127        lc.push(whileNode);
2128
2129        JoinPredecessorExpression test = null;
2130        Block body = null;
2131
2132        try {
2133            expect(LPAREN);
2134            test = joinPredecessorExpression();
2135            expect(RPAREN);
2136            body = getStatement();
2137        } finally {
2138            lc.pop(whileNode);
2139        }
2140
2141        if (body != null) {
2142            appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
2143        }
2144    }
2145
2146    /**
2147     * ...IterationStatement :
2148     *           ...
2149     *           do Statement while( Expression ) ;
2150     *           ...
2151     *
2152     * See 12.6
2153     *
2154     * Parse DO WHILE statement.
2155     */
2156    private void doStatement() {
2157        // Capture DO token.
2158        final long doToken = token;
2159        int doLine = 0;
2160        // DO tested in the caller.
2161        next();
2162
2163        final ParserContextLoopNode doWhileNode = new ParserContextLoopNode();
2164        lc.push(doWhileNode);
2165
2166        Block body = null;
2167        JoinPredecessorExpression test = null;
2168
2169        try {
2170           // Get DO body.
2171            body = getStatement();
2172
2173            expect(WHILE);
2174            expect(LPAREN);
2175            doLine = line;
2176            test = joinPredecessorExpression();
2177            expect(RPAREN);
2178
2179            if (type == SEMICOLON) {
2180                endOfLine();
2181            }
2182        } finally {
2183            lc.pop(doWhileNode);
2184        }
2185
2186        appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
2187    }
2188
2189    /**
2190     * ContinueStatement :
2191     *      continue Identifier? ; // [no LineTerminator here]
2192     *
2193     * See 12.7
2194     *
2195     * Parse CONTINUE statement.
2196     */
2197    private void continueStatement() {
2198        // Capture CONTINUE token.
2199        final int  continueLine  = line;
2200        final long continueToken = token;
2201        // CONTINUE tested in caller.
2202        nextOrEOL();
2203
2204        ParserContextLabelNode labelNode = null;
2205
2206        // SEMICOLON or label.
2207        switch (type) {
2208        case RBRACE:
2209        case SEMICOLON:
2210        case EOL:
2211        case EOF:
2212            break;
2213
2214        default:
2215            final IdentNode ident = getIdent();
2216            labelNode = lc.findLabel(ident.getName());
2217
2218            if (labelNode == null) {
2219                throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
2220            }
2221
2222            break;
2223        }
2224
2225        final String labelName = labelNode == null ? null : labelNode.getLabelName();
2226        final ParserContextLoopNode targetNode = lc.getContinueTo(labelName);
2227
2228        if (targetNode == null) {
2229            throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
2230        }
2231
2232        endOfLine();
2233
2234        // Construct and add CONTINUE node.
2235        appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
2236    }
2237
2238    /**
2239     * BreakStatement :
2240     *      break Identifier? ; // [no LineTerminator here]
2241     *
2242     * See 12.8
2243     *
2244     */
2245    private void breakStatement() {
2246        // Capture BREAK token.
2247        final int  breakLine  = line;
2248        final long breakToken = token;
2249        // BREAK tested in caller.
2250        nextOrEOL();
2251
2252        ParserContextLabelNode labelNode = null;
2253
2254        // SEMICOLON or label.
2255        switch (type) {
2256        case RBRACE:
2257        case SEMICOLON:
2258        case EOL:
2259        case EOF:
2260            break;
2261
2262        default:
2263            final IdentNode ident = getIdent();
2264            labelNode = lc.findLabel(ident.getName());
2265
2266            if (labelNode == null) {
2267                throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
2268            }
2269
2270            break;
2271        }
2272
2273        //either an explicit label - then get its node or just a "break" - get first breakable
2274        //targetNode is what we are breaking out from.
2275        final String labelName = labelNode == null ? null : labelNode.getLabelName();
2276        final ParserContextBreakableNode targetNode = lc.getBreakable(labelName);
2277        if (targetNode == null) {
2278            throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
2279        }
2280
2281        endOfLine();
2282
2283        // Construct and add BREAK node.
2284        appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
2285    }
2286
2287    /**
2288     * ReturnStatement :
2289     *      return Expression? ; // [no LineTerminator here]
2290     *
2291     * See 12.9
2292     *
2293     * Parse RETURN statement.
2294     */
2295    private void returnStatement() {
2296        // check for return outside function
2297        if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT || lc.getCurrentFunction().getKind() == FunctionNode.Kind.MODULE) {
2298            throw error(AbstractParser.message("invalid.return"));
2299        }
2300
2301        // Capture RETURN token.
2302        final int  returnLine  = line;
2303        final long returnToken = token;
2304        // RETURN tested in caller.
2305        nextOrEOL();
2306
2307        Expression expression = null;
2308
2309        // SEMICOLON or expression.
2310        switch (type) {
2311        case RBRACE:
2312        case SEMICOLON:
2313        case EOL:
2314        case EOF:
2315            break;
2316
2317        default:
2318            expression = expression();
2319            break;
2320        }
2321
2322        endOfLine();
2323
2324        // Construct and add RETURN node.
2325        appendStatement(new ReturnNode(returnLine, returnToken, finish, expression));
2326    }
2327
2328    /**
2329     * Parse YieldExpression.
2330     *
2331     * YieldExpression[In] :
2332     *   yield
2333     *   yield [no LineTerminator here] AssignmentExpression[?In, Yield]
2334     *   yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
2335     */
2336    @SuppressWarnings("fallthrough")
2337    private Expression yieldExpression(final boolean noIn) {
2338        assert inGeneratorFunction();
2339        // Capture YIELD token.
2340        long yieldToken = token;
2341        // YIELD tested in caller.
2342        assert type == YIELD;
2343        nextOrEOL();
2344
2345        Expression expression = null;
2346
2347        boolean yieldAsterisk = false;
2348        if (type == MUL) {
2349            yieldAsterisk = true;
2350            yieldToken = Token.recast(yieldToken, YIELD_STAR);
2351            next();
2352        }
2353
2354        switch (type) {
2355        case RBRACE:
2356        case SEMICOLON:
2357        case EOL:
2358        case EOF:
2359        case COMMARIGHT:
2360        case RPAREN:
2361        case RBRACKET:
2362        case COLON:
2363            if (!yieldAsterisk) {
2364                // treat (yield) as (yield void 0)
2365                expression = newUndefinedLiteral(yieldToken, finish);
2366                if (type == EOL) {
2367                    next();
2368                }
2369                break;
2370            } else {
2371                // AssignmentExpression required, fall through
2372            }
2373
2374        default:
2375            expression = assignmentExpression(noIn);
2376            break;
2377        }
2378
2379        // Construct and add YIELD node.
2380        return new UnaryNode(yieldToken, expression);
2381    }
2382
2383    private static UnaryNode newUndefinedLiteral(final long token, final int finish) {
2384        return new UnaryNode(Token.recast(token, VOID), LiteralNode.newInstance(token, finish, 0));
2385    }
2386
2387    /**
2388     * WithStatement :
2389     *      with ( Expression ) Statement
2390     *
2391     * See 12.10
2392     *
2393     * Parse WITH statement.
2394     */
2395    private void withStatement() {
2396        // Capture WITH token.
2397        final int  withLine  = line;
2398        final long withToken = token;
2399        // WITH tested in caller.
2400        next();
2401
2402        // ECMA 12.10.1 strict mode restrictions
2403        if (isStrictMode) {
2404            throw error(AbstractParser.message("strict.no.with"), withToken);
2405        }
2406
2407        expect(LPAREN);
2408        final Expression expression = expression();
2409        expect(RPAREN);
2410        final Block body = getStatement();
2411
2412        appendStatement(new WithNode(withLine, withToken, finish, expression, body));
2413    }
2414
2415    /**
2416     * SwitchStatement :
2417     *      switch ( Expression ) CaseBlock
2418     *
2419     * CaseBlock :
2420     *      { CaseClauses? }
2421     *      { CaseClauses? DefaultClause CaseClauses }
2422     *
2423     * CaseClauses :
2424     *      CaseClause
2425     *      CaseClauses CaseClause
2426     *
2427     * CaseClause :
2428     *      case Expression : StatementList?
2429     *
2430     * DefaultClause :
2431     *      default : StatementList?
2432     *
2433     * See 12.11
2434     *
2435     * Parse SWITCH statement.
2436     */
2437    private void switchStatement() {
2438        final int  switchLine  = line;
2439        final long switchToken = token;
2440
2441        // Block to capture variables declared inside the switch statement.
2442        final ParserContextBlockNode switchBlock = newBlock();
2443
2444        // SWITCH tested in caller.
2445        next();
2446
2447        // Create and add switch statement.
2448        final ParserContextSwitchNode switchNode = new ParserContextSwitchNode();
2449        lc.push(switchNode);
2450
2451        CaseNode defaultCase = null;
2452        // Prepare to accumulate cases.
2453        final List<CaseNode> cases = new ArrayList<>();
2454
2455        Expression expression = null;
2456
2457        try {
2458            expect(LPAREN);
2459            expression = expression();
2460            expect(RPAREN);
2461
2462            expect(LBRACE);
2463
2464
2465            while (type != RBRACE) {
2466                // Prepare for next case.
2467                Expression caseExpression = null;
2468                final long caseToken = token;
2469
2470                switch (type) {
2471                case CASE:
2472                    next();
2473                    caseExpression = expression();
2474                    break;
2475
2476                case DEFAULT:
2477                    if (defaultCase != null) {
2478                        throw error(AbstractParser.message("duplicate.default.in.switch"));
2479                    }
2480                    next();
2481                    break;
2482
2483                default:
2484                    // Force an error.
2485                    expect(CASE);
2486                    break;
2487                }
2488
2489                expect(COLON);
2490
2491                // Get CASE body.
2492                final Block statements = getBlock(false); // TODO: List<Statement> statements = caseStatementList();
2493                final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
2494
2495                if (caseExpression == null) {
2496                    defaultCase = caseNode;
2497                }
2498
2499                cases.add(caseNode);
2500            }
2501
2502            next();
2503        } finally {
2504            lc.pop(switchNode);
2505            restoreBlock(switchBlock);
2506        }
2507
2508        final SwitchNode switchStatement = new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase);
2509        appendStatement(new BlockStatement(switchLine, new Block(switchToken, finish, switchBlock.getFlags() | Block.IS_SYNTHETIC | Block.IS_SWITCH_BLOCK, switchStatement)));
2510    }
2511
2512    /**
2513     * LabelledStatement :
2514     *      Identifier : Statement
2515     *
2516     * See 12.12
2517     *
2518     * Parse label statement.
2519     */
2520    private void labelStatement() {
2521        // Capture label token.
2522        final long labelToken = token;
2523        // Get label ident.
2524        final IdentNode ident = getIdent();
2525
2526        expect(COLON);
2527
2528        if (lc.findLabel(ident.getName()) != null) {
2529            throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
2530        }
2531
2532        final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName());
2533        Block body = null;
2534        try {
2535            lc.push(labelNode);
2536            body = getStatement(true);
2537        } finally {
2538            assert lc.peek() instanceof ParserContextLabelNode;
2539            lc.pop(labelNode);
2540        }
2541
2542        appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
2543    }
2544
2545    /**
2546     * ThrowStatement :
2547     *      throw Expression ; // [no LineTerminator here]
2548     *
2549     * See 12.13
2550     *
2551     * Parse throw statement.
2552     */
2553    private void throwStatement() {
2554        // Capture THROW token.
2555        final int  throwLine  = line;
2556        final long throwToken = token;
2557        // THROW tested in caller.
2558        nextOrEOL();
2559
2560        Expression expression = null;
2561
2562        // SEMICOLON or expression.
2563        switch (type) {
2564        case RBRACE:
2565        case SEMICOLON:
2566        case EOL:
2567            break;
2568
2569        default:
2570            expression = expression();
2571            break;
2572        }
2573
2574        if (expression == null) {
2575            throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2576        }
2577
2578        endOfLine();
2579
2580        appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
2581    }
2582
2583    /**
2584     * TryStatement :
2585     *      try Block Catch
2586     *      try Block Finally
2587     *      try Block Catch Finally
2588     *
2589     * Catch :
2590     *      catch( Identifier if Expression ) Block
2591     *      catch( Identifier ) Block
2592     *
2593     * Finally :
2594     *      finally Block
2595     *
2596     * See 12.14
2597     *
2598     * Parse TRY statement.
2599     */
2600    private void tryStatement() {
2601        // Capture TRY token.
2602        final int  tryLine  = line;
2603        final long tryToken = token;
2604        // TRY tested in caller.
2605        next();
2606
2607        // Container block needed to act as target for labeled break statements
2608        final int startLine = line;
2609        final ParserContextBlockNode outer = newBlock();
2610        // Create try.
2611
2612        try {
2613            final Block       tryBody     = getBlock(true);
2614            final List<Block> catchBlocks = new ArrayList<>();
2615
2616            while (type == CATCH) {
2617                final int  catchLine  = line;
2618                final long catchToken = token;
2619                next();
2620                expect(LPAREN);
2621
2622                // ES6 catch parameter can be a BindingIdentifier or a BindingPattern
2623                // http://www.ecma-international.org/ecma-262/6.0/
2624                final String contextString = "catch argument";
2625                final Expression exception = bindingIdentifierOrPattern(contextString);
2626                final boolean isDestructuring = !(exception instanceof IdentNode);
2627                if (isDestructuring) {
2628                    verifyDestructuringBindingPattern(exception, new Consumer<IdentNode>() {
2629                        @Override
2630                        public void accept(final IdentNode identNode) {
2631                            verifyIdent(identNode, contextString);
2632                        }
2633                    });
2634                } else {
2635                    // ECMA 12.4.1 strict mode restrictions
2636                    verifyStrictIdent((IdentNode) exception, "catch argument");
2637                }
2638
2639
2640                // Nashorn extension: catch clause can have optional
2641                // condition. So, a single try can have more than one
2642                // catch clause each with it's own condition.
2643                final Expression ifExpression;
2644                if (!env._no_syntax_extensions && type == IF) {
2645                    next();
2646                    // Get the exception condition.
2647                    ifExpression = expression();
2648                } else {
2649                    ifExpression = null;
2650                }
2651
2652                expect(RPAREN);
2653
2654                final ParserContextBlockNode catchBlock = newBlock();
2655                try {
2656                    // Get CATCH body.
2657                    final Block catchBody = getBlock(true);
2658                    final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
2659                    appendStatement(catchNode);
2660                } finally {
2661                    restoreBlock(catchBlock);
2662                    catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements()));
2663                }
2664
2665                // If unconditional catch then should to be the end.
2666                if (ifExpression == null) {
2667                    break;
2668                }
2669            }
2670
2671            // Prepare to capture finally statement.
2672            Block finallyStatements = null;
2673
2674            if (type == FINALLY) {
2675                next();
2676                finallyStatements = getBlock(true);
2677            }
2678
2679            // Need at least one catch or a finally.
2680            if (catchBlocks.isEmpty() && finallyStatements == null) {
2681                throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
2682            }
2683
2684            final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
2685            // Add try.
2686            assert lc.peek() == outer;
2687            appendStatement(tryNode);
2688        } finally {
2689            restoreBlock(outer);
2690        }
2691
2692        appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements())));
2693    }
2694
2695    /**
2696     * DebuggerStatement :
2697     *      debugger ;
2698     *
2699     * See 12.15
2700     *
2701     * Parse debugger statement.
2702     */
2703    private void  debuggerStatement() {
2704        // Capture DEBUGGER token.
2705        final int  debuggerLine  = line;
2706        final long debuggerToken = token;
2707        // DEBUGGER tested in caller.
2708        next();
2709        endOfLine();
2710        appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish));
2711    }
2712
2713    /**
2714     * PrimaryExpression :
2715     *      this
2716     *      IdentifierReference
2717     *      Literal
2718     *      ArrayLiteral
2719     *      ObjectLiteral
2720     *      RegularExpressionLiteral
2721     *      TemplateLiteral
2722     *      CoverParenthesizedExpressionAndArrowParameterList
2723     *
2724     * CoverParenthesizedExpressionAndArrowParameterList :
2725     *      ( Expression )
2726     *      ( )
2727     *      ( ... BindingIdentifier )
2728     *      ( Expression , ... BindingIdentifier )
2729     *
2730     * Parse primary expression.
2731     * @return Expression node.
2732     */
2733    @SuppressWarnings("fallthrough")
2734    private Expression primaryExpression() {
2735        // Capture first token.
2736        final int  primaryLine  = line;
2737        final long primaryToken = token;
2738
2739        switch (type) {
2740        case THIS:
2741            final String name = type.getName();
2742            next();
2743            markThis(lc);
2744            return new IdentNode(primaryToken, finish, name);
2745        case IDENT:
2746            final IdentNode ident = getIdent();
2747            if (ident == null) {
2748                break;
2749            }
2750            detectSpecialProperty(ident);
2751            return ident;
2752        case OCTAL_LEGACY:
2753            if (isStrictMode) {
2754               throw error(AbstractParser.message("strict.no.octal"), token);
2755            }
2756        case STRING:
2757        case ESCSTRING:
2758        case DECIMAL:
2759        case HEXADECIMAL:
2760        case OCTAL:
2761        case BINARY_NUMBER:
2762        case FLOATING:
2763        case REGEX:
2764        case XML:
2765            return getLiteral();
2766        case EXECSTRING:
2767            return execString(primaryLine, primaryToken);
2768        case FALSE:
2769            next();
2770            return LiteralNode.newInstance(primaryToken, finish, false);
2771        case TRUE:
2772            next();
2773            return LiteralNode.newInstance(primaryToken, finish, true);
2774        case NULL:
2775            next();
2776            return LiteralNode.newInstance(primaryToken, finish);
2777        case LBRACKET:
2778            return arrayLiteral();
2779        case LBRACE:
2780            return objectLiteral();
2781        case LPAREN:
2782            next();
2783
2784            if (isES6()) {
2785                if (type == RPAREN) {
2786                    // ()
2787                    nextOrEOL();
2788                    expectDontAdvance(ARROW);
2789                    return new ExpressionList(primaryToken, finish, Collections.emptyList());
2790                } else if (type == ELLIPSIS) {
2791                    // (...rest)
2792                    final IdentNode restParam = formalParameterList(false).get(0);
2793                    expectDontAdvance(RPAREN);
2794                    nextOrEOL();
2795                    expectDontAdvance(ARROW);
2796                    return new ExpressionList(primaryToken, finish, Collections.singletonList(restParam));
2797                }
2798            }
2799
2800            final Expression expression = expression();
2801
2802            expect(RPAREN);
2803
2804            return expression;
2805        case TEMPLATE:
2806        case TEMPLATE_HEAD:
2807            return templateLiteral();
2808
2809        default:
2810            // In this context some operator tokens mark the start of a literal.
2811            if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
2812                next();
2813                return getLiteral();
2814            }
2815            if (isNonStrictModeIdent()) {
2816                return getIdent();
2817            }
2818            break;
2819        }
2820
2821        return null;
2822    }
2823
2824    /**
2825     * Convert execString to a call to $EXEC.
2826     *
2827     * @param primaryToken Original string token.
2828     * @return callNode to $EXEC.
2829     */
2830    CallNode execString(final int primaryLine, final long primaryToken) {
2831        // Synthesize an ident to call $EXEC.
2832        final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
2833        // Skip over EXECSTRING.
2834        next();
2835        // Set up argument list for call.
2836        // Skip beginning of edit string expression.
2837        expect(LBRACE);
2838        // Add the following expression to arguments.
2839        final List<Expression> arguments = Collections.singletonList(expression());
2840        // Skip ending of edit string expression.
2841        expect(RBRACE);
2842
2843        return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
2844    }
2845
2846    /**
2847     * ArrayLiteral :
2848     *      [ Elision? ]
2849     *      [ ElementList ]
2850     *      [ ElementList , Elision? ]
2851     *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
2852     *
2853     * ElementList : Elision? AssignmentExpression
2854     *      ElementList , Elision? AssignmentExpression
2855     *
2856     * Elision :
2857     *      ,
2858     *      Elision ,
2859     *
2860     * See 12.1.4
2861     * JavaScript 1.8
2862     *
2863     * Parse array literal.
2864     * @return Expression node.
2865     */
2866    @SuppressWarnings("fallthrough")
2867    private LiteralNode<Expression[]> arrayLiteral() {
2868        // Capture LBRACKET token.
2869        final long arrayToken = token;
2870        // LBRACKET tested in caller.
2871        next();
2872
2873        // Prepare to accumulate elements.
2874        final List<Expression> elements = new ArrayList<>();
2875        // Track elisions.
2876        boolean elision = true;
2877        boolean hasSpread = false;
2878        loop:
2879        while (true) {
2880            long spreadToken = 0;
2881            switch (type) {
2882            case RBRACKET:
2883                next();
2884
2885                break loop;
2886
2887            case COMMARIGHT:
2888                next();
2889
2890                // If no prior expression
2891                if (elision) {
2892                    elements.add(null);
2893                }
2894
2895                elision = true;
2896
2897                break;
2898
2899            case ELLIPSIS:
2900                if (isES6()) {
2901                    hasSpread = true;
2902                    spreadToken = token;
2903                    next();
2904                }
2905                // fall through
2906
2907            default:
2908                if (!elision) {
2909                    throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2910                }
2911
2912                // Add expression element.
2913                Expression expression = assignmentExpression(false);
2914                if (expression != null) {
2915                    if (spreadToken != 0) {
2916                        expression = new UnaryNode(Token.recast(spreadToken, SPREAD_ARRAY), expression);
2917                    }
2918                    elements.add(expression);
2919                } else {
2920                    expect(RBRACKET);
2921                }
2922
2923                elision = false;
2924                break;
2925            }
2926        }
2927
2928        return LiteralNode.newInstance(arrayToken, finish, elements, hasSpread, elision);
2929    }
2930
2931    /**
2932     * ObjectLiteral :
2933     *      { }
2934     *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2935     *
2936     * PropertyNameAndValueList :
2937     *      PropertyAssignment
2938     *      PropertyNameAndValueList , PropertyAssignment
2939     *
2940     * See 11.1.5
2941     *
2942     * Parse an object literal.
2943     * @return Expression node.
2944     */
2945    private ObjectNode objectLiteral() {
2946        // Capture LBRACE token.
2947        final long objectToken = token;
2948        // LBRACE tested in caller.
2949        next();
2950
2951        // Object context.
2952        // Prepare to accumulate elements.
2953        final List<PropertyNode> elements = new ArrayList<>();
2954        final Map<String, Integer> map = new HashMap<>();
2955
2956        // Create a block for the object literal.
2957        boolean commaSeen = true;
2958        loop:
2959        while (true) {
2960            switch (type) {
2961                case RBRACE:
2962                    next();
2963                    break loop;
2964
2965                case COMMARIGHT:
2966                    if (commaSeen) {
2967                        throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2968                    }
2969                    next();
2970                    commaSeen = true;
2971                    break;
2972
2973                default:
2974                    if (!commaSeen) {
2975                        throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2976                    }
2977
2978                    commaSeen = false;
2979                    // Get and add the next property.
2980                    final PropertyNode property = propertyAssignment();
2981
2982                    if (property.isComputed()) {
2983                        elements.add(property);
2984                        break;
2985                    }
2986
2987                    final String key = property.getKeyName();
2988                    final Integer existing = map.get(key);
2989
2990                    if (existing == null) {
2991                        map.put(key, elements.size());
2992                        elements.add(property);
2993                        break;
2994                    }
2995
2996                    final PropertyNode existingProperty = elements.get(existing);
2997
2998                    // ECMA section 11.1.5 Object Initialiser
2999                    // point # 4 on property assignment production
3000                    final Expression   value  = property.getValue();
3001                    final FunctionNode getter = property.getGetter();
3002                    final FunctionNode setter = property.getSetter();
3003
3004                    final Expression   prevValue  = existingProperty.getValue();
3005                    final FunctionNode prevGetter = existingProperty.getGetter();
3006                    final FunctionNode prevSetter = existingProperty.getSetter();
3007
3008                    if (!isES6()) {
3009                        checkPropertyRedefinition(property, value, getter, setter, prevValue, prevGetter, prevSetter);
3010                    } else {
3011                        if (property.getKey() instanceof IdentNode && ((IdentNode)property.getKey()).isProtoPropertyName() &&
3012                                        existingProperty.getKey() instanceof IdentNode && ((IdentNode)existingProperty.getKey()).isProtoPropertyName()) {
3013                            throw error(AbstractParser.message("multiple.proto.key"), property.getToken());
3014                        }
3015                    }
3016
3017                    if (value != null || prevValue != null) {
3018                        map.put(key, elements.size());
3019                        elements.add(property);
3020                    } else if (getter != null) {
3021                        assert prevGetter != null || prevSetter != null;
3022                        elements.set(existing, existingProperty.setGetter(getter));
3023                    } else if (setter != null) {
3024                        assert prevGetter != null || prevSetter != null;
3025                        elements.set(existing, existingProperty.setSetter(setter));
3026                    }
3027                    break;
3028            }
3029        }
3030
3031        return new ObjectNode(objectToken, finish, elements);
3032    }
3033
3034    private void checkPropertyRedefinition(final PropertyNode property, final Expression value, final FunctionNode getter, final FunctionNode setter, final Expression prevValue, final FunctionNode prevGetter, final FunctionNode prevSetter) {
3035        // ECMA 11.1.5 strict mode restrictions
3036        if (isStrictMode && value != null && prevValue != null) {
3037            throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3038        }
3039
3040        final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
3041        final boolean isAccessor     = getter != null     || setter != null;
3042
3043        // data property redefined as accessor property
3044        if (prevValue != null && isAccessor) {
3045            throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3046        }
3047
3048        // accessor property redefined as data
3049        if (isPrevAccessor && value != null) {
3050            throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3051        }
3052
3053        if (isAccessor && isPrevAccessor) {
3054            if (getter != null && prevGetter != null ||
3055                    setter != null && prevSetter != null) {
3056                throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
3057            }
3058        }
3059    }
3060
3061    /**
3062     * LiteralPropertyName :
3063     *      IdentifierName
3064     *      StringLiteral
3065     *      NumericLiteral
3066     *
3067     * @return PropertyName node
3068     */
3069    @SuppressWarnings("fallthrough")
3070    private PropertyKey literalPropertyName() {
3071        switch (type) {
3072        case IDENT:
3073            return getIdent().setIsPropertyName();
3074        case OCTAL_LEGACY:
3075            if (isStrictMode) {
3076                throw error(AbstractParser.message("strict.no.octal"), token);
3077            }
3078        case STRING:
3079        case ESCSTRING:
3080        case DECIMAL:
3081        case HEXADECIMAL:
3082        case OCTAL:
3083        case BINARY_NUMBER:
3084        case FLOATING:
3085            return getLiteral();
3086        default:
3087            return getIdentifierName().setIsPropertyName();
3088        }
3089    }
3090
3091    /**
3092     * ComputedPropertyName :
3093     *      AssignmentExpression
3094     *
3095     * @return PropertyName node
3096     */
3097    private Expression computedPropertyName() {
3098        expect(LBRACKET);
3099        final Expression expression = assignmentExpression(false);
3100        expect(RBRACKET);
3101        return expression;
3102    }
3103
3104    /**
3105     * PropertyName :
3106     *      LiteralPropertyName
3107     *      ComputedPropertyName
3108     *
3109     * @return PropertyName node
3110     */
3111    private Expression propertyName() {
3112        if (type == LBRACKET && isES6()) {
3113            return computedPropertyName();
3114        } else {
3115            return (Expression)literalPropertyName();
3116        }
3117    }
3118
3119    /**
3120     * PropertyAssignment :
3121     *      PropertyName : AssignmentExpression
3122     *      get PropertyName ( ) { FunctionBody }
3123     *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
3124     *
3125     * PropertySetParameterList :
3126     *      Identifier
3127     *
3128     * PropertyName :
3129     *      IdentifierName
3130     *      StringLiteral
3131     *      NumericLiteral
3132     *
3133     * See 11.1.5
3134     *
3135     * Parse an object literal property.
3136     * @return Property or reference node.
3137     */
3138    private PropertyNode propertyAssignment() {
3139        // Capture firstToken.
3140        final long propertyToken = token;
3141        final int  functionLine  = line;
3142
3143        final Expression propertyName;
3144        final boolean isIdentifier;
3145
3146        boolean generator = false;
3147        if (type == MUL && isES6()) {
3148            generator = true;
3149            next();
3150        }
3151
3152        final boolean computed = type == LBRACKET;
3153        if (type == IDENT) {
3154            // Get IDENT.
3155            final String ident = (String)expectValue(IDENT);
3156
3157            if (type != COLON && (type != LPAREN || !isES6())) {
3158                final long getSetToken = propertyToken;
3159
3160                switch (ident) {
3161                case GET_NAME:
3162                    final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
3163                    return new PropertyNode(propertyToken, finish, getter.key, null, getter.functionNode, null, false, getter.computed);
3164
3165                case SET_NAME:
3166                    final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
3167                    return new PropertyNode(propertyToken, finish, setter.key, null, null, setter.functionNode, false, setter.computed);
3168                default:
3169                    break;
3170                }
3171            }
3172
3173            isIdentifier = true;
3174            IdentNode identNode = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
3175            if (type == COLON && ident.equals("__proto__")) {
3176                identNode = identNode.setIsProtoPropertyName();
3177            }
3178            propertyName = identNode;
3179        } else {
3180            isIdentifier = isNonStrictModeIdent();
3181            propertyName = propertyName();
3182        }
3183
3184        Expression propertyValue;
3185
3186        if (generator) {
3187            expectDontAdvance(LPAREN);
3188        }
3189
3190        if (type == LPAREN && isES6()) {
3191            propertyValue = propertyMethodFunction(propertyName, propertyToken, functionLine, generator, FunctionNode.ES6_IS_METHOD, computed).functionNode;
3192        } else if (isIdentifier && (type == COMMARIGHT || type == RBRACE || type == ASSIGN) && isES6()) {
3193            propertyValue = createIdentNode(propertyToken, finish, ((IdentNode) propertyName).getPropertyName());
3194            if (type == ASSIGN && isES6()) {
3195                // TODO if not destructuring, this is a SyntaxError
3196                final long assignToken = token;
3197                next();
3198                final Expression rhs = assignmentExpression(false);
3199                propertyValue = verifyAssignment(assignToken, propertyValue, rhs);
3200            }
3201        } else {
3202            expect(COLON);
3203
3204            defaultNames.push(propertyName);
3205            try {
3206                propertyValue = assignmentExpression(false);
3207            } finally {
3208                defaultNames.pop();
3209            }
3210        }
3211
3212        return new PropertyNode(propertyToken, finish, propertyName, propertyValue, null, null, false, computed);
3213    }
3214
3215    private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
3216        return propertyGetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
3217    }
3218
3219    private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine, final int flags) {
3220        final boolean computed = type == LBRACKET;
3221        final Expression propertyName = propertyName();
3222        final String getterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
3223        final IdentNode getNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("get " + getterName));
3224        expect(LPAREN);
3225        expect(RPAREN);
3226
3227        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
3228        functionNode.setFlag(flags);
3229        if (computed) {
3230            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3231        }
3232        lc.push(functionNode);
3233
3234        Block functionBody;
3235
3236
3237        try {
3238            functionBody = functionBody(functionNode);
3239        } finally {
3240            lc.pop(functionNode);
3241        }
3242
3243        final FunctionNode  function = createFunctionNode(
3244                functionNode,
3245                getSetToken,
3246                getNameNode,
3247                Collections.<IdentNode>emptyList(),
3248                FunctionNode.Kind.GETTER,
3249                functionLine,
3250                functionBody);
3251
3252        return new PropertyFunction(propertyName, function, computed);
3253    }
3254
3255    private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
3256        return propertySetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
3257    }
3258
3259    private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine, final int flags) {
3260        final boolean computed = type == LBRACKET;
3261        final Expression propertyName = propertyName();
3262        final String setterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
3263        final IdentNode setNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("set " + setterName));
3264        expect(LPAREN);
3265        // be sloppy and allow missing setter parameter even though
3266        // spec does not permit it!
3267        final IdentNode argIdent;
3268        if (isBindingIdentifier()) {
3269            argIdent = getIdent();
3270            verifyIdent(argIdent, "setter argument");
3271        } else {
3272            argIdent = null;
3273        }
3274        expect(RPAREN);
3275        final List<IdentNode> parameters = new ArrayList<>();
3276        if (argIdent != null) {
3277            parameters.add(argIdent);
3278        }
3279
3280
3281        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
3282        functionNode.setFlag(flags);
3283        if (computed) {
3284            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3285        }
3286        lc.push(functionNode);
3287
3288        Block functionBody;
3289        try {
3290            functionBody = functionBody(functionNode);
3291        } finally {
3292            lc.pop(functionNode);
3293        }
3294
3295
3296        final FunctionNode  function = createFunctionNode(
3297                functionNode,
3298                getSetToken,
3299                setNameNode,
3300                parameters,
3301                FunctionNode.Kind.SETTER,
3302                functionLine,
3303                functionBody);
3304
3305        return new PropertyFunction(propertyName, function, computed);
3306    }
3307
3308    private PropertyFunction propertyMethodFunction(final Expression key, final long methodToken, final int methodLine, final boolean generator, final int flags, final boolean computed) {
3309        final String methodName = key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : getDefaultValidFunctionName(methodLine, false);
3310        final IdentNode methodNameNode = createIdentNode(((Node)key).getToken(), finish, methodName);
3311
3312        final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
3313        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(methodNameNode, methodToken, functionKind, methodLine, null);
3314        functionNode.setFlag(flags);
3315        if (computed) {
3316            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3317        }
3318        lc.push(functionNode);
3319
3320        try {
3321            final ParserContextBlockNode parameterBlock = newBlock();
3322            final List<IdentNode> parameters;
3323            try {
3324                expect(LPAREN);
3325                parameters = formalParameterList(generator);
3326                functionNode.setParameters(parameters);
3327                expect(RPAREN);
3328            } finally {
3329                restoreBlock(parameterBlock);
3330            }
3331
3332            Block functionBody = functionBody(functionNode);
3333
3334            functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
3335
3336            final FunctionNode  function = createFunctionNode(
3337                            functionNode,
3338                            methodToken,
3339                            methodNameNode,
3340                            parameters,
3341                            functionKind,
3342                            methodLine,
3343                            functionBody);
3344            return new PropertyFunction(key, function, computed);
3345        } finally {
3346            lc.pop(functionNode);
3347        }
3348    }
3349
3350    private static class PropertyFunction {
3351        final Expression key;
3352        final FunctionNode functionNode;
3353        final boolean computed;
3354
3355        PropertyFunction(final Expression key, final FunctionNode function, final boolean computed) {
3356            this.key = key;
3357            this.functionNode = function;
3358            this.computed = computed;
3359        }
3360    }
3361
3362    /**
3363     * LeftHandSideExpression :
3364     *      NewExpression
3365     *      CallExpression
3366     *
3367     * CallExpression :
3368     *      MemberExpression Arguments
3369     *      SuperCall
3370     *      CallExpression Arguments
3371     *      CallExpression [ Expression ]
3372     *      CallExpression . IdentifierName
3373     *
3374     * SuperCall :
3375     *      super Arguments
3376     *
3377     * See 11.2
3378     *
3379     * Parse left hand side expression.
3380     * @return Expression node.
3381     */
3382    private Expression leftHandSideExpression() {
3383        int  callLine  = line;
3384        long callToken = token;
3385
3386        Expression lhs = memberExpression();
3387
3388        if (type == LPAREN) {
3389            final List<Expression> arguments = optimizeList(argumentList());
3390
3391            // Catch special functions.
3392            if (lhs instanceof IdentNode) {
3393                detectSpecialFunction((IdentNode)lhs);
3394            }
3395
3396            lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3397        }
3398
3399        loop:
3400        while (true) {
3401            // Capture token.
3402            callLine  = line;
3403            callToken = token;
3404
3405            switch (type) {
3406            case LPAREN: {
3407                // Get NEW or FUNCTION arguments.
3408                final List<Expression> arguments = optimizeList(argumentList());
3409
3410                // Create call node.
3411                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3412
3413                break;
3414            }
3415            case LBRACKET: {
3416                next();
3417
3418                // Get array index.
3419                final Expression rhs = expression();
3420
3421                expect(RBRACKET);
3422
3423                // Create indexing node.
3424                lhs = new IndexNode(callToken, finish, lhs, rhs);
3425
3426                break;
3427            }
3428            case PERIOD: {
3429                next();
3430
3431                final IdentNode property = getIdentifierName();
3432
3433                // Create property access node.
3434                lhs = new AccessNode(callToken, finish, lhs, property.getName());
3435
3436                break;
3437            }
3438            case TEMPLATE:
3439            case TEMPLATE_HEAD: {
3440                // tagged template literal
3441                final List<Expression> arguments = templateLiteralArgumentList();
3442
3443                // Create call node.
3444                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3445
3446                break;
3447            }
3448            default:
3449                break loop;
3450            }
3451        }
3452
3453        return lhs;
3454    }
3455
3456    /**
3457     * NewExpression :
3458     *      MemberExpression
3459     *      new NewExpression
3460     *
3461     * See 11.2
3462     *
3463     * Parse new expression.
3464     * @return Expression node.
3465     */
3466    private Expression newExpression() {
3467        final long newToken = token;
3468        // NEW is tested in caller.
3469        next();
3470
3471        if (type == PERIOD && isES6()) {
3472            next();
3473            if (type == IDENT && "target".equals(getValue())) {
3474                if (lc.getCurrentFunction().isProgram()) {
3475                    throw error(AbstractParser.message("new.target.in.function"), token);
3476                }
3477                next();
3478                markNewTarget(lc);
3479                return new IdentNode(newToken, finish, "new.target");
3480            } else {
3481                throw error(AbstractParser.message("expected.target"), token);
3482            }
3483        }
3484
3485        // Get function base.
3486        final int  callLine    = line;
3487        final Expression constructor = memberExpression();
3488        if (constructor == null) {
3489            return null;
3490        }
3491        // Get arguments.
3492        ArrayList<Expression> arguments;
3493
3494        // Allow for missing arguments.
3495        if (type == LPAREN) {
3496            arguments = argumentList();
3497        } else {
3498            arguments = new ArrayList<>();
3499        }
3500
3501        // Nashorn extension: This is to support the following interface implementation
3502        // syntax:
3503        //
3504        //     var r = new java.lang.Runnable() {
3505        //         run: function() { println("run"); }
3506        //     };
3507        //
3508        // The object literal following the "new Constructor()" expression
3509        // is passed as an additional (last) argument to the constructor.
3510        if (!env._no_syntax_extensions && type == LBRACE) {
3511            arguments.add(objectLiteral());
3512        }
3513
3514        final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
3515
3516        return new UnaryNode(newToken, callNode);
3517    }
3518
3519    /**
3520     * MemberExpression :
3521     *      PrimaryExpression
3522     *        FunctionExpression
3523     *        ClassExpression
3524     *        GeneratorExpression
3525     *      MemberExpression [ Expression ]
3526     *      MemberExpression . IdentifierName
3527     *      MemberExpression TemplateLiteral
3528     *      SuperProperty
3529     *      MetaProperty
3530     *      new MemberExpression Arguments
3531     *
3532     * SuperProperty :
3533     *      super [ Expression ]
3534     *      super . IdentifierName
3535     *
3536     * MetaProperty :
3537     *      NewTarget
3538     *
3539     * Parse member expression.
3540     * @return Expression node.
3541     */
3542    @SuppressWarnings("fallthrough")
3543    private Expression memberExpression() {
3544        // Prepare to build operation.
3545        Expression lhs;
3546        boolean isSuper = false;
3547
3548        switch (type) {
3549        case NEW:
3550            // Get new expression.
3551            lhs = newExpression();
3552            break;
3553
3554        case FUNCTION:
3555            // Get function expression.
3556            lhs = functionExpression(false, false);
3557            break;
3558
3559        case CLASS:
3560            if (isES6()) {
3561                lhs = classExpression(false);
3562                break;
3563            } else {
3564                // fall through
3565            }
3566
3567        case SUPER:
3568            if (isES6()) {
3569                final ParserContextFunctionNode currentFunction = getCurrentNonArrowFunction();
3570                if (currentFunction.isMethod()) {
3571                    final long identToken = Token.recast(token, IDENT);
3572                    next();
3573                    lhs = createIdentNode(identToken, finish, SUPER.getName());
3574
3575                    switch (type) {
3576                        case LBRACKET:
3577                        case PERIOD:
3578                            getCurrentNonArrowFunction().setFlag(FunctionNode.ES6_USES_SUPER);
3579                            isSuper = true;
3580                            break;
3581                        case LPAREN:
3582                            if (currentFunction.isSubclassConstructor()) {
3583                                lhs = ((IdentNode)lhs).setIsDirectSuper();
3584                                break;
3585                            } else {
3586                                // fall through to throw error
3587                            }
3588                        default:
3589                            throw error(AbstractParser.message("invalid.super"), identToken);
3590                    }
3591                    break;
3592                } else {
3593                    // fall through
3594                }
3595            } else {
3596                // fall through
3597            }
3598
3599        default:
3600            // Get primary expression.
3601            lhs = primaryExpression();
3602            break;
3603        }
3604
3605        loop:
3606        while (true) {
3607            // Capture token.
3608            final long callToken = token;
3609
3610            switch (type) {
3611            case LBRACKET: {
3612                next();
3613
3614                // Get array index.
3615                final Expression index = expression();
3616
3617                expect(RBRACKET);
3618
3619                // Create indexing node.
3620                lhs = new IndexNode(callToken, finish, lhs, index);
3621
3622                if (isSuper) {
3623                    isSuper = false;
3624                    lhs = ((BaseNode) lhs).setIsSuper();
3625                }
3626
3627                break;
3628            }
3629            case PERIOD: {
3630                if (lhs == null) {
3631                    throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3632                }
3633
3634                next();
3635
3636                final IdentNode property = getIdentifierName();
3637
3638                // Create property access node.
3639                lhs = new AccessNode(callToken, finish, lhs, property.getName());
3640
3641                if (isSuper) {
3642                    isSuper = false;
3643                    lhs = ((BaseNode) lhs).setIsSuper();
3644                }
3645
3646                break;
3647            }
3648            case TEMPLATE:
3649            case TEMPLATE_HEAD: {
3650                // tagged template literal
3651                final int callLine = line;
3652                final List<Expression> arguments = templateLiteralArgumentList();
3653
3654                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
3655
3656                break;
3657            }
3658            default:
3659                break loop;
3660            }
3661        }
3662
3663        return lhs;
3664    }
3665
3666    /**
3667     * Arguments :
3668     *      ( )
3669     *      ( ArgumentList )
3670     *
3671     * ArgumentList :
3672     *      AssignmentExpression
3673     *      ... AssignmentExpression
3674     *      ArgumentList , AssignmentExpression
3675     *      ArgumentList , ... AssignmentExpression
3676     *
3677     * See 11.2
3678     *
3679     * Parse function call arguments.
3680     * @return Argument list.
3681     */
3682    private ArrayList<Expression> argumentList() {
3683        // Prepare to accumulate list of arguments.
3684        final ArrayList<Expression> nodeList = new ArrayList<>();
3685        // LPAREN tested in caller.
3686        next();
3687
3688        // Track commas.
3689        boolean first = true;
3690
3691        while (type != RPAREN) {
3692            // Comma prior to every argument except the first.
3693            if (!first) {
3694                expect(COMMARIGHT);
3695            } else {
3696                first = false;
3697            }
3698
3699            long spreadToken = 0;
3700            if (type == ELLIPSIS && isES6()) {
3701                spreadToken = token;
3702                next();
3703            }
3704
3705            // Get argument expression.
3706            Expression expression = assignmentExpression(false);
3707            if (spreadToken != 0) {
3708                expression = new UnaryNode(Token.recast(spreadToken, TokenType.SPREAD_ARGUMENT), expression);
3709            }
3710            nodeList.add(expression);
3711        }
3712
3713        expect(RPAREN);
3714        return nodeList;
3715    }
3716
3717    private static <T> List<T> optimizeList(final ArrayList<T> list) {
3718        switch(list.size()) {
3719            case 0: {
3720                return Collections.emptyList();
3721            }
3722            case 1: {
3723                return Collections.singletonList(list.get(0));
3724            }
3725            default: {
3726                list.trimToSize();
3727                return list;
3728            }
3729        }
3730    }
3731
3732    /**
3733     * FunctionDeclaration :
3734     *      function Identifier ( FormalParameterList? ) { FunctionBody }
3735     *
3736     * FunctionExpression :
3737     *      function Identifier? ( FormalParameterList? ) { FunctionBody }
3738     *
3739     * See 13
3740     *
3741     * Parse function declaration.
3742     * @param isStatement True if for is a statement.
3743     *
3744     * @return Expression node.
3745     */
3746    private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
3747        final long functionToken = token;
3748        final int  functionLine  = line;
3749        // FUNCTION is tested in caller.
3750        assert type == FUNCTION;
3751        next();
3752
3753        boolean generator = false;
3754        if (type == MUL && isES6()) {
3755            generator = true;
3756            next();
3757        }
3758
3759        IdentNode name = null;
3760
3761        if (isBindingIdentifier()) {
3762            if (type == YIELD && ((!isStatement && generator) || (isStatement && inGeneratorFunction()))) {
3763                // 12.1.1 Early SyntaxError if:
3764                // GeneratorExpression with BindingIdentifier yield
3765                // HoistableDeclaration with BindingIdentifier yield in generator function body
3766                expect(IDENT);
3767            }
3768            name = getIdent();
3769            verifyStrictIdent(name, "function name");
3770        } else if (isStatement) {
3771            // Nashorn extension: anonymous function statements.
3772            // Do not allow anonymous function statement if extensions
3773            // are now allowed. But if we are reparsing then anon function
3774            // statement is possible - because it was used as function
3775            // expression in surrounding code.
3776            if (env._no_syntax_extensions && reparsedFunction == null) {
3777                expect(IDENT);
3778            }
3779        }
3780
3781        // name is null, generate anonymous name
3782        boolean isAnonymous = false;
3783        if (name == null) {
3784            final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
3785            name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
3786            isAnonymous = true;
3787        }
3788
3789        final FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
3790        List<IdentNode> parameters = Collections.emptyList();
3791        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, functionKind, functionLine, parameters);
3792        lc.push(functionNode);
3793
3794        Block functionBody = null;
3795        // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
3796        // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
3797        hideDefaultName();
3798        try {
3799            final ParserContextBlockNode parameterBlock = newBlock();
3800            try {
3801                expect(LPAREN);
3802                parameters = formalParameterList(generator);
3803                functionNode.setParameters(parameters);
3804                expect(RPAREN);
3805            } finally {
3806                restoreBlock(parameterBlock);
3807            }
3808
3809            functionBody = functionBody(functionNode);
3810
3811            functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
3812        } finally {
3813            defaultNames.pop();
3814            lc.pop(functionNode);
3815        }
3816
3817        if (isStatement) {
3818            if (topLevel || useBlockScope() || (!isStrictMode && env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ACCEPT)) {
3819                functionNode.setFlag(FunctionNode.IS_DECLARED);
3820            } else if (isStrictMode) {
3821                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
3822            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
3823                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
3824            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
3825                warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
3826            }
3827            if (isArguments(name)) {
3828               lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
3829            }
3830        }
3831
3832        if (isAnonymous) {
3833            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
3834        }
3835
3836        verifyParameterList(parameters, functionNode);
3837
3838        final FunctionNode function = createFunctionNode(
3839                functionNode,
3840                functionToken,
3841                name,
3842                parameters,
3843                functionKind,
3844                functionLine,
3845                functionBody);
3846
3847        if (isStatement) {
3848            if (isAnonymous) {
3849                appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function));
3850                return function;
3851            }
3852
3853            // mark ES6 block functions as lexically scoped
3854            final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
3855            final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
3856            if (topLevel) {
3857                functionDeclarations.add(varNode);
3858            } else if (useBlockScope()) {
3859                prependStatement(varNode); // Hoist to beginning of current block
3860            } else {
3861                appendStatement(varNode);
3862            }
3863        }
3864
3865        return function;
3866    }
3867
3868    private void verifyParameterList(final List<IdentNode> parameters, final ParserContextFunctionNode functionNode) {
3869        final IdentNode duplicateParameter = functionNode.getDuplicateParameterBinding();
3870        if (duplicateParameter != null) {
3871            if (functionNode.isStrict() || functionNode.getKind() == FunctionNode.Kind.ARROW || !functionNode.isSimpleParameterList()) {
3872                throw error(AbstractParser.message("strict.param.redefinition", duplicateParameter.getName()), duplicateParameter.getToken());
3873            }
3874
3875            final int arity = parameters.size();
3876            final HashSet<String> parametersSet = new HashSet<>(arity);
3877
3878            for (int i = arity - 1; i >= 0; i--) {
3879                final IdentNode parameter = parameters.get(i);
3880                String parameterName = parameter.getName();
3881
3882                if (parametersSet.contains(parameterName)) {
3883                    // redefinition of parameter name, rename in non-strict mode
3884                    parameterName = functionNode.uniqueName(parameterName);
3885                    final long parameterToken = parameter.getToken();
3886                    parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
3887                }
3888                parametersSet.add(parameterName);
3889            }
3890        }
3891    }
3892
3893    private static Block maybeWrapBodyInParameterBlock(final Block functionBody, final ParserContextBlockNode parameterBlock) {
3894        assert functionBody.isFunctionBody();
3895        if (!parameterBlock.getStatements().isEmpty()) {
3896            parameterBlock.appendStatement(new BlockStatement(functionBody));
3897            return new Block(parameterBlock.getToken(), functionBody.getFinish(), (functionBody.getFlags() | Block.IS_PARAMETER_BLOCK) & ~Block.IS_BODY, parameterBlock.getStatements());
3898        }
3899        return functionBody;
3900    }
3901
3902    private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
3903        final String defaultFunctionName = getDefaultFunctionName();
3904        if (isValidIdentifier(defaultFunctionName)) {
3905            if (isStatement) {
3906                // The name will be used as the LHS of a symbol assignment. We add the anonymous function
3907                // prefix to ensure that it can't clash with another variable.
3908                return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
3909            }
3910            return defaultFunctionName;
3911        }
3912        return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
3913    }
3914
3915    private static boolean isValidIdentifier(final String name) {
3916        if (name == null || name.isEmpty()) {
3917            return false;
3918        }
3919        if (!Character.isJavaIdentifierStart(name.charAt(0))) {
3920            return false;
3921        }
3922        for (int i = 1; i < name.length(); ++i) {
3923            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
3924                return false;
3925            }
3926        }
3927        return true;
3928    }
3929
3930    private String getDefaultFunctionName() {
3931        if (!defaultNames.isEmpty()) {
3932            final Object nameExpr = defaultNames.peek();
3933            if (nameExpr instanceof PropertyKey) {
3934                markDefaultNameUsed();
3935                return ((PropertyKey)nameExpr).getPropertyName();
3936            } else if (nameExpr instanceof AccessNode) {
3937                markDefaultNameUsed();
3938                return ((AccessNode)nameExpr).getProperty();
3939            }
3940        }
3941        return null;
3942    }
3943
3944    private void markDefaultNameUsed() {
3945        defaultNames.pop();
3946        hideDefaultName();
3947    }
3948
3949    private void hideDefaultName() {
3950        // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
3951        // from. Can't be null
3952        defaultNames.push("");
3953    }
3954
3955    /**
3956     * FormalParameterList :
3957     *      Identifier
3958     *      FormalParameterList , Identifier
3959     *
3960     * See 13
3961     *
3962     * Parse function parameter list.
3963     * @return List of parameter nodes.
3964     */
3965    private List<IdentNode> formalParameterList(final boolean yield) {
3966        return formalParameterList(RPAREN, yield);
3967    }
3968
3969    /**
3970     * Same as the other method of the same name - except that the end
3971     * token type expected is passed as argument to this method.
3972     *
3973     * FormalParameterList :
3974     *      Identifier
3975     *      FormalParameterList , Identifier
3976     *
3977     * See 13
3978     *
3979     * Parse function parameter list.
3980     * @return List of parameter nodes.
3981     */
3982    private List<IdentNode> formalParameterList(final TokenType endType, final boolean yield) {
3983        // Prepare to gather parameters.
3984        final ArrayList<IdentNode> parameters = new ArrayList<>();
3985        // Track commas.
3986        boolean first = true;
3987
3988        while (type != endType) {
3989            // Comma prior to every argument except the first.
3990            if (!first) {
3991                expect(COMMARIGHT);
3992            } else {
3993                first = false;
3994            }
3995
3996            boolean restParameter = false;
3997            if (type == ELLIPSIS && isES6()) {
3998                next();
3999                restParameter = true;
4000            }
4001
4002            if (type == YIELD && yield) {
4003                expect(IDENT);
4004            }
4005
4006            final long paramToken = token;
4007            final int paramLine = line;
4008            final String contextString = "function parameter";
4009            IdentNode ident;
4010            if (isBindingIdentifier() || restParameter || !isES6()) {
4011                ident = bindingIdentifier(contextString);
4012
4013                if (restParameter) {
4014                    ident = ident.setIsRestParameter();
4015                    // rest parameter must be last
4016                    expectDontAdvance(endType);
4017                    parameters.add(ident);
4018                    break;
4019                } else if (type == ASSIGN && isES6()) {
4020                    next();
4021                    ident = ident.setIsDefaultParameter();
4022
4023                    if (type == YIELD && yield) {
4024                        // error: yield in default expression
4025                        expect(IDENT);
4026                    }
4027
4028                    // default parameter
4029                    final Expression initializer = assignmentExpression(false);
4030
4031                    final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4032                    if (currentFunction != null) {
4033                        if (env._parse_only) {
4034                            // keep what is seen in source "as is" and save it as parameter expression
4035                            final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, initializer);
4036                            currentFunction.addParameterExpression(ident, assignment);
4037                        } else {
4038                            // desugar to: param = (param === undefined) ? initializer : param;
4039                            // possible alternative: if (param === undefined) param = initializer;
4040                            final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4041                            final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4042                            final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
4043                            lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4044                        }
4045                    }
4046                }
4047
4048                final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4049                if (currentFunction != null) {
4050                    currentFunction.addParameterBinding(ident);
4051                    if (ident.isRestParameter() || ident.isDefaultParameter()) {
4052                        currentFunction.setSimpleParameterList(false);
4053                    }
4054                }
4055            } else {
4056                final Expression pattern = bindingPattern();
4057                // Introduce synthetic temporary parameter to capture the object to be destructured.
4058                ident = createIdentNode(paramToken, pattern.getFinish(), String.format("arguments[%d]", parameters.size())).setIsDestructuredParameter();
4059                verifyDestructuringParameterBindingPattern(pattern, paramToken, paramLine, contextString);
4060
4061                Expression value = ident;
4062                if (type == ASSIGN) {
4063                    next();
4064                    ident = ident.setIsDefaultParameter();
4065
4066                    // binding pattern with initializer. desugar to: (param === undefined) ? initializer : param
4067                    final Expression initializer = assignmentExpression(false);
4068
4069                    if (env._parse_only) {
4070                        // we don't want the synthetic identifier in parse only mode
4071                        value = initializer;
4072                    } else {
4073                        // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list)
4074                        final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4075                        value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4076                    }
4077                }
4078
4079                final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4080                if (currentFunction != null) {
4081                    // destructuring assignment
4082                    final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), pattern, value);
4083                    if (env._parse_only) {
4084                        // in parse-only mode, represent source tree "as is"
4085                        if (ident.isDefaultParameter()) {
4086                            currentFunction.addParameterExpression(ident, assignment);
4087                        } else {
4088                            currentFunction.addParameterExpression(ident, pattern);
4089                        }
4090                    } else {
4091                        lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4092                    }
4093                }
4094            }
4095            parameters.add(ident);
4096        }
4097
4098        parameters.trimToSize();
4099        return parameters;
4100    }
4101
4102    private void verifyDestructuringParameterBindingPattern(final Expression pattern, final long paramToken, final int paramLine, final String contextString) {
4103        verifyDestructuringBindingPattern(pattern, new Consumer<IdentNode>() {
4104            public void accept(final IdentNode identNode) {
4105                verifyIdent(identNode, contextString);
4106
4107                final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4108                if (currentFunction != null) {
4109                    // declare function-scope variables for destructuring bindings
4110                    if (!env._parse_only) {
4111                        lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null));
4112                    }
4113                    // detect duplicate bounds names in parameter list
4114                    currentFunction.addParameterBinding(identNode);
4115                    currentFunction.setSimpleParameterList(false);
4116                }
4117            }
4118        });
4119    }
4120
4121    /**
4122     * FunctionBody :
4123     *      SourceElements?
4124     *
4125     * See 13
4126     *
4127     * Parse function body.
4128     * @return function node (body.)
4129     */
4130    private Block functionBody(final ParserContextFunctionNode functionNode) {
4131        long lastToken = 0L;
4132        ParserContextBlockNode body = null;
4133        final long bodyToken = token;
4134        Block functionBody;
4135        int bodyFinish = 0;
4136
4137        final boolean parseBody;
4138        Object endParserState = null;
4139        try {
4140            // Create a new function block.
4141            body = newBlock();
4142            if (env._debug_scopes) {
4143                // debug scope options forces everything to be in scope
4144                markEval(lc);
4145            }
4146            assert functionNode != null;
4147            final int functionId = functionNode.getId();
4148            parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
4149            // Nashorn extension: expression closures
4150            if ((!env._no_syntax_extensions || functionNode.getKind() == FunctionNode.Kind.ARROW) && type != LBRACE) {
4151                /*
4152                 * Example:
4153                 *
4154                 * function square(x) x * x;
4155                 * print(square(3));
4156                 */
4157
4158                // just expression as function body
4159                final Expression expr = assignmentExpression(false);
4160                lastToken = previousToken;
4161                functionNode.setLastToken(previousToken);
4162                assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
4163                // EOL uses length field to store the line number
4164                final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
4165                // Only create the return node if we aren't skipping nested functions. Note that we aren't
4166                // skipping parsing of these extended functions; they're considered to be small anyway. Also,
4167                // they don't end with a single well known token, so it'd be very hard to get correctly (see
4168                // the note below for reasoning on skipping happening before instead of after RBRACE for
4169                // details).
4170                if (parseBody) {
4171                    functionNode.setFlag(FunctionNode.HAS_EXPRESSION_BODY);
4172                    final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
4173                    appendStatement(returnNode);
4174                }
4175                // bodyFinish = finish;
4176            } else {
4177                expectDontAdvance(LBRACE);
4178                if (parseBody || !skipFunctionBody(functionNode)) {
4179                    next();
4180                    // Gather the function elements.
4181                    final List<Statement> prevFunctionDecls = functionDeclarations;
4182                    functionDeclarations = new ArrayList<>();
4183                    try {
4184                        sourceElements(0);
4185                        addFunctionDeclarations(functionNode);
4186                    } finally {
4187                        functionDeclarations = prevFunctionDecls;
4188                    }
4189
4190                    lastToken = token;
4191                    if (parseBody) {
4192                        // Since the lexer can read ahead and lexify some number of tokens in advance and have
4193                        // them buffered in the TokenStream, we need to produce a lexer state as it was just
4194                        // before it lexified RBRACE, and not whatever is its current (quite possibly well read
4195                        // ahead) state.
4196                        endParserState = new ParserState(Token.descPosition(token), line, linePosition);
4197
4198                        // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
4199                        // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
4200                        // state after it. The reason is that RBRACE is a well-known token that we can expect and
4201                        // will never involve us getting into a weird lexer state, and as such is a great reparse
4202                        // point. Typical example of a weird lexer state after RBRACE would be:
4203                        //     function this_is_skipped() { ... } "use strict";
4204                        // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
4205                        // of compensating for the possibility of a string literal (or similar) after RBRACE,
4206                        // we'll rather just restart parsing from this well-known, friendly token instead.
4207                    }
4208                }
4209                bodyFinish = finish;
4210                functionNode.setLastToken(token);
4211                expect(RBRACE);
4212            }
4213        } finally {
4214            restoreBlock(body);
4215        }
4216
4217        // NOTE: we can only do alterations to the function node after restoreFunctionNode.
4218
4219        if (parseBody) {
4220            functionNode.setEndParserState(endParserState);
4221        } else if (!body.getStatements().isEmpty()){
4222            // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
4223            // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
4224            // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
4225            // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
4226            // nested bodies early if we were supposed to skip 'em.
4227            body.setStatements(Collections.<Statement>emptyList());
4228        }
4229
4230        if (reparsedFunction != null) {
4231            // We restore the flags stored in the function's ScriptFunctionData that we got when we first
4232            // eagerly parsed the code. We're doing it because some flags would be set based on the
4233            // content of the function, or even content of its nested functions, most of which are normally
4234            // skipped during an on-demand compilation.
4235            final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
4236            if (data != null) {
4237                // Data can be null if when we originally parsed the file, we removed the function declaration
4238                // as it was dead code.
4239                functionNode.setFlag(data.getFunctionFlags());
4240                // This compensates for missing markEval() in case the function contains an inner function
4241                // that contains eval(), that now we didn't discover since we skipped the inner function.
4242                if (functionNode.hasNestedEval()) {
4243                    assert functionNode.hasScopeBlock();
4244                    body.setFlag(Block.NEEDS_SCOPE);
4245                }
4246            }
4247        }
4248        functionBody = new Block(bodyToken, bodyFinish, body.getFlags() | Block.IS_BODY, body.getStatements());
4249        return functionBody;
4250    }
4251
4252    private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
4253        if (reparsedFunction == null) {
4254            // Not reparsing, so don't skip any function body.
4255            return false;
4256        }
4257        // Skip to the RBRACE of this function, and continue parsing from there.
4258        final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
4259        if (data == null) {
4260            // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
4261            // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
4262            // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
4263            return false;
4264        }
4265        final ParserState parserState = (ParserState)data.getEndParserState();
4266        assert parserState != null;
4267
4268        if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) {
4269            // RBRACE is already in the token stream, so fast forward to it
4270            for (; k < stream.last(); k++) {
4271                final long nextToken = stream.get(k + 1);
4272                if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) {
4273                    token = stream.get(k);
4274                    type = Token.descType(token);
4275                    next();
4276                    assert type == RBRACE && start == parserState.position;
4277                    return true;
4278                }
4279            }
4280        }
4281
4282        stream.reset();
4283        lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
4284        line = parserState.line;
4285        linePosition = parserState.linePosition;
4286        // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
4287        // the RBRACE.
4288        type = SEMICOLON;
4289        scanFirstToken();
4290
4291        return true;
4292    }
4293
4294    /**
4295     * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
4296     * for resuming parsing after skipping a function body.
4297     */
4298    private static class ParserState implements Serializable {
4299        private final int position;
4300        private final int line;
4301        private final int linePosition;
4302
4303        private static final long serialVersionUID = -2382565130754093694L;
4304
4305        ParserState(final int position, final int line, final int linePosition) {
4306            this.position = position;
4307            this.line = line;
4308            this.linePosition = linePosition;
4309        }
4310
4311        Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
4312            final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
4313            newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
4314            return newLexer;
4315        }
4316    }
4317
4318    private void printAST(final FunctionNode functionNode) {
4319        if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) {
4320            env.getErr().println(new ASTWriter(functionNode));
4321        }
4322
4323        if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) {
4324            env.getErr().println(new PrintVisitor(functionNode, true, false));
4325        }
4326    }
4327
4328    private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
4329        VarNode lastDecl = null;
4330        for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
4331            Statement decl = functionDeclarations.get(i);
4332            if (lastDecl == null && decl instanceof VarNode) {
4333                decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
4334                functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
4335            }
4336            prependStatement(decl);
4337        }
4338    }
4339
4340    private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
4341        if (env._parse_only || earlyError) {
4342            throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
4343        }
4344        final ArrayList<Expression> args = new ArrayList<>();
4345        args.add(lhs);
4346        if (rhs == null) {
4347            args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
4348        } else {
4349            args.add(rhs);
4350        }
4351        args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
4352        return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
4353    }
4354
4355    /**
4356     * PostfixExpression :
4357     *      LeftHandSideExpression
4358     *      LeftHandSideExpression ++ // [no LineTerminator here]
4359     *      LeftHandSideExpression -- // [no LineTerminator here]
4360     *
4361     * See 11.3
4362     *
4363     * UnaryExpression :
4364     *      PostfixExpression
4365     *      delete UnaryExpression
4366     *      void UnaryExpression
4367     *      typeof UnaryExpression
4368     *      ++ UnaryExpression
4369     *      -- UnaryExpression
4370     *      + UnaryExpression
4371     *      - UnaryExpression
4372     *      ~ UnaryExpression
4373     *      ! UnaryExpression
4374     *
4375     * See 11.4
4376     *
4377     * Parse unary expression.
4378     * @return Expression node.
4379     */
4380    private Expression unaryExpression() {
4381        final int  unaryLine  = line;
4382        final long unaryToken = token;
4383
4384        switch (type) {
4385        case DELETE: {
4386            next();
4387            final Expression expr = unaryExpression();
4388            if (expr instanceof BaseNode || expr instanceof IdentNode) {
4389                return new UnaryNode(unaryToken, expr);
4390            }
4391            appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
4392            return LiteralNode.newInstance(unaryToken, finish, true);
4393        }
4394        case ADD:
4395        case SUB: {
4396            final TokenType opType = type;
4397            next();
4398            final Expression expr = unaryExpression();
4399            return new UnaryNode(Token.recast(unaryToken, (opType == TokenType.ADD) ? TokenType.POS : TokenType.NEG), expr);
4400        }
4401        case VOID:
4402        case TYPEOF:
4403        case BIT_NOT:
4404        case NOT:
4405            next();
4406            final Expression expr = unaryExpression();
4407            return new UnaryNode(unaryToken, expr);
4408
4409        case INCPREFIX:
4410        case DECPREFIX:
4411            final TokenType opType = type;
4412            next();
4413
4414            final Expression lhs = leftHandSideExpression();
4415            // ++, -- without operand..
4416            if (lhs == null) {
4417                throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
4418            }
4419
4420            return verifyIncDecExpression(unaryToken, opType, lhs, false);
4421
4422        default:
4423            break;
4424        }
4425
4426        final Expression expression = leftHandSideExpression();
4427
4428        if (last != EOL) {
4429            switch (type) {
4430            case INCPREFIX:
4431            case DECPREFIX:
4432                final long opToken = token;
4433                final TokenType opType = type;
4434                final Expression lhs = expression;
4435                // ++, -- without operand..
4436                if (lhs == null) {
4437                    throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
4438                }
4439                next();
4440
4441                return verifyIncDecExpression(opToken, opType, lhs, true);
4442            default:
4443                break;
4444            }
4445        }
4446
4447        if (expression == null) {
4448            throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
4449        }
4450
4451        return expression;
4452    }
4453
4454    private Expression verifyIncDecExpression(final long unaryToken, final TokenType opType, final Expression lhs, final boolean isPostfix) {
4455        assert lhs != null;
4456
4457        if (!(lhs instanceof AccessNode ||
4458              lhs instanceof IndexNode ||
4459              lhs instanceof IdentNode)) {
4460            return referenceError(lhs, null, env._early_lvalue_error);
4461        }
4462
4463        if (lhs instanceof IdentNode) {
4464            if (!checkIdentLValue((IdentNode)lhs)) {
4465                return referenceError(lhs, null, false);
4466            }
4467            verifyIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
4468        }
4469
4470        return incDecExpression(unaryToken, opType, lhs, isPostfix);
4471    }
4472
4473    /**
4474     * {@code
4475     * MultiplicativeExpression :
4476     *      UnaryExpression
4477     *      MultiplicativeExpression * UnaryExpression
4478     *      MultiplicativeExpression / UnaryExpression
4479     *      MultiplicativeExpression % UnaryExpression
4480     *
4481     * See 11.5
4482     *
4483     * AdditiveExpression :
4484     *      MultiplicativeExpression
4485     *      AdditiveExpression + MultiplicativeExpression
4486     *      AdditiveExpression - MultiplicativeExpression
4487     *
4488     * See 11.6
4489     *
4490     * ShiftExpression :
4491     *      AdditiveExpression
4492     *      ShiftExpression << AdditiveExpression
4493     *      ShiftExpression >> AdditiveExpression
4494     *      ShiftExpression >>> AdditiveExpression
4495     *
4496     * See 11.7
4497     *
4498     * RelationalExpression :
4499     *      ShiftExpression
4500     *      RelationalExpression < ShiftExpression
4501     *      RelationalExpression > ShiftExpression
4502     *      RelationalExpression <= ShiftExpression
4503     *      RelationalExpression >= ShiftExpression
4504     *      RelationalExpression instanceof ShiftExpression
4505     *      RelationalExpression in ShiftExpression // if !noIf
4506     *
4507     * See 11.8
4508     *
4509     *      RelationalExpression
4510     *      EqualityExpression == RelationalExpression
4511     *      EqualityExpression != RelationalExpression
4512     *      EqualityExpression === RelationalExpression
4513     *      EqualityExpression !== RelationalExpression
4514     *
4515     * See 11.9
4516     *
4517     * BitwiseANDExpression :
4518     *      EqualityExpression
4519     *      BitwiseANDExpression & EqualityExpression
4520     *
4521     * BitwiseXORExpression :
4522     *      BitwiseANDExpression
4523     *      BitwiseXORExpression ^ BitwiseANDExpression
4524     *
4525     * BitwiseORExpression :
4526     *      BitwiseXORExpression
4527     *      BitwiseORExpression | BitwiseXORExpression
4528     *
4529     * See 11.10
4530     *
4531     * LogicalANDExpression :
4532     *      BitwiseORExpression
4533     *      LogicalANDExpression && BitwiseORExpression
4534     *
4535     * LogicalORExpression :
4536     *      LogicalANDExpression
4537     *      LogicalORExpression || LogicalANDExpression
4538     *
4539     * See 11.11
4540     *
4541     * ConditionalExpression :
4542     *      LogicalORExpression
4543     *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
4544     *
4545     * See 11.12
4546     *
4547     * AssignmentExpression :
4548     *      ConditionalExpression
4549     *      LeftHandSideExpression AssignmentOperator AssignmentExpression
4550     *
4551     * AssignmentOperator :
4552     *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
4553     *
4554     * See 11.13
4555     *
4556     * Expression :
4557     *      AssignmentExpression
4558     *      Expression , AssignmentExpression
4559     *
4560     * See 11.14
4561     * }
4562     *
4563     * Parse expression.
4564     * @return Expression node.
4565     */
4566    protected Expression expression() {
4567        // This method is protected so that subclass can get details
4568        // at expression start point!
4569
4570        // Include commas in expression parsing.
4571        return expression(false);
4572    }
4573
4574    private Expression expression(final boolean noIn) {
4575        Expression assignmentExpression = assignmentExpression(noIn);
4576        while (type == COMMARIGHT) {
4577            final long commaToken = token;
4578            next();
4579
4580            boolean rhsRestParameter = false;
4581            if (type == ELLIPSIS && isES6()) {
4582                // (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).
4583                // 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.
4584                if (isRestParameterEndOfArrowFunctionParameterList()) {
4585                    next();
4586                    rhsRestParameter = true;
4587                }
4588            }
4589
4590            Expression rhs = assignmentExpression(noIn);
4591
4592            if (rhsRestParameter) {
4593                rhs = ((IdentNode)rhs).setIsRestParameter();
4594                // Our only valid move is to end Expression here and continue with ArrowFunction.
4595                // We've already checked that this is the parameter list of an arrow function (see above).
4596                // RPAREN is next, so we'll finish the binary expression and drop out of the loop.
4597                assert type == RPAREN;
4598            }
4599
4600            assignmentExpression = new BinaryNode(commaToken, assignmentExpression, rhs);
4601        }
4602        return assignmentExpression;
4603    }
4604
4605    private Expression expression(final int minPrecedence, final boolean noIn) {
4606        return expression(unaryExpression(), minPrecedence, noIn);
4607    }
4608
4609    private JoinPredecessorExpression joinPredecessorExpression() {
4610        return new JoinPredecessorExpression(expression());
4611    }
4612
4613    private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
4614        // Get the precedence of the next operator.
4615        int precedence = type.getPrecedence();
4616        Expression lhs = exprLhs;
4617
4618        // While greater precedence.
4619        while (type.isOperator(noIn) && precedence >= minPrecedence) {
4620            // Capture the operator token.
4621            final long op = token;
4622
4623            if (type == TERNARY) {
4624                // Skip operator.
4625                next();
4626
4627                // Pass expression. Middle expression of a conditional expression can be a "in"
4628                // expression - even in the contexts where "in" is not permitted.
4629                final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
4630
4631                expect(COLON);
4632
4633                // Fail expression.
4634                final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
4635
4636                // Build up node.
4637                lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
4638            } else {
4639                // Skip operator.
4640                next();
4641
4642                 // Get the next primary expression.
4643                Expression rhs;
4644                final boolean isAssign = Token.descType(op) == ASSIGN;
4645                if(isAssign) {
4646                    defaultNames.push(lhs);
4647                }
4648                try {
4649                    rhs = unaryExpression();
4650                    // Get precedence of next operator.
4651                    int nextPrecedence = type.getPrecedence();
4652
4653                    // Subtask greater precedence.
4654                    while (type.isOperator(noIn) &&
4655                           (nextPrecedence > precedence ||
4656                           nextPrecedence == precedence && !type.isLeftAssociative())) {
4657                        rhs = expression(rhs, nextPrecedence, noIn);
4658                        nextPrecedence = type.getPrecedence();
4659                    }
4660                } finally {
4661                    if(isAssign) {
4662                        defaultNames.pop();
4663                    }
4664                }
4665                lhs = verifyAssignment(op, lhs, rhs);
4666            }
4667
4668            precedence = type.getPrecedence();
4669        }
4670
4671        return lhs;
4672    }
4673
4674    /**
4675     * AssignmentExpression.
4676     *
4677     * AssignmentExpression[In, Yield] :
4678     *   ConditionalExpression[?In, ?Yield]
4679     *   [+Yield] YieldExpression[?In]
4680     *   ArrowFunction[?In, ?Yield]
4681     *   LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield]
4682     *   LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield]
4683     *
4684     * @param noIn {@code true} if IN operator should be ignored.
4685     * @return the assignment expression
4686     */
4687    protected Expression assignmentExpression(final boolean noIn) {
4688        // This method is protected so that subclass can get details
4689        // at assignment expression start point!
4690
4691        if (type == YIELD && inGeneratorFunction() && isES6()) {
4692            return yieldExpression(noIn);
4693        }
4694
4695        final long startToken = token;
4696        final int startLine = line;
4697        final Expression exprLhs = conditionalExpression(noIn);
4698
4699        if (type == ARROW && isES6()) {
4700            if (checkNoLineTerminator()) {
4701                final Expression paramListExpr;
4702                if (exprLhs instanceof ExpressionList) {
4703                    paramListExpr = (((ExpressionList)exprLhs).getExpressions().isEmpty() ? null : ((ExpressionList)exprLhs).getExpressions().get(0));
4704                } else {
4705                    paramListExpr = exprLhs;
4706                }
4707                return arrowFunction(startToken, startLine, paramListExpr);
4708            }
4709        }
4710        assert !(exprLhs instanceof ExpressionList);
4711
4712        if (isAssignmentOperator(type)) {
4713            final boolean isAssign = type == ASSIGN;
4714            if (isAssign) {
4715                defaultNames.push(exprLhs);
4716            }
4717            try {
4718                final long assignToken = token;
4719                next();
4720                final Expression exprRhs = assignmentExpression(noIn);
4721                return verifyAssignment(assignToken, exprLhs, exprRhs);
4722            } finally {
4723                if (isAssign) {
4724                    defaultNames.pop();
4725                }
4726            }
4727        } else {
4728            return exprLhs;
4729        }
4730    }
4731
4732    /**
4733     * Is type one of {@code = *= /= %= += -= <<= >>= >>>= &= ^= |=}?
4734     */
4735    private static boolean isAssignmentOperator(final TokenType type) {
4736        switch (type) {
4737        case ASSIGN:
4738        case ASSIGN_ADD:
4739        case ASSIGN_BIT_AND:
4740        case ASSIGN_BIT_OR:
4741        case ASSIGN_BIT_XOR:
4742        case ASSIGN_DIV:
4743        case ASSIGN_MOD:
4744        case ASSIGN_MUL:
4745        case ASSIGN_SAR:
4746        case ASSIGN_SHL:
4747        case ASSIGN_SHR:
4748        case ASSIGN_SUB:
4749            return true;
4750        }
4751        return false;
4752    }
4753
4754    /**
4755     * ConditionalExpression.
4756     */
4757    private Expression conditionalExpression(final boolean noIn) {
4758        return expression(TERNARY.getPrecedence(), noIn);
4759    }
4760
4761    /**
4762     * ArrowFunction.
4763     *
4764     * @param startToken start token of the ArrowParameters expression
4765     * @param functionLine start line of the arrow function
4766     * @param paramListExpr ArrowParameters expression or {@code null} for {@code ()} (empty list)
4767     */
4768    private Expression arrowFunction(final long startToken, final int functionLine, final Expression paramListExpr) {
4769        // caller needs to check that there's no LineTerminator between parameter list and arrow
4770        assert type != ARROW || checkNoLineTerminator();
4771        expect(ARROW);
4772
4773        final long functionToken = Token.recast(startToken, ARROW);
4774        final IdentNode name = new IdentNode(functionToken, Token.descPosition(functionToken), NameCodec.encode("=>:") + functionLine);
4775        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.ARROW, functionLine, null);
4776        functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
4777
4778        lc.push(functionNode);
4779        try {
4780            final ParserContextBlockNode parameterBlock = newBlock();
4781            final List<IdentNode> parameters;
4782            try {
4783                parameters = convertArrowFunctionParameterList(paramListExpr, functionLine);
4784                functionNode.setParameters(parameters);
4785
4786                if (!functionNode.isSimpleParameterList()) {
4787                    markEvalInArrowParameterList(parameterBlock);
4788                }
4789            } finally {
4790                restoreBlock(parameterBlock);
4791            }
4792            Block functionBody = functionBody(functionNode);
4793
4794            functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
4795
4796            verifyParameterList(parameters, functionNode);
4797
4798            final FunctionNode function = createFunctionNode(
4799                            functionNode,
4800                            functionToken,
4801                            name,
4802                            parameters,
4803                            FunctionNode.Kind.ARROW,
4804                            functionLine,
4805                            functionBody);
4806            return function;
4807        } finally {
4808            lc.pop(functionNode);
4809        }
4810    }
4811
4812    private void markEvalInArrowParameterList(final ParserContextBlockNode parameterBlock) {
4813        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
4814        final ParserContextFunctionNode current = iter.next();
4815        final ParserContextFunctionNode parent = iter.next();
4816
4817        if (parent.getFlag(FunctionNode.HAS_EVAL) != 0) {
4818            // we might have flagged has-eval in the parent function during parsing the parameter list,
4819            // if the parameter list contains eval; must tag arrow function as has-eval.
4820            for (final Statement st : parameterBlock.getStatements()) {
4821                st.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
4822                    @Override
4823                    public boolean enterCallNode(final CallNode callNode) {
4824                        if (callNode.getFunction() instanceof IdentNode && ((IdentNode) callNode.getFunction()).getName().equals("eval")) {
4825                            current.setFlag(FunctionNode.HAS_EVAL);
4826                        }
4827                        return true;
4828                    }
4829                });
4830            }
4831            // TODO: function containing the arrow function should not be flagged has-eval
4832        }
4833    }
4834
4835    private List<IdentNode> convertArrowFunctionParameterList(final Expression paramListExpr, final int functionLine) {
4836        final List<IdentNode> parameters;
4837        if (paramListExpr == null) {
4838            // empty parameter list, i.e. () =>
4839            parameters = Collections.emptyList();
4840        } else if (paramListExpr instanceof IdentNode || paramListExpr.isTokenType(ASSIGN) || isDestructuringLhs(paramListExpr)) {
4841            parameters = Collections.singletonList(verifyArrowParameter(paramListExpr, 0, functionLine));
4842        } else if (paramListExpr instanceof BinaryNode && Token.descType(paramListExpr.getToken()) == COMMARIGHT) {
4843            parameters = new ArrayList<>();
4844            Expression car = paramListExpr;
4845            do {
4846                final Expression cdr = ((BinaryNode) car).rhs();
4847                parameters.add(0, verifyArrowParameter(cdr, parameters.size(), functionLine));
4848                car = ((BinaryNode) car).lhs();
4849            } while (car instanceof BinaryNode && Token.descType(car.getToken()) == COMMARIGHT);
4850            parameters.add(0, verifyArrowParameter(car, parameters.size(), functionLine));
4851        } else {
4852            throw error(AbstractParser.message("expected.arrow.parameter"), paramListExpr.getToken());
4853        }
4854        return parameters;
4855    }
4856
4857    private IdentNode verifyArrowParameter(final Expression param, final int index, final int paramLine) {
4858        final String contextString = "function parameter";
4859        if (param instanceof IdentNode) {
4860            final IdentNode ident = (IdentNode)param;
4861            verifyStrictIdent(ident, contextString);
4862            final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4863            if (currentFunction != null) {
4864                currentFunction.addParameterBinding(ident);
4865            }
4866            return ident;
4867        }
4868
4869        if (param.isTokenType(ASSIGN)) {
4870            final Expression lhs = ((BinaryNode) param).lhs();
4871            final long paramToken = lhs.getToken();
4872            final Expression initializer = ((BinaryNode) param).rhs();
4873            if (lhs instanceof IdentNode) {
4874                // default parameter
4875                final IdentNode ident = (IdentNode) lhs;
4876
4877                final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4878                if (currentFunction != null) {
4879                    if (env._parse_only) {
4880                        currentFunction.addParameterExpression(ident, param);
4881                    } else {
4882                        final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4883                        final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4884                        final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
4885                        lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4886                    }
4887
4888                    currentFunction.addParameterBinding(ident);
4889                    currentFunction.setSimpleParameterList(false);
4890                }
4891                return ident;
4892            } else if (isDestructuringLhs(lhs)) {
4893                // binding pattern with initializer
4894                // Introduce synthetic temporary parameter to capture the object to be destructured.
4895                final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter().setIsDefaultParameter();
4896                verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
4897
4898                final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4899                if (currentFunction != null) {
4900                    if (env._parse_only) {
4901                        currentFunction.addParameterExpression(ident, param);
4902                    } else {
4903                        final BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
4904                        final TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
4905                        final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value);
4906                        lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4907                    }
4908                }
4909                return ident;
4910            }
4911        } else if (isDestructuringLhs(param)) {
4912            // binding pattern
4913            final long paramToken = param.getToken();
4914
4915            // Introduce synthetic temporary parameter to capture the object to be destructured.
4916            final IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter();
4917            verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
4918
4919            final ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
4920            if (currentFunction != null) {
4921                if (env._parse_only) {
4922                    currentFunction.addParameterExpression(ident, param);
4923                } else {
4924                    final BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident);
4925                    lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
4926                }
4927            }
4928            return ident;
4929        }
4930        throw error(AbstractParser.message("invalid.arrow.parameter"), param.getToken());
4931    }
4932
4933    private boolean checkNoLineTerminator() {
4934        assert type == ARROW;
4935        if (last == RPAREN) {
4936            return true;
4937        } else if (last == IDENT) {
4938            return true;
4939        }
4940        for (int i = k - 1; i >= 0; i--) {
4941            final TokenType t = T(i);
4942            switch (t) {
4943            case RPAREN:
4944            case IDENT:
4945                return true;
4946            case EOL:
4947                return false;
4948            case COMMENT:
4949                continue;
4950            default:
4951                if (t.getKind() == TokenKind.FUTURESTRICT) {
4952                    return true;
4953                }
4954                return false;
4955            }
4956        }
4957        return false;
4958    }
4959
4960    /**
4961     * Peek ahead to see if what follows after the ellipsis is a rest parameter
4962     * at the end of an arrow function parameter list.
4963     */
4964    private boolean isRestParameterEndOfArrowFunctionParameterList() {
4965        assert type == ELLIPSIS;
4966        // find IDENT, RPAREN, ARROW, in that order, skipping over EOL (where allowed) and COMMENT
4967        int i = 1;
4968        for (;;) {
4969            final TokenType t = T(k + i++);
4970            if (t == IDENT) {
4971                break;
4972            } else if (t == EOL || t == COMMENT) {
4973                continue;
4974            } else {
4975                return false;
4976            }
4977        }
4978        for (;;) {
4979            final TokenType t = T(k + i++);
4980            if (t == RPAREN) {
4981                break;
4982            } else if (t == EOL || t == COMMENT) {
4983                continue;
4984            } else {
4985                return false;
4986            }
4987        }
4988        for (;;) {
4989            final TokenType t = T(k + i++);
4990            if (t == ARROW) {
4991                break;
4992            } else if (t == COMMENT) {
4993                continue;
4994            } else {
4995                return false;
4996            }
4997        }
4998        return true;
4999    }
5000
5001    /**
5002     * Parse an end of line.
5003     */
5004    private void endOfLine() {
5005        switch (type) {
5006        case SEMICOLON:
5007        case EOL:
5008            next();
5009            break;
5010        case RPAREN:
5011        case RBRACKET:
5012        case RBRACE:
5013        case EOF:
5014            break;
5015        default:
5016            if (last != EOL) {
5017                expect(SEMICOLON);
5018            }
5019            break;
5020        }
5021    }
5022
5023    /**
5024     * Parse untagged template literal as string concatenation.
5025     */
5026    private Expression templateLiteral() {
5027        assert type == TEMPLATE || type == TEMPLATE_HEAD;
5028        final boolean noSubstitutionTemplate = type == TEMPLATE;
5029        long lastLiteralToken = token;
5030        LiteralNode<?> literal = getLiteral();
5031        if (noSubstitutionTemplate) {
5032            return literal;
5033        }
5034
5035        if (env._parse_only) {
5036            final List<Expression> exprs = new ArrayList<>();
5037            exprs.add(literal);
5038            TokenType lastLiteralType;
5039            do {
5040                final Expression expression = expression();
5041                if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5042                    throw error(AbstractParser.message("unterminated.template.expression"), token);
5043                }
5044                exprs.add(expression);
5045                lastLiteralType = type;
5046                literal = getLiteral();
5047                exprs.add(literal);
5048            } while (lastLiteralType == TEMPLATE_MIDDLE);
5049            return new TemplateLiteral(exprs);
5050        } else {
5051            Expression concat = literal;
5052            TokenType lastLiteralType;
5053            do {
5054                final Expression expression = expression();
5055                if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5056                    throw error(AbstractParser.message("unterminated.template.expression"), token);
5057                }
5058                concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression);
5059                lastLiteralType = type;
5060                lastLiteralToken = token;
5061                literal = getLiteral();
5062                concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal);
5063            } while (lastLiteralType == TEMPLATE_MIDDLE);
5064            return concat;
5065        }
5066    }
5067
5068    /**
5069     * Parse tagged template literal as argument list.
5070     * @return argument list for a tag function call (template object, ...substitutions)
5071     */
5072    private List<Expression> templateLiteralArgumentList() {
5073        assert type == TEMPLATE || type == TEMPLATE_HEAD;
5074        final ArrayList<Expression> argumentList = new ArrayList<>();
5075        final ArrayList<Expression> rawStrings = new ArrayList<>();
5076        final ArrayList<Expression> cookedStrings = new ArrayList<>();
5077        argumentList.add(null); // filled at the end
5078
5079        final long templateToken = token;
5080        final boolean hasSubstitutions = type == TEMPLATE_HEAD;
5081        addTemplateLiteralString(rawStrings, cookedStrings);
5082
5083        if (hasSubstitutions) {
5084            TokenType lastLiteralType;
5085            do {
5086                final Expression expression = expression();
5087                if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
5088                    throw error(AbstractParser.message("unterminated.template.expression"), token);
5089                }
5090                argumentList.add(expression);
5091
5092                lastLiteralType = type;
5093                addTemplateLiteralString(rawStrings, cookedStrings);
5094            } while (lastLiteralType == TEMPLATE_MIDDLE);
5095        }
5096
5097        final LiteralNode<Expression[]> rawStringArray = LiteralNode.newInstance(templateToken, finish, rawStrings);
5098        final LiteralNode<Expression[]> cookedStringArray = LiteralNode.newInstance(templateToken, finish, cookedStrings);
5099        final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray);
5100        argumentList.set(0, templateObject);
5101        return optimizeList(argumentList);
5102    }
5103
5104    private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) {
5105        final long stringToken = token;
5106        final String rawString = lexer.valueOfRawString(stringToken);
5107        final String cookedString = (String) getValue();
5108        next();
5109        rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString));
5110        cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
5111    }
5112
5113
5114    /**
5115     * Parse a module.
5116     *
5117     * Module :
5118     *      ModuleBody?
5119     *
5120     * ModuleBody :
5121     *      ModuleItemList
5122     */
5123    private FunctionNode module(final String moduleName) {
5124        final boolean oldStrictMode = isStrictMode;
5125        try {
5126            isStrictMode = true; // Module code is always strict mode code. (ES6 10.2.1)
5127
5128            // Make a pseudo-token for the script holding its start and length.
5129            final int functionStart = Math.min(Token.descPosition(Token.withDelimiter(token)), finish);
5130            final long functionToken = Token.toDesc(FUNCTION, functionStart, source.getLength() - functionStart);
5131            final int  functionLine  = line;
5132
5133            final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), moduleName);
5134            final ParserContextFunctionNode script = createParserContextFunctionNode(
5135                            ident,
5136                            functionToken,
5137                            FunctionNode.Kind.MODULE,
5138                            functionLine,
5139                            Collections.<IdentNode>emptyList());
5140            lc.push(script);
5141
5142            final ParserContextModuleNode module = new ParserContextModuleNode(moduleName);
5143            lc.push(module);
5144
5145            final ParserContextBlockNode body = newBlock();
5146
5147            functionDeclarations = new ArrayList<>();
5148            moduleBody();
5149            addFunctionDeclarations(script);
5150            functionDeclarations = null;
5151
5152            restoreBlock(body);
5153            body.setFlag(Block.NEEDS_SCOPE);
5154            final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
5155            lc.pop(module);
5156            lc.pop(script);
5157            script.setLastToken(token);
5158
5159            expect(EOF);
5160
5161            script.setModule(module.createModule());
5162            return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.MODULE, functionLine, programBody);
5163        } finally {
5164            isStrictMode = oldStrictMode;
5165        }
5166    }
5167
5168    /**
5169     * Parse module body.
5170     *
5171     * ModuleBody :
5172     *      ModuleItemList
5173     *
5174     * ModuleItemList :
5175     *      ModuleItem
5176     *      ModuleItemList ModuleItem
5177     *
5178     * ModuleItem :
5179     *      ImportDeclaration
5180     *      ExportDeclaration
5181     *      StatementListItem
5182     */
5183    private void moduleBody() {
5184        loop:
5185        while (type != EOF) {
5186            switch (type) {
5187            case EOF:
5188                break loop;
5189            case IMPORT:
5190                importDeclaration();
5191                break;
5192            case EXPORT:
5193                exportDeclaration();
5194                break;
5195            default:
5196                // StatementListItem
5197                statement(true, 0, false, false);
5198                break;
5199            }
5200        }
5201    }
5202
5203
5204    /**
5205     * Parse import declaration.
5206     *
5207     * ImportDeclaration :
5208     *     import ImportClause FromClause ;
5209     *     import ModuleSpecifier ;
5210     * ImportClause :
5211     *     ImportedDefaultBinding
5212     *     NameSpaceImport
5213     *     NamedImports
5214     *     ImportedDefaultBinding , NameSpaceImport
5215     *     ImportedDefaultBinding , NamedImports
5216     * ImportedDefaultBinding :
5217     *     ImportedBinding
5218     * ModuleSpecifier :
5219     *     StringLiteral
5220     * ImportedBinding :
5221     *     BindingIdentifier
5222     */
5223    private void importDeclaration() {
5224        final int startPosition = start;
5225        expect(IMPORT);
5226        final ParserContextModuleNode module = lc.getCurrentModule();
5227        if (type == STRING || type == ESCSTRING) {
5228            // import ModuleSpecifier ;
5229            final IdentNode moduleSpecifier = createIdentNode(token, finish, (String) getValue());
5230            next();
5231            module.addModuleRequest(moduleSpecifier);
5232        } else {
5233            // import ImportClause FromClause ;
5234            List<Module.ImportEntry> importEntries;
5235            if (type == MUL) {
5236                importEntries = Collections.singletonList(nameSpaceImport(startPosition));
5237            } else if (type == LBRACE) {
5238                importEntries = namedImports(startPosition);
5239            } else if (isBindingIdentifier()) {
5240                // ImportedDefaultBinding
5241                final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding");
5242                final Module.ImportEntry defaultImport = Module.ImportEntry.importSpecifier(importedDefaultBinding, startPosition, finish);
5243
5244                if (type == COMMARIGHT) {
5245                    next();
5246                    importEntries = new ArrayList<>();
5247                    if (type == MUL) {
5248                        importEntries.add(nameSpaceImport(startPosition));
5249                    } else if (type == LBRACE) {
5250                        importEntries.addAll(namedImports(startPosition));
5251                    } else {
5252                        throw error(AbstractParser.message("expected.named.import"));
5253                    }
5254                } else {
5255                    importEntries = Collections.singletonList(defaultImport);
5256                }
5257            } else {
5258                throw error(AbstractParser.message("expected.import"));
5259            }
5260
5261            final IdentNode moduleSpecifier = fromClause();
5262            module.addModuleRequest(moduleSpecifier);
5263            for (int i = 0; i < importEntries.size(); i++) {
5264                module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier, finish));
5265            }
5266        }
5267        expect(SEMICOLON);
5268    }
5269
5270    /**
5271     * NameSpaceImport :
5272     *     * as ImportedBinding
5273     *
5274     * @param startPosition the start of the import declaration
5275     * @return imported binding identifier
5276     */
5277    private Module.ImportEntry nameSpaceImport(final int startPosition) {
5278        assert type == MUL;
5279        final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
5280        next();
5281        final long asToken = token;
5282        final String as = (String) expectValue(IDENT);
5283        if (!"as".equals(as)) {
5284            throw error(AbstractParser.message("expected.as"), asToken);
5285        }
5286        final IdentNode localNameSpace = bindingIdentifier("ImportedBinding");
5287        return Module.ImportEntry.importSpecifier(starName, localNameSpace, startPosition, finish);
5288    }
5289
5290    /**
5291     * NamedImports :
5292     *     { }
5293     *     { ImportsList }
5294     *     { ImportsList , }
5295     * ImportsList :
5296     *     ImportSpecifier
5297     *     ImportsList , ImportSpecifier
5298     * ImportSpecifier :
5299     *     ImportedBinding
5300     *     IdentifierName as ImportedBinding
5301     * ImportedBinding :
5302     *     BindingIdentifier
5303     */
5304    private List<Module.ImportEntry> namedImports(final int startPosition) {
5305        assert type == LBRACE;
5306        next();
5307        final List<Module.ImportEntry> importEntries = new ArrayList<>();
5308        while (type != RBRACE) {
5309            final boolean bindingIdentifier = isBindingIdentifier();
5310            final long nameToken = token;
5311            final IdentNode importName = getIdentifierName();
5312            if (type == IDENT && "as".equals(getValue())) {
5313                next();
5314                final IdentNode localName = bindingIdentifier("ImportedBinding");
5315                importEntries.add(Module.ImportEntry.importSpecifier(importName, localName, startPosition, finish));
5316            } else if (!bindingIdentifier) {
5317                throw error(AbstractParser.message("expected.binding.identifier"), nameToken);
5318            } else {
5319                importEntries.add(Module.ImportEntry.importSpecifier(importName, startPosition, finish));
5320            }
5321            if (type == COMMARIGHT) {
5322                next();
5323            } else {
5324                break;
5325            }
5326        }
5327        expect(RBRACE);
5328        return importEntries;
5329    }
5330
5331    /**
5332     * FromClause :
5333     *     from ModuleSpecifier
5334     */
5335    private IdentNode fromClause() {
5336        final long fromToken = token;
5337        final String name = (String) expectValue(IDENT);
5338        if (!"from".equals(name)) {
5339            throw error(AbstractParser.message("expected.from"), fromToken);
5340        }
5341        if (type == STRING || type == ESCSTRING) {
5342            final IdentNode moduleSpecifier = createIdentNode(Token.recast(token, IDENT), finish, (String) getValue());
5343            next();
5344            return moduleSpecifier;
5345        } else {
5346            throw error(expectMessage(STRING));
5347        }
5348    }
5349
5350    /**
5351     * Parse export declaration.
5352     *
5353     * ExportDeclaration :
5354     *     export * FromClause ;
5355     *     export ExportClause FromClause ;
5356     *     export ExportClause ;
5357     *     export VariableStatement
5358     *     export Declaration
5359     *     export default HoistableDeclaration[Default]
5360     *     export default ClassDeclaration[Default]
5361     *     export default [lookahead !in {function, class}] AssignmentExpression[In] ;
5362     */
5363    private void exportDeclaration() {
5364        expect(EXPORT);
5365        final int startPosition = start;
5366        final ParserContextModuleNode module = lc.getCurrentModule();
5367        switch (type) {
5368            case MUL: {
5369                final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
5370                next();
5371                final IdentNode moduleRequest = fromClause();
5372                expect(SEMICOLON);
5373                module.addModuleRequest(moduleRequest);
5374                module.addStarExportEntry(Module.ExportEntry.exportStarFrom(starName, moduleRequest, startPosition, finish));
5375                break;
5376            }
5377            case LBRACE: {
5378                final List<Module.ExportEntry> exportEntries = exportClause(startPosition);
5379                if (type == IDENT && "from".equals(getValue())) {
5380                    final IdentNode moduleRequest = fromClause();
5381                    module.addModuleRequest(moduleRequest);
5382                    for (final Module.ExportEntry exportEntry : exportEntries) {
5383                        module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest, finish));
5384                    }
5385                } else {
5386                    for (final Module.ExportEntry exportEntry : exportEntries) {
5387                        module.addLocalExportEntry(exportEntry);
5388                    }
5389                }
5390                expect(SEMICOLON);
5391                break;
5392            }
5393            case DEFAULT:
5394                final IdentNode defaultName = createIdentNode(Token.recast(token, IDENT), finish, Module.DEFAULT_NAME);
5395                next();
5396                final Expression assignmentExpression;
5397                IdentNode ident;
5398                final int lineNumber = line;
5399                final long rhsToken = token;
5400                final boolean declaration;
5401                switch (type) {
5402                    case FUNCTION:
5403                        assignmentExpression = functionExpression(false, true);
5404                        ident = ((FunctionNode) assignmentExpression).getIdent();
5405                        declaration = true;
5406                        break;
5407                    case CLASS:
5408                        assignmentExpression = classDeclaration(true);
5409                        ident = ((ClassNode) assignmentExpression).getIdent();
5410                        declaration = true;
5411                        break;
5412                    default:
5413                        assignmentExpression = assignmentExpression(false);
5414                        ident = null;
5415                        declaration = false;
5416                        break;
5417                }
5418                if (ident != null) {
5419                    module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
5420                } else {
5421                    ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME);
5422                    lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression));
5423                    if (!declaration) {
5424                        expect(SEMICOLON);
5425                    }
5426                    module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
5427                }
5428                break;
5429            case VAR:
5430            case LET:
5431            case CONST:
5432                final List<Statement> statements = lc.getCurrentBlock().getStatements();
5433                final int previousEnd = statements.size();
5434                variableStatement(type);
5435                for (final Statement statement : statements.subList(previousEnd, statements.size())) {
5436                    if (statement instanceof VarNode) {
5437                        module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName(), startPosition, finish));
5438                    }
5439                }
5440                break;
5441            case CLASS: {
5442                final ClassNode classDeclaration = classDeclaration(false);
5443                module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent(), startPosition, finish));
5444                break;
5445            }
5446            case FUNCTION: {
5447                final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true);
5448                module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent(), startPosition, finish));
5449                break;
5450            }
5451            default:
5452                throw error(AbstractParser.message("invalid.export"), token);
5453        }
5454    }
5455
5456    /**
5457     * ExportClause :
5458     *     { }
5459     *     { ExportsList }
5460     *     { ExportsList , }
5461     * ExportsList :
5462     *     ExportSpecifier
5463     *     ExportsList , ExportSpecifier
5464     * ExportSpecifier :
5465     *     IdentifierName
5466     *     IdentifierName as IdentifierName
5467     *
5468     * @return a list of ExportSpecifiers
5469     */
5470    private List<Module.ExportEntry> exportClause(final int startPosition) {
5471        assert type == LBRACE;
5472        next();
5473        final List<Module.ExportEntry> exports = new ArrayList<>();
5474        while (type != RBRACE) {
5475            final IdentNode localName = getIdentifierName();
5476            if (type == IDENT && "as".equals(getValue())) {
5477                next();
5478                final IdentNode exportName = getIdentifierName();
5479                exports.add(Module.ExportEntry.exportSpecifier(exportName, localName, startPosition, finish));
5480            } else {
5481                exports.add(Module.ExportEntry.exportSpecifier(localName, startPosition, finish));
5482            }
5483            if (type == COMMARIGHT) {
5484                next();
5485            } else {
5486                break;
5487            }
5488        }
5489        expect(RBRACE);
5490        return exports;
5491    }
5492
5493    @Override
5494    public String toString() {
5495        return "'JavaScript Parsing'";
5496    }
5497
5498    private static void markEval(final ParserContext lc) {
5499        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5500        boolean flaggedCurrentFn = false;
5501        while (iter.hasNext()) {
5502            final ParserContextFunctionNode fn = iter.next();
5503            if (!flaggedCurrentFn) {
5504                fn.setFlag(FunctionNode.HAS_EVAL);
5505                flaggedCurrentFn = true;
5506                if (fn.getKind() == FunctionNode.Kind.ARROW) {
5507                    // possible use of this in an eval that's nested in an arrow function, e.g.:
5508                    // function fun(){ return (() => eval("this"))(); };
5509                    markThis(lc);
5510                    markNewTarget(lc);
5511                }
5512            } else {
5513                fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
5514            }
5515            final ParserContextBlockNode body = lc.getFunctionBody(fn);
5516            // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
5517            // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
5518            // this method when the parser skips a nested function.
5519            body.setFlag(Block.NEEDS_SCOPE);
5520            fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
5521        }
5522    }
5523
5524    private void prependStatement(final Statement statement) {
5525        lc.prependStatementToCurrentNode(statement);
5526    }
5527
5528    private void appendStatement(final Statement statement) {
5529        lc.appendStatementToCurrentNode(statement);
5530    }
5531
5532    private static void markSuperCall(final ParserContext lc) {
5533        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5534        while (iter.hasNext()) {
5535            final ParserContextFunctionNode fn = iter.next();
5536            if (fn.getKind() != FunctionNode.Kind.ARROW) {
5537                assert fn.isSubclassConstructor();
5538                fn.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
5539                break;
5540            }
5541        }
5542    }
5543
5544    private ParserContextFunctionNode getCurrentNonArrowFunction() {
5545        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5546        while (iter.hasNext()) {
5547            final ParserContextFunctionNode fn = iter.next();
5548            if (fn.getKind() != FunctionNode.Kind.ARROW) {
5549                return fn;
5550            }
5551        }
5552        return null;
5553    }
5554
5555    private static void markThis(final ParserContext lc) {
5556        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5557        while (iter.hasNext()) {
5558            final ParserContextFunctionNode fn = iter.next();
5559            fn.setFlag(FunctionNode.USES_THIS);
5560            if (fn.getKind() != FunctionNode.Kind.ARROW) {
5561                break;
5562            }
5563        }
5564    }
5565
5566    private static void markNewTarget(final ParserContext lc) {
5567        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
5568        while (iter.hasNext()) {
5569            final ParserContextFunctionNode fn = iter.next();
5570            if (fn.getKind() != FunctionNode.Kind.ARROW) {
5571                if (!fn.isProgram()) {
5572                    fn.setFlag(FunctionNode.ES6_USES_NEW_TARGET);
5573                }
5574                break;
5575            }
5576        }
5577    }
5578
5579    private boolean inGeneratorFunction() {
5580        return lc.getCurrentFunction().getKind() == FunctionNode.Kind.GENERATOR;
5581    }
5582}
5583