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