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