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