Parser.java revision 1655:3ac5d360070e
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.ASSIGN;
32import static jdk.nashorn.internal.parser.TokenType.CASE;
33import static jdk.nashorn.internal.parser.TokenType.CATCH;
34import static jdk.nashorn.internal.parser.TokenType.COLON;
35import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
36import static jdk.nashorn.internal.parser.TokenType.CONST;
37import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
38import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
39import static jdk.nashorn.internal.parser.TokenType.ELSE;
40import static jdk.nashorn.internal.parser.TokenType.EOF;
41import static jdk.nashorn.internal.parser.TokenType.EOL;
42import static jdk.nashorn.internal.parser.TokenType.FINALLY;
43import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
44import static jdk.nashorn.internal.parser.TokenType.IDENT;
45import static jdk.nashorn.internal.parser.TokenType.IF;
46import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
47import static jdk.nashorn.internal.parser.TokenType.LBRACE;
48import static jdk.nashorn.internal.parser.TokenType.LET;
49import static jdk.nashorn.internal.parser.TokenType.LPAREN;
50import static jdk.nashorn.internal.parser.TokenType.RBRACE;
51import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
52import static jdk.nashorn.internal.parser.TokenType.RPAREN;
53import static jdk.nashorn.internal.parser.TokenType.SEMICOLON;
54import static jdk.nashorn.internal.parser.TokenType.TEMPLATE;
55import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_HEAD;
56import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_MIDDLE;
57import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_TAIL;
58import static jdk.nashorn.internal.parser.TokenType.TERNARY;
59import static jdk.nashorn.internal.parser.TokenType.WHILE;
60
61import java.io.Serializable;
62import java.util.ArrayDeque;
63import java.util.ArrayList;
64import java.util.Collections;
65import java.util.Deque;
66import java.util.HashMap;
67import java.util.HashSet;
68import java.util.Iterator;
69import java.util.List;
70import java.util.Map;
71import jdk.nashorn.internal.codegen.CompilerConstants;
72import jdk.nashorn.internal.codegen.Namespace;
73import jdk.nashorn.internal.ir.AccessNode;
74import jdk.nashorn.internal.ir.BaseNode;
75import jdk.nashorn.internal.ir.BinaryNode;
76import jdk.nashorn.internal.ir.Block;
77import jdk.nashorn.internal.ir.BlockStatement;
78import jdk.nashorn.internal.ir.BreakNode;
79import jdk.nashorn.internal.ir.CallNode;
80import jdk.nashorn.internal.ir.CaseNode;
81import jdk.nashorn.internal.ir.CatchNode;
82import jdk.nashorn.internal.ir.ContinueNode;
83import jdk.nashorn.internal.ir.DebuggerNode;
84import jdk.nashorn.internal.ir.EmptyNode;
85import jdk.nashorn.internal.ir.ErrorNode;
86import jdk.nashorn.internal.ir.Expression;
87import jdk.nashorn.internal.ir.ExpressionStatement;
88import jdk.nashorn.internal.ir.ForNode;
89import jdk.nashorn.internal.ir.FunctionNode;
90import jdk.nashorn.internal.ir.IdentNode;
91import jdk.nashorn.internal.ir.IfNode;
92import jdk.nashorn.internal.ir.IndexNode;
93import jdk.nashorn.internal.ir.JoinPredecessorExpression;
94import jdk.nashorn.internal.ir.LabelNode;
95import jdk.nashorn.internal.ir.LiteralNode;
96import jdk.nashorn.internal.ir.Node;
97import jdk.nashorn.internal.ir.ObjectNode;
98import jdk.nashorn.internal.ir.PropertyKey;
99import jdk.nashorn.internal.ir.PropertyNode;
100import jdk.nashorn.internal.ir.ReturnNode;
101import jdk.nashorn.internal.ir.RuntimeNode;
102import jdk.nashorn.internal.ir.Statement;
103import jdk.nashorn.internal.ir.SwitchNode;
104import jdk.nashorn.internal.ir.TernaryNode;
105import jdk.nashorn.internal.ir.ThrowNode;
106import jdk.nashorn.internal.ir.TryNode;
107import jdk.nashorn.internal.ir.UnaryNode;
108import jdk.nashorn.internal.ir.VarNode;
109import jdk.nashorn.internal.ir.WhileNode;
110import jdk.nashorn.internal.ir.WithNode;
111import jdk.nashorn.internal.ir.debug.ASTWriter;
112import jdk.nashorn.internal.ir.debug.PrintVisitor;
113import jdk.nashorn.internal.runtime.Context;
114import jdk.nashorn.internal.runtime.ErrorManager;
115import jdk.nashorn.internal.runtime.JSErrorType;
116import jdk.nashorn.internal.runtime.ParserException;
117import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
118import jdk.nashorn.internal.runtime.ScriptEnvironment;
119import jdk.nashorn.internal.runtime.ScriptingFunctions;
120import jdk.nashorn.internal.runtime.Source;
121import jdk.nashorn.internal.runtime.Timing;
122import jdk.nashorn.internal.runtime.linker.NameCodec;
123import jdk.nashorn.internal.runtime.logging.DebugLogger;
124import jdk.nashorn.internal.runtime.logging.Loggable;
125import jdk.nashorn.internal.runtime.logging.Logger;
126
127/**
128 * Builds the IR.
129 */
130@Logger(name="parser")
131public class Parser extends AbstractParser implements Loggable {
132    private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName();
133
134    /** Current env. */
135    private final ScriptEnvironment env;
136
137    /** Is scripting mode. */
138    private final boolean scripting;
139
140    private List<Statement> functionDeclarations;
141
142    private final ParserContext lc;
143    private final Deque<Object> defaultNames;
144
145    /** Namespace for function names where not explicitly given */
146    private final Namespace namespace;
147
148    private final DebugLogger log;
149
150    /** to receive line information from Lexer when scanning multine literals. */
151    protected final Lexer.LineInfoReceiver lineInfoReceiver;
152
153    private RecompilableScriptFunctionData reparsedFunction;
154
155    /**
156     * Constructor
157     *
158     * @param env     script environment
159     * @param source  source to parse
160     * @param errors  error manager
161     */
162    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors) {
163        this(env, source, errors, env._strict, null);
164    }
165
166    /**
167     * Constructor
168     *
169     * @param env     script environment
170     * @param source  source to parse
171     * @param errors  error manager
172     * @param strict  strict
173     * @param log debug logger if one is needed
174     */
175    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) {
176        this(env, source, errors, strict, 0, log);
177    }
178
179    /**
180     * Construct a parser.
181     *
182     * @param env     script environment
183     * @param source  source to parse
184     * @param errors  error manager
185     * @param strict  parser created with strict mode enabled.
186     * @param lineOffset line offset to start counting lines from
187     * @param log debug logger if one is needed
188     */
189    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) {
190        super(source, errors, strict, lineOffset);
191        this.lc = new ParserContext();
192        this.defaultNames = new ArrayDeque<>();
193        this.env = env;
194        this.namespace = new Namespace(env.getNamespace());
195        this.scripting = env._scripting;
196        if (this.scripting) {
197            this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
198                @Override
199                public void lineInfo(final int receiverLine, final int receiverLinePosition) {
200                    // update the parser maintained line information
201                    Parser.this.line = receiverLine;
202                    Parser.this.linePosition = receiverLinePosition;
203                }
204            };
205        } else {
206            // non-scripting mode script can't have multi-line literals
207            this.lineInfoReceiver = null;
208        }
209
210        this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
211    }
212
213    @Override
214    public DebugLogger getLogger() {
215        return log;
216    }
217
218    @Override
219    public DebugLogger initLogger(final Context context) {
220        return context.getLogger(this.getClass());
221    }
222
223    /**
224     * Sets the name for the first function. This is only used when reparsing anonymous functions to ensure they can
225     * preserve their already assigned name, as that name doesn't appear in their source text.
226     * @param name the name for the first parsed function.
227     */
228    public void setFunctionName(final String name) {
229        defaultNames.push(createIdentNode(0, 0, name));
230    }
231
232    /**
233     * Sets the {@link RecompilableScriptFunctionData} representing the function being reparsed (when this
234     * parser instance is used to reparse a previously parsed function, as part of its on-demand compilation).
235     * This will trigger various special behaviors, such as skipping nested function bodies.
236     * @param reparsedFunction the function being reparsed.
237     */
238    public void setReparsedFunction(final RecompilableScriptFunctionData reparsedFunction) {
239        this.reparsedFunction = reparsedFunction;
240    }
241
242    /**
243     * Execute parse and return the resulting function node.
244     * Errors will be thrown and the error manager will contain information
245     * if parsing should fail
246     *
247     * This is the default parse call, which will name the function node
248     * {code :program} {@link CompilerConstants#PROGRAM}
249     *
250     * @return function node resulting from successful parse
251     */
252    public FunctionNode parse() {
253        return parse(PROGRAM.symbolName(), 0, source.getLength(), false);
254    }
255
256    /**
257     * Execute parse and return the resulting function node.
258     * Errors will be thrown and the error manager will contain information
259     * if parsing should fail
260     *
261     * This should be used to create one and only one function node
262     *
263     * @param scriptName name for the script, given to the parsed FunctionNode
264     * @param startPos start position in source
265     * @param len length of parse
266     * @param allowPropertyFunction if true, "get" and "set" are allowed as first tokens of the program, followed by
267     * a property getter or setter function. This is used when reparsing a function that can potentially be defined as a
268     * property getter or setter in an object literal.
269     *
270     * @return function node resulting from successful parse
271     */
272    public FunctionNode parse(final String scriptName, final int startPos, final int len, final boolean allowPropertyFunction) {
273        final boolean isTimingEnabled = env.isTimingEnabled();
274        final long t0 = isTimingEnabled ? System.nanoTime() : 0L;
275        log.info(this, " begin for '", scriptName, "'");
276
277        try {
278            stream = new TokenStream();
279            lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
280            lexer.line = lexer.pendingLine = lineOffset + 1;
281            line = lineOffset;
282
283            // Set up first token (skips opening EOL.)
284            k = -1;
285            next();
286            // Begin parse.
287            return program(scriptName, allowPropertyFunction);
288        } catch (final Exception e) {
289            handleParseException(e);
290
291            return null;
292        } finally {
293            final String end = this + " end '" + scriptName + "'";
294            if (isTimingEnabled) {
295                env._timing.accumulateTime(toString(), System.nanoTime() - t0);
296                log.info(end, "' in ", Timing.toMillisPrint(System.nanoTime() - t0), " ms");
297            } else {
298                log.info(end);
299            }
300        }
301    }
302
303    /**
304     * Parse and return the list of function parameter list. A comma
305     * separated list of function parameter identifiers is expected to be parsed.
306     * Errors will be thrown and the error manager will contain information
307     * if parsing should fail. This method is used to check if parameter Strings
308     * passed to "Function" constructor is a valid or not.
309     *
310     * @return the list of IdentNodes representing the formal parameter list
311     */
312    public List<IdentNode> parseFormalParameterList() {
313        try {
314            stream = new TokenStream();
315            lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
316
317            // Set up first token (skips opening EOL.)
318            k = -1;
319            next();
320
321            return formalParameterList(TokenType.EOF);
322        } catch (final Exception e) {
323            handleParseException(e);
324            return null;
325        }
326    }
327
328    /**
329     * Execute parse and return the resulting function node.
330     * Errors will be thrown and the error manager will contain information
331     * if parsing should fail. This method is used to check if code String
332     * passed to "Function" constructor is a valid function body or not.
333     *
334     * @return function node resulting from successful parse
335     */
336    public FunctionNode parseFunctionBody() {
337        try {
338            stream = new TokenStream();
339            lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
340            final int functionLine = line;
341
342            // Set up first token (skips opening EOL.)
343            k = -1;
344            next();
345
346            // Make a fake token for the function.
347            final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
348            // Set up the function to append elements.
349
350            final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName());
351            final ParserContextFunctionNode function = createParserContextFunctionNode(ident, functionToken, FunctionNode.Kind.NORMAL, functionLine, Collections.<IdentNode>emptyList());
352            lc.push(function);
353
354            final ParserContextBlockNode body = newBlock();
355
356            functionDeclarations = new ArrayList<>();
357            sourceElements(false);
358            addFunctionDeclarations(function);
359            functionDeclarations = null;
360
361            restoreBlock(body);
362            body.setFlag(Block.NEEDS_SCOPE);
363
364            final Block functionBody = new Block(functionToken, source.getLength() - 1,
365                body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
366            lc.pop(function);
367
368            expect(EOF);
369
370            final FunctionNode functionNode = createFunctionNode(
371                    function,
372                    functionToken,
373                    ident,
374                    Collections.<IdentNode>emptyList(),
375                    FunctionNode.Kind.NORMAL,
376                    functionLine,
377                    functionBody);
378            printAST(functionNode);
379            return functionNode;
380        } catch (final Exception e) {
381            handleParseException(e);
382            return null;
383        }
384    }
385
386    private void handleParseException(final Exception e) {
387        // Extract message from exception.  The message will be in error
388        // message format.
389        String message = e.getMessage();
390
391        // If empty message.
392        if (message == null) {
393            message = e.toString();
394        }
395
396        // Issue message.
397        if (e instanceof ParserException) {
398            errors.error((ParserException)e);
399        } else {
400            errors.error(message);
401        }
402
403        if (env._dump_on_error) {
404            e.printStackTrace(env.getErr());
405        }
406    }
407
408    /**
409     * Skip to a good parsing recovery point.
410     */
411    private void recover(final Exception e) {
412        if (e != null) {
413            // Extract message from exception.  The message will be in error
414            // message format.
415            String message = e.getMessage();
416
417            // If empty message.
418            if (message == null) {
419                message = e.toString();
420            }
421
422            // Issue message.
423            if (e instanceof ParserException) {
424                errors.error((ParserException)e);
425            } else {
426                errors.error(message);
427            }
428
429            if (env._dump_on_error) {
430                e.printStackTrace(env.getErr());
431            }
432        }
433
434        // Skip to a recovery point.
435loop:
436        while (true) {
437            switch (type) {
438            case EOF:
439                // Can not go any further.
440                break loop;
441            case EOL:
442            case SEMICOLON:
443            case RBRACE:
444                // Good recovery points.
445                next();
446                break loop;
447            default:
448                // So we can recover after EOL.
449                nextOrEOL();
450                break;
451            }
452        }
453    }
454
455    /**
456     * Set up a new block.
457     *
458     * @return New block.
459     */
460    private ParserContextBlockNode newBlock() {
461        return lc.push(new ParserContextBlockNode(token));
462    }
463
464    private ParserContextFunctionNode createParserContextFunctionNode(final IdentNode ident, final long functionToken, final FunctionNode.Kind kind, final int functionLine, final List<IdentNode> parameters) {
465        // Build function name.
466        final StringBuilder sb = new StringBuilder();
467
468        final ParserContextFunctionNode parentFunction = lc.getCurrentFunction();
469        if (parentFunction != null && !parentFunction.isProgram()) {
470            sb.append(parentFunction.getName()).append('$');
471        }
472
473        assert ident.getName() != null;
474        sb.append(ident.getName());
475
476        final String name = namespace.uniqueName(sb.toString());
477        assert parentFunction != null || name.equals(PROGRAM.symbolName()) || name.startsWith(RecompilableScriptFunctionData.RECOMPILATION_PREFIX) : "name = " + name;
478
479        int flags = 0;
480        if (isStrictMode) {
481            flags |= FunctionNode.IS_STRICT;
482        }
483        if (parentFunction == null) {
484            flags |= FunctionNode.IS_PROGRAM;
485        }
486
487        final ParserContextFunctionNode functionNode = new ParserContextFunctionNode(functionToken, ident, name, namespace, functionLine, kind, parameters);
488        functionNode.setFlag(flags);
489        return functionNode;
490    }
491
492    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){
493        // Start new block.
494        final FunctionNode functionNode =
495            new FunctionNode(
496                source,
497                functionLine,
498                body.getToken(),
499                Token.descPosition(body.getToken()),
500                startToken,
501                function.getLastToken(),
502                namespace,
503                ident,
504                function.getName(),
505                parameters,
506                kind,
507                function.getFlags(),
508                body,
509                function.getEndParserState());
510
511        printAST(functionNode);
512
513        return functionNode;
514    }
515
516    /**
517     * Restore the current block.
518     */
519    private ParserContextBlockNode restoreBlock(final ParserContextBlockNode block) {
520        return lc.pop(block);
521    }
522
523    /**
524     * Get the statements in a block.
525     * @return Block statements.
526     */
527    private Block getBlock(final boolean needsBraces) {
528        final long blockToken = token;
529        final ParserContextBlockNode newBlock = newBlock();
530        try {
531            // Block opening brace.
532            if (needsBraces) {
533                expect(LBRACE);
534            }
535            // Accumulate block statements.
536            statementList();
537
538        } finally {
539            restoreBlock(newBlock);
540        }
541
542        // Block closing brace.
543        if (needsBraces) {
544            expect(RBRACE);
545        }
546
547        final int flags = newBlock.getFlags() | (needsBraces? 0 : Block.IS_SYNTHETIC);
548        return new Block(blockToken, finish, flags, newBlock.getStatements());
549    }
550
551
552    /**
553     * Get all the statements generated by a single statement.
554     * @return Statements.
555     */
556    private Block getStatement() {
557        if (type == LBRACE) {
558            return getBlock(true);
559        }
560        // Set up new block. Captures first token.
561        final ParserContextBlockNode newBlock = newBlock();
562        try {
563            statement(false, false, true);
564        } finally {
565            restoreBlock(newBlock);
566        }
567        return new Block(newBlock.getToken(), finish, newBlock.getFlags() | Block.IS_SYNTHETIC, newBlock.getStatements());
568    }
569
570    /**
571     * Detect calls to special functions.
572     * @param ident Called function.
573     */
574    private void detectSpecialFunction(final IdentNode ident) {
575        final String name = ident.getName();
576
577        if (EVAL.symbolName().equals(name)) {
578            markEval(lc);
579        }
580    }
581
582    /**
583     * Detect use of special properties.
584     * @param ident Referenced property.
585     */
586    private void detectSpecialProperty(final IdentNode ident) {
587        if (isArguments(ident)) {
588            lc.getCurrentFunction().setFlag(FunctionNode.USES_ARGUMENTS);
589        }
590    }
591
592    private boolean useBlockScope() {
593        return env._es6;
594    }
595
596    private static boolean isArguments(final String name) {
597        return ARGUMENTS_NAME.equals(name);
598    }
599
600    private static boolean isArguments(final IdentNode ident) {
601        return isArguments(ident.getName());
602    }
603
604    /**
605     * Tells whether a IdentNode can be used as L-value of an assignment
606     *
607     * @param ident IdentNode to be checked
608     * @return whether the ident can be used as L-value
609     */
610    private static boolean checkIdentLValue(final IdentNode ident) {
611        return ident.tokenType().getKind() != TokenKind.KEYWORD;
612    }
613
614    /**
615     * Verify an assignment expression.
616     * @param op  Operation token.
617     * @param lhs Left hand side expression.
618     * @param rhs Right hand side expression.
619     * @return Verified expression.
620     */
621    private Expression verifyAssignment(final long op, final Expression lhs, final Expression rhs) {
622        final TokenType opType = Token.descType(op);
623
624        switch (opType) {
625        case ASSIGN:
626        case ASSIGN_ADD:
627        case ASSIGN_BIT_AND:
628        case ASSIGN_BIT_OR:
629        case ASSIGN_BIT_XOR:
630        case ASSIGN_DIV:
631        case ASSIGN_MOD:
632        case ASSIGN_MUL:
633        case ASSIGN_SAR:
634        case ASSIGN_SHL:
635        case ASSIGN_SHR:
636        case ASSIGN_SUB:
637            if (!(lhs instanceof AccessNode ||
638                  lhs instanceof IndexNode ||
639                  lhs instanceof IdentNode)) {
640                return referenceError(lhs, rhs, env._early_lvalue_error);
641            }
642
643            if (lhs instanceof IdentNode) {
644                if (!checkIdentLValue((IdentNode)lhs)) {
645                    return referenceError(lhs, rhs, false);
646                }
647                verifyStrictIdent((IdentNode)lhs, "assignment");
648            }
649            break;
650
651        default:
652            break;
653        }
654
655        // Build up node.
656        if(BinaryNode.isLogical(opType)) {
657            return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs));
658        }
659        return new BinaryNode(op, lhs, rhs);
660    }
661
662
663    /**
664     * Reduce increment/decrement to simpler operations.
665     * @param firstToken First token.
666     * @param tokenType  Operation token (INCPREFIX/DEC.)
667     * @param expression Left hand side expression.
668     * @param isPostfix  Prefix or postfix.
669     * @return           Reduced expression.
670     */
671    private static UnaryNode incDecExpression(final long firstToken, final TokenType tokenType, final Expression expression, final boolean isPostfix) {
672        if (isPostfix) {
673            return new UnaryNode(Token.recast(firstToken, tokenType == DECPREFIX ? DECPOSTFIX : INCPOSTFIX), expression.getStart(), Token.descPosition(firstToken) + Token.descLength(firstToken), expression);
674        }
675
676        return new UnaryNode(firstToken, expression);
677    }
678
679    /**
680     * -----------------------------------------------------------------------
681     *
682     * Grammar based on
683     *
684     *      ECMAScript Language Specification
685     *      ECMA-262 5th Edition / December 2009
686     *
687     * -----------------------------------------------------------------------
688     */
689
690    /**
691     * Program :
692     *      SourceElements?
693     *
694     * See 14
695     *
696     * Parse the top level script.
697     */
698    private FunctionNode program(final String scriptName, final boolean allowPropertyFunction) {
699        // Make a pseudo-token for the script holding its start and length.
700        final long functionToken = Token.toDesc(FUNCTION, Token.descPosition(Token.withDelimiter(token)), source.getLength());
701        final int  functionLine  = line;
702
703        final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), scriptName);
704        final ParserContextFunctionNode script = createParserContextFunctionNode(
705                ident,
706                functionToken,
707                FunctionNode.Kind.SCRIPT,
708                functionLine,
709                Collections.<IdentNode>emptyList());
710        lc.push(script);
711        final ParserContextBlockNode body = newBlock();
712
713        functionDeclarations = new ArrayList<>();
714        sourceElements(allowPropertyFunction);
715        addFunctionDeclarations(script);
716        functionDeclarations = null;
717
718        restoreBlock(body);
719        body.setFlag(Block.NEEDS_SCOPE);
720        final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
721        lc.pop(script);
722        script.setLastToken(token);
723
724        expect(EOF);
725
726        return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.SCRIPT, functionLine, programBody);
727    }
728
729    /**
730     * Directive value or null if statement is not a directive.
731     *
732     * @param stmt Statement to be checked
733     * @return Directive value if the given statement is a directive
734     */
735    private String getDirective(final Node stmt) {
736        if (stmt instanceof ExpressionStatement) {
737            final Node expr = ((ExpressionStatement)stmt).getExpression();
738            if (expr instanceof LiteralNode) {
739                final LiteralNode<?> lit = (LiteralNode<?>)expr;
740                final long litToken = lit.getToken();
741                final TokenType tt = Token.descType(litToken);
742                // A directive is either a string or an escape string
743                if (tt == TokenType.STRING || tt == TokenType.ESCSTRING) {
744                    // Make sure that we don't unescape anything. Return as seen in source!
745                    return source.getString(lit.getStart(), Token.descLength(litToken));
746                }
747            }
748        }
749
750        return null;
751    }
752
753    /**
754     * SourceElements :
755     *      SourceElement
756     *      SourceElements SourceElement
757     *
758     * See 14
759     *
760     * Parse the elements of the script or function.
761     */
762    private void sourceElements(final boolean shouldAllowPropertyFunction) {
763        List<Node>    directiveStmts        = null;
764        boolean       checkDirective        = true;
765        boolean       allowPropertyFunction = shouldAllowPropertyFunction;
766        final boolean oldStrictMode         = isStrictMode;
767
768
769        try {
770            // If is a script, then process until the end of the script.
771            while (type != EOF) {
772                // Break if the end of a code block.
773                if (type == RBRACE) {
774                    break;
775                }
776
777                try {
778                    // Get the next element.
779                    statement(true, allowPropertyFunction, false);
780                    allowPropertyFunction = false;
781
782                    // check for directive prologues
783                    if (checkDirective) {
784                        // skip any debug statement like line number to get actual first line
785                        final Statement lastStatement = lc.getLastStatement();
786
787                        // get directive prologue, if any
788                        final String directive = getDirective(lastStatement);
789
790                        // If we have seen first non-directive statement,
791                        // no more directive statements!!
792                        checkDirective = directive != null;
793
794                        if (checkDirective) {
795                            if (!oldStrictMode) {
796                                if (directiveStmts == null) {
797                                    directiveStmts = new ArrayList<>();
798                                }
799                                directiveStmts.add(lastStatement);
800                            }
801
802                            // handle use strict directive
803                            if ("use strict".equals(directive)) {
804                                isStrictMode = true;
805                                final ParserContextFunctionNode function = lc.getCurrentFunction();
806                                function.setFlag(FunctionNode.IS_STRICT);
807
808                                // We don't need to check these, if lexical environment is already strict
809                                if (!oldStrictMode && directiveStmts != null) {
810                                    // check that directives preceding this one do not violate strictness
811                                    for (final Node statement : directiveStmts) {
812                                        // the get value will force unescape of preceding
813                                        // escaped string directives
814                                        getValue(statement.getToken());
815                                    }
816
817                                    // verify that function name as well as parameter names
818                                    // satisfy strict mode restrictions.
819                                    verifyStrictIdent(function.getIdent(), "function name");
820                                    for (final IdentNode param : function.getParameters()) {
821                                        verifyStrictIdent(param, "function parameter");
822                                    }
823                                }
824                            } else if (Context.DEBUG) {
825                                final int flag = FunctionNode.getDirectiveFlag(directive);
826                                if (flag != 0) {
827                                    final ParserContextFunctionNode function = lc.getCurrentFunction();
828                                    function.setFlag(flag);
829                                }
830                            }
831                        }
832                    }
833                } catch (final Exception e) {
834                    final int errorLine = line;
835                    final long errorToken = token;
836                    //recover parsing
837                    recover(e);
838                    final ErrorNode errorExpr = new ErrorNode(errorToken, finish);
839                    final ExpressionStatement expressionStatement = new ExpressionStatement(errorLine, errorToken, finish, errorExpr);
840                    appendStatement(expressionStatement);
841                }
842
843                // No backtracking from here on.
844                stream.commit(k);
845            }
846        } finally {
847            isStrictMode = oldStrictMode;
848        }
849    }
850
851    /**
852     * Statement :
853     *      Block
854     *      VariableStatement
855     *      EmptyStatement
856     *      ExpressionStatement
857     *      IfStatement
858     *      IterationStatement
859     *      ContinueStatement
860     *      BreakStatement
861     *      ReturnStatement
862     *      WithStatement
863     *      LabelledStatement
864     *      SwitchStatement
865     *      ThrowStatement
866     *      TryStatement
867     *      DebuggerStatement
868     *
869     * see 12
870     *
871     * Parse any of the basic statement types.
872     */
873    private void statement() {
874        statement(false, false, false);
875    }
876
877    /**
878     * @param topLevel does this statement occur at the "top level" of a script or a function?
879     * @param allowPropertyFunction allow property "get" and "set" functions?
880     * @param singleStatement are we in a single statement context?
881     */
882    private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
883        if (type == FUNCTION) {
884            // As per spec (ECMA section 12), function declarations as arbitrary statement
885            // is not "portable". Implementation can issue a warning or disallow the same.
886            functionExpression(true, topLevel);
887            return;
888        }
889
890        switch (type) {
891        case LBRACE:
892            block();
893            break;
894        case VAR:
895            variableStatement(type);
896            break;
897        case SEMICOLON:
898            emptyStatement();
899            break;
900        case IF:
901            ifStatement();
902            break;
903        case FOR:
904            forStatement();
905            break;
906        case WHILE:
907            whileStatement();
908            break;
909        case DO:
910            doStatement();
911            break;
912        case CONTINUE:
913            continueStatement();
914            break;
915        case BREAK:
916            breakStatement();
917            break;
918        case RETURN:
919            returnStatement();
920            break;
921        case YIELD:
922            yieldStatement();
923            break;
924        case WITH:
925            withStatement();
926            break;
927        case SWITCH:
928            switchStatement();
929            break;
930        case THROW:
931            throwStatement();
932            break;
933        case TRY:
934            tryStatement();
935            break;
936        case DEBUGGER:
937            debuggerStatement();
938            break;
939        case RPAREN:
940        case RBRACKET:
941        case EOF:
942            expect(SEMICOLON);
943            break;
944        default:
945            if (useBlockScope() && (type == LET || type == CONST)) {
946                if (singleStatement) {
947                    throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
948                }
949                variableStatement(type);
950                break;
951            }
952            if (env._const_as_var && type == CONST) {
953                variableStatement(TokenType.VAR);
954                break;
955            }
956
957            if (type == IDENT || isNonStrictModeIdent()) {
958                if (T(k + 1) == COLON) {
959                    labelStatement();
960                    return;
961                }
962                if(allowPropertyFunction) {
963                    final String ident = (String)getValue();
964                    final long propertyToken = token;
965                    final int propertyLine = line;
966                    if("get".equals(ident)) {
967                        next();
968                        addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
969                        return;
970                    } else if("set".equals(ident)) {
971                        next();
972                        addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
973                        return;
974                    }
975                }
976            }
977
978            expressionStatement();
979            break;
980        }
981    }
982
983    private void addPropertyFunctionStatement(final PropertyFunction propertyFunction) {
984        final FunctionNode fn = propertyFunction.functionNode;
985        functionDeclarations.add(new ExpressionStatement(fn.getLineNumber(), fn.getToken(), finish, fn));
986    }
987
988    /**
989     * block :
990     *      { StatementList? }
991     *
992     * see 12.1
993     *
994     * Parse a statement block.
995     */
996    private void block() {
997        appendStatement(new BlockStatement(line, getBlock(true)));
998    }
999
1000    /**
1001     * StatementList :
1002     *      Statement
1003     *      StatementList Statement
1004     *
1005     * See 12.1
1006     *
1007     * Parse a list of statements.
1008     */
1009    private void statementList() {
1010        // Accumulate statements until end of list. */
1011loop:
1012        while (type != EOF) {
1013            switch (type) {
1014            case EOF:
1015            case CASE:
1016            case DEFAULT:
1017            case RBRACE:
1018                break loop;
1019            default:
1020                break;
1021            }
1022
1023            // Get next statement.
1024            statement();
1025        }
1026    }
1027
1028    /**
1029     * Make sure that in strict mode, the identifier name used is allowed.
1030     *
1031     * @param ident         Identifier that is verified
1032     * @param contextString String used in error message to give context to the user
1033     */
1034    private void verifyStrictIdent(final IdentNode ident, final String contextString) {
1035        if (isStrictMode) {
1036            switch (ident.getName()) {
1037            case "eval":
1038            case "arguments":
1039                throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1040            default:
1041                break;
1042            }
1043
1044            if (ident.isFutureStrictName()) {
1045                throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1046            }
1047        }
1048    }
1049
1050    /*
1051     * VariableStatement :
1052     *      var VariableDeclarationList ;
1053     *
1054     * VariableDeclarationList :
1055     *      VariableDeclaration
1056     *      VariableDeclarationList , VariableDeclaration
1057     *
1058     * VariableDeclaration :
1059     *      Identifier Initializer?
1060     *
1061     * Initializer :
1062     *      = AssignmentExpression
1063     *
1064     * See 12.2
1065     *
1066     * Parse a VAR statement.
1067     * @param isStatement True if a statement (not used in a FOR.)
1068     */
1069    private List<VarNode> variableStatement(final TokenType varType) {
1070        return variableStatement(varType, true, -1);
1071    }
1072
1073    private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) {
1074        // VAR tested in caller.
1075        next();
1076
1077        final List<VarNode> vars = new ArrayList<>();
1078        int varFlags = 0;
1079        if (varType == LET) {
1080            varFlags |= VarNode.IS_LET;
1081        } else if (varType == CONST) {
1082            varFlags |= VarNode.IS_CONST;
1083        }
1084
1085        while (true) {
1086            // Get starting token.
1087            final int  varLine  = line;
1088            final long varToken = token;
1089            // Get name of var.
1090            final IdentNode name = getIdent();
1091            verifyStrictIdent(name, "variable name");
1092
1093            // Assume no init.
1094            Expression init = null;
1095
1096            // Look for initializer assignment.
1097            if (type == ASSIGN) {
1098                next();
1099
1100                // Get initializer expression. Suppress IN if not statement.
1101                defaultNames.push(name);
1102                try {
1103                    init = assignmentExpression(!isStatement);
1104                } finally {
1105                    defaultNames.pop();
1106                }
1107            } else if (varType == CONST && isStatement) {
1108                throw error(AbstractParser.message("missing.const.assignment", name.getName()));
1109            }
1110
1111            // Only set declaration flag on lexically scoped let/const as it adds runtime overhead.
1112            final IdentNode actualName = varType == LET || varType == CONST ? name.setIsDeclaredHere() : name;
1113            // Allocate var node.
1114            final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, actualName, init, varFlags);
1115            vars.add(var);
1116            appendStatement(var);
1117
1118            if (type != COMMARIGHT) {
1119                break;
1120            }
1121            next();
1122        }
1123
1124        // If is a statement then handle end of line.
1125        if (isStatement) {
1126            endOfLine();
1127        }
1128
1129        return vars;
1130    }
1131
1132    /**
1133     * EmptyStatement :
1134     *      ;
1135     *
1136     * See 12.3
1137     *
1138     * Parse an empty statement.
1139     */
1140    private void emptyStatement() {
1141        if (env._empty_statements) {
1142            appendStatement(new EmptyNode(line, token, Token.descPosition(token) + Token.descLength(token)));
1143        }
1144
1145        // SEMICOLON checked in caller.
1146        next();
1147    }
1148
1149    /**
1150     * ExpressionStatement :
1151     *      Expression ; // [lookahead ~( or  function )]
1152     *
1153     * See 12.4
1154     *
1155     * Parse an expression used in a statement block.
1156     */
1157    private void expressionStatement() {
1158        // Lookahead checked in caller.
1159        final int  expressionLine  = line;
1160        final long expressionToken = token;
1161
1162        // Get expression and add as statement.
1163        final Expression expression = expression();
1164
1165        ExpressionStatement expressionStatement = null;
1166        if (expression != null) {
1167            expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
1168            appendStatement(expressionStatement);
1169        } else {
1170            expect(null);
1171        }
1172
1173        endOfLine();
1174    }
1175
1176    /**
1177     * IfStatement :
1178     *      if ( Expression ) Statement else Statement
1179     *      if ( Expression ) Statement
1180     *
1181     * See 12.5
1182     *
1183     * Parse an IF statement.
1184     */
1185    private void ifStatement() {
1186        // Capture IF token.
1187        final int  ifLine  = line;
1188        final long ifToken = token;
1189         // IF tested in caller.
1190        next();
1191
1192        expect(LPAREN);
1193        final Expression test = expression();
1194        expect(RPAREN);
1195        final Block pass = getStatement();
1196
1197        Block fail = null;
1198        if (type == ELSE) {
1199            next();
1200            fail = getStatement();
1201        }
1202
1203        appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1204    }
1205
1206    /**
1207     * ... IterationStatement:
1208     *           ...
1209     *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1210     *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1211     *           for ( LeftHandSideExpression in Expression ) Statement
1212     *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1213     *
1214     * See 12.6
1215     *
1216     * Parse a FOR statement.
1217     */
1218    @SuppressWarnings("fallthrough")
1219    private void forStatement() {
1220        final long forToken = token;
1221        final int forLine = line;
1222        // start position of this for statement. This is used
1223        // for sort order for variables declared in the initializer
1224        // part of this 'for' statement (if any).
1225        final int forStart = Token.descPosition(forToken);
1226        // When ES6 for-let is enabled we create a container block to capture the LET.
1227        final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1228
1229        // Create FOR node, capturing FOR token.
1230        final ParserContextLoopNode forNode = new ParserContextLoopNode();
1231        lc.push(forNode);
1232        Block body = null;
1233        List<VarNode> vars = null;
1234        Expression init = null;
1235        JoinPredecessorExpression test = null;
1236        JoinPredecessorExpression modify = null;
1237
1238        int flags = 0;
1239        boolean isForOf = false;
1240
1241        try {
1242            // FOR tested in caller.
1243            next();
1244
1245            // Nashorn extension: for each expression.
1246            // iterate property values rather than property names.
1247            if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1248                flags |= ForNode.IS_FOR_EACH;
1249                next();
1250            }
1251
1252            expect(LPAREN);
1253
1254            switch (type) {
1255            case VAR:
1256                // Var declaration captured in for outer block.
1257                vars = variableStatement(type, false, forStart);
1258                break;
1259            case SEMICOLON:
1260                break;
1261            default:
1262                if (useBlockScope() && (type == LET || type == CONST)) {
1263                    flags |= ForNode.PER_ITERATION_SCOPE;
1264                    // LET/CONST declaration captured in container block created above.
1265                    vars = variableStatement(type, false, forStart);
1266                    break;
1267                }
1268                if (env._const_as_var && type == CONST) {
1269                    // Var declaration captured in for outer block.
1270                    vars = variableStatement(TokenType.VAR, false, forStart);
1271                    break;
1272                }
1273
1274                init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1275                break;
1276            }
1277
1278            switch (type) {
1279            case SEMICOLON:
1280                // for (init; test; modify)
1281
1282                // for each (init; test; modify) is invalid
1283                if ((flags & ForNode.IS_FOR_EACH) != 0) {
1284                    throw error(AbstractParser.message("for.each.without.in"), token);
1285                }
1286
1287                expect(SEMICOLON);
1288                if (type != SEMICOLON) {
1289                    test = joinPredecessorExpression();
1290                }
1291                expect(SEMICOLON);
1292                if (type != RPAREN) {
1293                    modify = joinPredecessorExpression();
1294                }
1295                break;
1296
1297            case IDENT:
1298                if (env._es6 && "of".equals(getValue())) {
1299                    isForOf = true;
1300                    // fall through
1301                } else {
1302                    expect(SEMICOLON); // fail with expected message
1303                    break;
1304                }
1305            case IN:
1306
1307                flags |= isForOf ? ForNode.IS_FOR_OF : ForNode.IS_FOR_IN;
1308                test = new JoinPredecessorExpression();
1309                if (vars != null) {
1310                    // for (var i in obj)
1311                    if (vars.size() == 1) {
1312                        init = new IdentNode(vars.get(0).getName());
1313                    } else {
1314                        // for (var i, j in obj) is invalid
1315                        throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), vars.get(1).getToken());
1316                    }
1317                } else {
1318                    // for (expr in obj)
1319                    assert init != null : "for..in/of init expression can not be null here";
1320
1321                    // check if initial expression is a valid L-value
1322                    if (!(init instanceof AccessNode ||
1323                          init instanceof IndexNode ||
1324                          init instanceof IdentNode)) {
1325                        throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
1326                    }
1327
1328                    if (init instanceof IdentNode) {
1329                        if (!checkIdentLValue((IdentNode)init)) {
1330                            throw error(AbstractParser.message("not.lvalue.for.in.loop", isForOf ? "of" : "in"), init.getToken());
1331                        }
1332                        verifyStrictIdent((IdentNode)init, isForOf ? "for-of iterator" : "for-in iterator");
1333                    }
1334                }
1335
1336                next();
1337
1338                // For-of only allows AssignmentExpression.
1339                modify = isForOf ? new JoinPredecessorExpression(assignmentExpression(false)) : joinPredecessorExpression();
1340                break;
1341
1342            default:
1343                expect(SEMICOLON);
1344                break;
1345            }
1346
1347            expect(RPAREN);
1348
1349            // Set the for body.
1350            body = getStatement();
1351        } finally {
1352            lc.pop(forNode);
1353
1354            if (vars != null) {
1355                for (final VarNode var : vars) {
1356                    appendStatement(var);
1357                }
1358            }
1359            if (body != null) {
1360                appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
1361            }
1362            if (outer != null) {
1363                restoreBlock(outer);
1364                if (body != null) {
1365                    appendStatement(new BlockStatement(forLine, new Block(
1366                                    outer.getToken(),
1367                                    body.getFinish(),
1368                                    outer.getStatements())));
1369                }
1370            }
1371        }
1372    }
1373
1374    /**
1375     * ...IterationStatement :
1376     *           ...
1377     *           while ( Expression ) Statement
1378     *           ...
1379     *
1380     * See 12.6
1381     *
1382     * Parse while statement.
1383     */
1384    private void whileStatement() {
1385        // Capture WHILE token.
1386        final long whileToken = token;
1387        final int whileLine = line;
1388        // WHILE tested in caller.
1389        next();
1390
1391        final ParserContextLoopNode whileNode = new ParserContextLoopNode();
1392        lc.push(whileNode);
1393
1394        JoinPredecessorExpression test = null;
1395        Block body = null;
1396
1397        try {
1398            expect(LPAREN);
1399            test = joinPredecessorExpression();
1400            expect(RPAREN);
1401            body = getStatement();
1402        } finally {
1403            lc.pop(whileNode);
1404        }
1405
1406        if (body != null) {
1407            appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
1408        }
1409    }
1410
1411    /**
1412     * ...IterationStatement :
1413     *           ...
1414     *           do Statement while( Expression ) ;
1415     *           ...
1416     *
1417     * See 12.6
1418     *
1419     * Parse DO WHILE statement.
1420     */
1421    private void doStatement() {
1422        // Capture DO token.
1423        final long doToken = token;
1424        int doLine = 0;
1425        // DO tested in the caller.
1426        next();
1427
1428        final ParserContextLoopNode doWhileNode = new ParserContextLoopNode();
1429        lc.push(doWhileNode);
1430
1431        Block body = null;
1432        JoinPredecessorExpression test = null;
1433
1434        try {
1435           // Get DO body.
1436            body = getStatement();
1437
1438            expect(WHILE);
1439            expect(LPAREN);
1440            doLine = line;
1441            test = joinPredecessorExpression();
1442            expect(RPAREN);
1443
1444            if (type == SEMICOLON) {
1445                endOfLine();
1446            }
1447        } finally {
1448            lc.pop(doWhileNode);
1449        }
1450
1451        appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
1452    }
1453
1454    /**
1455     * ContinueStatement :
1456     *      continue Identifier? ; // [no LineTerminator here]
1457     *
1458     * See 12.7
1459     *
1460     * Parse CONTINUE statement.
1461     */
1462    private void continueStatement() {
1463        // Capture CONTINUE token.
1464        final int  continueLine  = line;
1465        final long continueToken = token;
1466        // CONTINUE tested in caller.
1467        nextOrEOL();
1468
1469        ParserContextLabelNode labelNode = null;
1470
1471        // SEMICOLON or label.
1472        switch (type) {
1473        case RBRACE:
1474        case SEMICOLON:
1475        case EOL:
1476        case EOF:
1477            break;
1478
1479        default:
1480            final IdentNode ident = getIdent();
1481            labelNode = lc.findLabel(ident.getName());
1482
1483            if (labelNode == null) {
1484                throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1485            }
1486
1487            break;
1488        }
1489
1490        final String labelName = labelNode == null ? null : labelNode.getLabelName();
1491        final ParserContextLoopNode targetNode = lc.getContinueTo(labelName);
1492
1493        if (targetNode == null) {
1494            throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
1495        }
1496
1497        endOfLine();
1498
1499        // Construct and add CONTINUE node.
1500        appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
1501    }
1502
1503    /**
1504     * BreakStatement :
1505     *      break Identifier? ; // [no LineTerminator here]
1506     *
1507     * See 12.8
1508     *
1509     */
1510    private void breakStatement() {
1511        // Capture BREAK token.
1512        final int  breakLine  = line;
1513        final long breakToken = token;
1514        // BREAK tested in caller.
1515        nextOrEOL();
1516
1517        ParserContextLabelNode labelNode = null;
1518
1519        // SEMICOLON or label.
1520        switch (type) {
1521        case RBRACE:
1522        case SEMICOLON:
1523        case EOL:
1524        case EOF:
1525            break;
1526
1527        default:
1528            final IdentNode ident = getIdent();
1529            labelNode = lc.findLabel(ident.getName());
1530
1531            if (labelNode == null) {
1532                throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1533            }
1534
1535            break;
1536        }
1537
1538        //either an explicit label - then get its node or just a "break" - get first breakable
1539        //targetNode is what we are breaking out from.
1540        final String labelName = labelNode == null ? null : labelNode.getLabelName();
1541        final ParserContextBreakableNode targetNode = lc.getBreakable(labelName);
1542        if (targetNode == null) {
1543            throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
1544        }
1545
1546        endOfLine();
1547
1548        // Construct and add BREAK node.
1549        appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
1550    }
1551
1552    /**
1553     * ReturnStatement :
1554     *      return Expression? ; // [no LineTerminator here]
1555     *
1556     * See 12.9
1557     *
1558     * Parse RETURN statement.
1559     */
1560    private void returnStatement() {
1561        // check for return outside function
1562        if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT) {
1563            throw error(AbstractParser.message("invalid.return"));
1564        }
1565
1566        // Capture RETURN token.
1567        final int  returnLine  = line;
1568        final long returnToken = token;
1569        // RETURN tested in caller.
1570        nextOrEOL();
1571
1572        Expression expression = null;
1573
1574        // SEMICOLON or expression.
1575        switch (type) {
1576        case RBRACE:
1577        case SEMICOLON:
1578        case EOL:
1579        case EOF:
1580            break;
1581
1582        default:
1583            expression = expression();
1584            break;
1585        }
1586
1587        endOfLine();
1588
1589        // Construct and add RETURN node.
1590        appendStatement(new ReturnNode(returnLine, returnToken, finish, expression));
1591    }
1592
1593    /**
1594     * YieldStatement :
1595     *      yield Expression? ; // [no LineTerminator here]
1596     *
1597     * JavaScript 1.8
1598     *
1599     * Parse YIELD statement.
1600     */
1601    private void yieldStatement() {
1602        // Capture YIELD token.
1603        final int  yieldLine  = line;
1604        final long yieldToken = token;
1605        // YIELD tested in caller.
1606        nextOrEOL();
1607
1608        Expression expression = null;
1609
1610        // SEMICOLON or expression.
1611        switch (type) {
1612        case RBRACE:
1613        case SEMICOLON:
1614        case EOL:
1615        case EOF:
1616            break;
1617
1618        default:
1619            expression = expression();
1620            break;
1621        }
1622
1623        endOfLine();
1624
1625        // Construct and add YIELD node.
1626        appendStatement(new ReturnNode(yieldLine, yieldToken, finish, expression));
1627    }
1628
1629    /**
1630     * WithStatement :
1631     *      with ( Expression ) Statement
1632     *
1633     * See 12.10
1634     *
1635     * Parse WITH statement.
1636     */
1637    private void withStatement() {
1638        // Capture WITH token.
1639        final int  withLine  = line;
1640        final long withToken = token;
1641        // WITH tested in caller.
1642        next();
1643
1644        // ECMA 12.10.1 strict mode restrictions
1645        if (isStrictMode) {
1646            throw error(AbstractParser.message("strict.no.with"), withToken);
1647        }
1648
1649        expect(LPAREN);
1650        final Expression expression = expression();
1651        expect(RPAREN);
1652        final Block body = getStatement();
1653
1654        appendStatement(new WithNode(withLine, withToken, finish, expression, body));
1655    }
1656
1657    /**
1658     * SwitchStatement :
1659     *      switch ( Expression ) CaseBlock
1660     *
1661     * CaseBlock :
1662     *      { CaseClauses? }
1663     *      { CaseClauses? DefaultClause CaseClauses }
1664     *
1665     * CaseClauses :
1666     *      CaseClause
1667     *      CaseClauses CaseClause
1668     *
1669     * CaseClause :
1670     *      case Expression : StatementList?
1671     *
1672     * DefaultClause :
1673     *      default : StatementList?
1674     *
1675     * See 12.11
1676     *
1677     * Parse SWITCH statement.
1678     */
1679    private void switchStatement() {
1680        final int  switchLine  = line;
1681        final long switchToken = token;
1682        // SWITCH tested in caller.
1683        next();
1684
1685        // Create and add switch statement.
1686        final ParserContextSwitchNode switchNode= new ParserContextSwitchNode();
1687        lc.push(switchNode);
1688
1689        CaseNode defaultCase = null;
1690        // Prepare to accumulate cases.
1691        final List<CaseNode> cases = new ArrayList<>();
1692
1693        Expression expression = null;
1694
1695        try {
1696            expect(LPAREN);
1697            expression = expression();
1698            expect(RPAREN);
1699
1700            expect(LBRACE);
1701
1702
1703            while (type != RBRACE) {
1704                // Prepare for next case.
1705                Expression caseExpression = null;
1706                final long caseToken = token;
1707
1708                switch (type) {
1709                case CASE:
1710                    next();
1711                    caseExpression = expression();
1712                    break;
1713
1714                case DEFAULT:
1715                    if (defaultCase != null) {
1716                        throw error(AbstractParser.message("duplicate.default.in.switch"));
1717                    }
1718                    next();
1719                    break;
1720
1721                default:
1722                    // Force an error.
1723                    expect(CASE);
1724                    break;
1725                }
1726
1727                expect(COLON);
1728
1729                // Get CASE body.
1730                final Block statements = getBlock(false);
1731                final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
1732
1733                if (caseExpression == null) {
1734                    defaultCase = caseNode;
1735                }
1736
1737                cases.add(caseNode);
1738            }
1739
1740            next();
1741        } finally {
1742            lc.pop(switchNode);
1743        }
1744
1745        appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase));
1746    }
1747
1748    /**
1749     * LabelledStatement :
1750     *      Identifier : Statement
1751     *
1752     * See 12.12
1753     *
1754     * Parse label statement.
1755     */
1756    private void labelStatement() {
1757        // Capture label token.
1758        final long labelToken = token;
1759        // Get label ident.
1760        final IdentNode ident = getIdent();
1761
1762        expect(COLON);
1763
1764        if (lc.findLabel(ident.getName()) != null) {
1765            throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
1766        }
1767
1768        final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName());
1769        Block body = null;
1770        try {
1771            lc.push(labelNode);
1772            body = getStatement();
1773        } finally {
1774            assert lc.peek() instanceof ParserContextLabelNode;
1775            lc.pop(labelNode);
1776        }
1777
1778        appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
1779    }
1780
1781    /**
1782     * ThrowStatement :
1783     *      throw Expression ; // [no LineTerminator here]
1784     *
1785     * See 12.13
1786     *
1787     * Parse throw statement.
1788     */
1789    private void throwStatement() {
1790        // Capture THROW token.
1791        final int  throwLine  = line;
1792        final long throwToken = token;
1793        // THROW tested in caller.
1794        nextOrEOL();
1795
1796        Expression expression = null;
1797
1798        // SEMICOLON or expression.
1799        switch (type) {
1800        case RBRACE:
1801        case SEMICOLON:
1802        case EOL:
1803            break;
1804
1805        default:
1806            expression = expression();
1807            break;
1808        }
1809
1810        if (expression == null) {
1811            throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
1812        }
1813
1814        endOfLine();
1815
1816        appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
1817    }
1818
1819    /**
1820     * TryStatement :
1821     *      try Block Catch
1822     *      try Block Finally
1823     *      try Block Catch Finally
1824     *
1825     * Catch :
1826     *      catch( Identifier if Expression ) Block
1827     *      catch( Identifier ) Block
1828     *
1829     * Finally :
1830     *      finally Block
1831     *
1832     * See 12.14
1833     *
1834     * Parse TRY statement.
1835     */
1836    private void tryStatement() {
1837        // Capture TRY token.
1838        final int  tryLine  = line;
1839        final long tryToken = token;
1840        // TRY tested in caller.
1841        next();
1842
1843        // Container block needed to act as target for labeled break statements
1844        final int startLine = line;
1845        final ParserContextBlockNode outer = newBlock();
1846        // Create try.
1847
1848        try {
1849            final Block       tryBody     = getBlock(true);
1850            final List<Block> catchBlocks = new ArrayList<>();
1851
1852            while (type == CATCH) {
1853                final int  catchLine  = line;
1854                final long catchToken = token;
1855                next();
1856                expect(LPAREN);
1857                final IdentNode exception = getIdent();
1858
1859                // ECMA 12.4.1 strict mode restrictions
1860                verifyStrictIdent(exception, "catch argument");
1861
1862                // Nashorn extension: catch clause can have optional
1863                // condition. So, a single try can have more than one
1864                // catch clause each with it's own condition.
1865                final Expression ifExpression;
1866                if (!env._no_syntax_extensions && type == IF) {
1867                    next();
1868                    // Get the exception condition.
1869                    ifExpression = expression();
1870                } else {
1871                    ifExpression = null;
1872                }
1873
1874                expect(RPAREN);
1875
1876                final ParserContextBlockNode catchBlock = newBlock();
1877                try {
1878                    // Get CATCH body.
1879                    final Block catchBody = getBlock(true);
1880                    final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
1881                    appendStatement(catchNode);
1882                } finally {
1883                    restoreBlock(catchBlock);
1884                    catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements()));
1885                }
1886
1887                // If unconditional catch then should to be the end.
1888                if (ifExpression == null) {
1889                    break;
1890                }
1891            }
1892
1893            // Prepare to capture finally statement.
1894            Block finallyStatements = null;
1895
1896            if (type == FINALLY) {
1897                next();
1898                finallyStatements = getBlock(true);
1899            }
1900
1901            // Need at least one catch or a finally.
1902            if (catchBlocks.isEmpty() && finallyStatements == null) {
1903                throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
1904            }
1905
1906            final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
1907            // Add try.
1908            assert lc.peek() == outer;
1909            appendStatement(tryNode);
1910        } finally {
1911            restoreBlock(outer);
1912        }
1913
1914        appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements())));
1915    }
1916
1917    /**
1918     * DebuggerStatement :
1919     *      debugger ;
1920     *
1921     * See 12.15
1922     *
1923     * Parse debugger statement.
1924     */
1925    private void  debuggerStatement() {
1926        // Capture DEBUGGER token.
1927        final int  debuggerLine  = line;
1928        final long debuggerToken = token;
1929        // DEBUGGER tested in caller.
1930        next();
1931        endOfLine();
1932        appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish));
1933    }
1934
1935    /**
1936     * PrimaryExpression :
1937     *      this
1938     *      Identifier
1939     *      Literal
1940     *      ArrayLiteral
1941     *      ObjectLiteral
1942     *      RegularExpressionLiteral
1943     *      TemplateLiteral
1944     *      ( Expression )
1945     *
1946     * Parse primary expression.
1947     * @return Expression node.
1948     */
1949    @SuppressWarnings("fallthrough")
1950    private Expression primaryExpression() {
1951        // Capture first token.
1952        final int  primaryLine  = line;
1953        final long primaryToken = token;
1954
1955        switch (type) {
1956        case THIS:
1957            final String name = type.getName();
1958            next();
1959            lc.getCurrentFunction().setFlag(FunctionNode.USES_THIS);
1960            return new IdentNode(primaryToken, finish, name);
1961        case IDENT:
1962            final IdentNode ident = getIdent();
1963            if (ident == null) {
1964                break;
1965            }
1966            detectSpecialProperty(ident);
1967            return ident;
1968        case OCTAL_LEGACY:
1969            if (isStrictMode) {
1970               throw error(AbstractParser.message("strict.no.octal"), token);
1971            }
1972        case STRING:
1973        case ESCSTRING:
1974        case DECIMAL:
1975        case HEXADECIMAL:
1976        case OCTAL:
1977        case BINARY_NUMBER:
1978        case FLOATING:
1979        case REGEX:
1980        case XML:
1981            return getLiteral();
1982        case EXECSTRING:
1983            return execString(primaryLine, primaryToken);
1984        case FALSE:
1985            next();
1986            return LiteralNode.newInstance(primaryToken, finish, false);
1987        case TRUE:
1988            next();
1989            return LiteralNode.newInstance(primaryToken, finish, true);
1990        case NULL:
1991            next();
1992            return LiteralNode.newInstance(primaryToken, finish);
1993        case LBRACKET:
1994            return arrayLiteral();
1995        case LBRACE:
1996            return objectLiteral();
1997        case LPAREN:
1998            next();
1999
2000            final Expression expression = expression();
2001
2002            expect(RPAREN);
2003
2004            return expression;
2005        case TEMPLATE:
2006        case TEMPLATE_HEAD:
2007            return templateLiteral();
2008
2009        default:
2010            // In this context some operator tokens mark the start of a literal.
2011            if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
2012                next();
2013                return getLiteral();
2014            }
2015            if (isNonStrictModeIdent()) {
2016                return getIdent();
2017            }
2018            break;
2019        }
2020
2021        return null;
2022    }
2023
2024    /**
2025     * Convert execString to a call to $EXEC.
2026     *
2027     * @param primaryToken Original string token.
2028     * @return callNode to $EXEC.
2029     */
2030    CallNode execString(final int primaryLine, final long primaryToken) {
2031        // Synthesize an ident to call $EXEC.
2032        final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
2033        // Skip over EXECSTRING.
2034        next();
2035        // Set up argument list for call.
2036        // Skip beginning of edit string expression.
2037        expect(LBRACE);
2038        // Add the following expression to arguments.
2039        final List<Expression> arguments = Collections.singletonList(expression());
2040        // Skip ending of edit string expression.
2041        expect(RBRACE);
2042
2043        return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
2044    }
2045
2046    /**
2047     * ArrayLiteral :
2048     *      [ Elision? ]
2049     *      [ ElementList ]
2050     *      [ ElementList , Elision? ]
2051     *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
2052     *
2053     * ElementList : Elision? AssignmentExpression
2054     *      ElementList , Elision? AssignmentExpression
2055     *
2056     * Elision :
2057     *      ,
2058     *      Elision ,
2059     *
2060     * See 12.1.4
2061     * JavaScript 1.8
2062     *
2063     * Parse array literal.
2064     * @return Expression node.
2065     */
2066    private LiteralNode<Expression[]> arrayLiteral() {
2067        // Capture LBRACKET token.
2068        final long arrayToken = token;
2069        // LBRACKET tested in caller.
2070        next();
2071
2072        // Prepare to accumulate elements.
2073        final List<Expression> elements = new ArrayList<>();
2074        // Track elisions.
2075        boolean elision = true;
2076loop:
2077        while (true) {
2078            switch (type) {
2079            case RBRACKET:
2080                next();
2081
2082                break loop;
2083
2084            case COMMARIGHT:
2085                next();
2086
2087                // If no prior expression
2088                if (elision) {
2089                    elements.add(null);
2090                }
2091
2092                elision = true;
2093
2094                break;
2095
2096            default:
2097                if (!elision) {
2098                    throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2099                }
2100                // Add expression element.
2101                final Expression expression = assignmentExpression(false);
2102
2103                if (expression != null) {
2104                    elements.add(expression);
2105                } else {
2106                    expect(RBRACKET);
2107                }
2108
2109                elision = false;
2110                break;
2111            }
2112        }
2113
2114        return LiteralNode.newInstance(arrayToken, finish, elements);
2115    }
2116
2117    /**
2118     * ObjectLiteral :
2119     *      { }
2120     *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2121     *
2122     * PropertyNameAndValueList :
2123     *      PropertyAssignment
2124     *      PropertyNameAndValueList , PropertyAssignment
2125     *
2126     * See 11.1.5
2127     *
2128     * Parse an object literal.
2129     * @return Expression node.
2130     */
2131    private ObjectNode objectLiteral() {
2132        // Capture LBRACE token.
2133        final long objectToken = token;
2134        // LBRACE tested in caller.
2135        next();
2136
2137        // Object context.
2138        // Prepare to accumulate elements.
2139        final List<PropertyNode> elements = new ArrayList<>();
2140        final Map<String, Integer> map = new HashMap<>();
2141
2142        // Create a block for the object literal.
2143        boolean commaSeen = true;
2144loop:
2145        while (true) {
2146            switch (type) {
2147                case RBRACE:
2148                    next();
2149                    break loop;
2150
2151                case COMMARIGHT:
2152                    if (commaSeen) {
2153                        throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2154                    }
2155                    next();
2156                    commaSeen = true;
2157                    break;
2158
2159                default:
2160                    if (!commaSeen) {
2161                        throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2162                    }
2163
2164                    commaSeen = false;
2165                    // Get and add the next property.
2166                    final PropertyNode property = propertyAssignment();
2167                    final String key = property.getKeyName();
2168                    final Integer existing = map.get(key);
2169
2170                    if (existing == null) {
2171                        map.put(key, elements.size());
2172                        elements.add(property);
2173                        break;
2174                    }
2175
2176                    final PropertyNode existingProperty = elements.get(existing);
2177
2178                    // ECMA section 11.1.5 Object Initialiser
2179                    // point # 4 on property assignment production
2180                    final Expression   value  = property.getValue();
2181                    final FunctionNode getter = property.getGetter();
2182                    final FunctionNode setter = property.getSetter();
2183
2184                    final Expression   prevValue  = existingProperty.getValue();
2185                    final FunctionNode prevGetter = existingProperty.getGetter();
2186                    final FunctionNode prevSetter = existingProperty.getSetter();
2187
2188                    // ECMA 11.1.5 strict mode restrictions
2189                    if (isStrictMode && value != null && prevValue != null) {
2190                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2191                    }
2192
2193                    final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
2194                    final boolean isAccessor     = getter != null     || setter != null;
2195
2196                    // data property redefined as accessor property
2197                    if (prevValue != null && isAccessor) {
2198                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2199                    }
2200
2201                    // accessor property redefined as data
2202                    if (isPrevAccessor && value != null) {
2203                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2204                    }
2205
2206                    if (isAccessor && isPrevAccessor) {
2207                        if (getter != null && prevGetter != null ||
2208                                setter != null && prevSetter != null) {
2209                            throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2210                        }
2211                    }
2212
2213                    if (value != null) {
2214                        elements.add(property);
2215                    } else if (getter != null) {
2216                        elements.set(existing, existingProperty.setGetter(getter));
2217                    } else if (setter != null) {
2218                        elements.set(existing, existingProperty.setSetter(setter));
2219                    }
2220                    break;
2221            }
2222        }
2223
2224        return new ObjectNode(objectToken, finish, elements);
2225    }
2226
2227    /**
2228     * PropertyName :
2229     *      IdentifierName
2230     *      StringLiteral
2231     *      NumericLiteral
2232     *
2233     * See 11.1.5
2234     *
2235     * @return PropertyName node
2236     */
2237    @SuppressWarnings("fallthrough")
2238    private PropertyKey propertyName() {
2239        switch (type) {
2240        case IDENT:
2241            return getIdent().setIsPropertyName();
2242        case OCTAL_LEGACY:
2243            if (isStrictMode) {
2244                throw error(AbstractParser.message("strict.no.octal"), token);
2245            }
2246        case STRING:
2247        case ESCSTRING:
2248        case DECIMAL:
2249        case HEXADECIMAL:
2250        case OCTAL:
2251        case BINARY_NUMBER:
2252        case FLOATING:
2253            return getLiteral();
2254        default:
2255            return getIdentifierName().setIsPropertyName();
2256        }
2257    }
2258
2259    /**
2260     * PropertyAssignment :
2261     *      PropertyName : AssignmentExpression
2262     *      get PropertyName ( ) { FunctionBody }
2263     *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
2264     *
2265     * PropertySetParameterList :
2266     *      Identifier
2267     *
2268     * PropertyName :
2269     *      IdentifierName
2270     *      StringLiteral
2271     *      NumericLiteral
2272     *
2273     * See 11.1.5
2274     *
2275     * Parse an object literal property.
2276     * @return Property or reference node.
2277     */
2278    private PropertyNode propertyAssignment() {
2279        // Capture firstToken.
2280        final long propertyToken = token;
2281        final int  functionLine  = line;
2282
2283        PropertyKey propertyName;
2284
2285        if (type == IDENT) {
2286            // Get IDENT.
2287            final String ident = (String)expectValue(IDENT);
2288
2289            if (type != COLON) {
2290                final long getSetToken = propertyToken;
2291
2292                switch (ident) {
2293                case "get":
2294                    final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
2295                    return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null);
2296
2297                case "set":
2298                    final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
2299                    return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode);
2300                default:
2301                    break;
2302                }
2303            }
2304
2305            propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
2306        } else {
2307            propertyName = propertyName();
2308        }
2309
2310        expect(COLON);
2311
2312        defaultNames.push(propertyName);
2313        try {
2314            return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
2315        } finally {
2316            defaultNames.pop();
2317        }
2318    }
2319
2320    private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
2321        final PropertyKey getIdent = propertyName();
2322        final String getterName = getIdent.getPropertyName();
2323        final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
2324        expect(LPAREN);
2325        expect(RPAREN);
2326
2327        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
2328        lc.push(functionNode);
2329
2330        Block functionBody;
2331
2332
2333        try {
2334            functionBody = functionBody(functionNode);
2335        } finally {
2336            lc.pop(functionNode);
2337        }
2338
2339        final FunctionNode  function = createFunctionNode(
2340                functionNode,
2341                getSetToken,
2342                getNameNode,
2343                Collections.<IdentNode>emptyList(),
2344                FunctionNode.Kind.GETTER,
2345                functionLine,
2346                functionBody);
2347
2348        return new PropertyFunction(getIdent, function);
2349    }
2350
2351    private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
2352        final PropertyKey setIdent = propertyName();
2353        final String setterName = setIdent.getPropertyName();
2354        final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
2355        expect(LPAREN);
2356        // be sloppy and allow missing setter parameter even though
2357        // spec does not permit it!
2358        final IdentNode argIdent;
2359        if (type == IDENT || isNonStrictModeIdent()) {
2360            argIdent = getIdent();
2361            verifyStrictIdent(argIdent, "setter argument");
2362        } else {
2363            argIdent = null;
2364        }
2365        expect(RPAREN);
2366        final List<IdentNode> parameters = new ArrayList<>();
2367        if (argIdent != null) {
2368            parameters.add(argIdent);
2369        }
2370
2371
2372        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
2373        lc.push(functionNode);
2374
2375        Block functionBody;
2376        try {
2377            functionBody = functionBody(functionNode);
2378        } finally {
2379            lc.pop(functionNode);
2380        }
2381
2382
2383        final FunctionNode  function = createFunctionNode(
2384                functionNode,
2385                getSetToken,
2386                setNameNode,
2387                parameters,
2388                FunctionNode.Kind.SETTER,
2389                functionLine,
2390                functionBody);
2391
2392        return new PropertyFunction(setIdent, function);
2393    }
2394
2395    private static class PropertyFunction {
2396        final PropertyKey ident;
2397        final FunctionNode functionNode;
2398
2399        PropertyFunction(final PropertyKey ident, final FunctionNode function) {
2400            this.ident = ident;
2401            this.functionNode = function;
2402        }
2403    }
2404
2405    /**
2406     * Parse left hand side expression.
2407     *
2408     * LeftHandSideExpression :
2409     *      NewExpression
2410     *      CallExpression
2411     *
2412     * CallExpression :
2413     *      MemberExpression Arguments
2414     *      CallExpression Arguments
2415     *      CallExpression [ Expression ]
2416     *      CallExpression . IdentifierName
2417     *      CallExpression TemplateLiteral
2418     *
2419     * @return Expression node.
2420     */
2421    private Expression leftHandSideExpression() {
2422        int  callLine  = line;
2423        long callToken = token;
2424
2425        Expression lhs = memberExpression();
2426
2427        if (type == LPAREN) {
2428            final List<Expression> arguments = optimizeList(argumentList());
2429
2430            // Catch special functions.
2431            if (lhs instanceof IdentNode) {
2432                detectSpecialFunction((IdentNode)lhs);
2433            }
2434
2435            lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2436        }
2437
2438loop:
2439        while (true) {
2440            // Capture token.
2441            callLine  = line;
2442            callToken = token;
2443
2444            switch (type) {
2445            case LPAREN: {
2446                // Get NEW or FUNCTION arguments.
2447                final List<Expression> arguments = optimizeList(argumentList());
2448
2449                // Create call node.
2450                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2451
2452                break;
2453            }
2454            case LBRACKET: {
2455                next();
2456
2457                // Get array index.
2458                final Expression rhs = expression();
2459
2460                expect(RBRACKET);
2461
2462                // Create indexing node.
2463                lhs = new IndexNode(callToken, finish, lhs, rhs);
2464
2465                break;
2466            }
2467            case PERIOD: {
2468                next();
2469
2470                final IdentNode property = getIdentifierName();
2471
2472                // Create property access node.
2473                lhs = new AccessNode(callToken, finish, lhs, property.getName());
2474
2475                break;
2476            }
2477            case TEMPLATE:
2478            case TEMPLATE_HEAD: {
2479                // tagged template literal
2480                final List<Expression> arguments = templateLiteralArgumentList();
2481
2482                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2483
2484                break;
2485            }
2486            default:
2487                break loop;
2488            }
2489        }
2490
2491        return lhs;
2492    }
2493
2494    /**
2495     * NewExpression :
2496     *      MemberExpression
2497     *      new NewExpression
2498     *
2499     * See 11.2
2500     *
2501     * Parse new expression.
2502     * @return Expression node.
2503     */
2504    private Expression newExpression() {
2505        final long newToken = token;
2506        // NEW is tested in caller.
2507        next();
2508
2509        // Get function base.
2510        final int  callLine    = line;
2511        final Expression constructor = memberExpression();
2512        if (constructor == null) {
2513            return null;
2514        }
2515        // Get arguments.
2516        ArrayList<Expression> arguments;
2517
2518        // Allow for missing arguments.
2519        if (type == LPAREN) {
2520            arguments = argumentList();
2521        } else {
2522            arguments = new ArrayList<>();
2523        }
2524
2525        // Nashorn extension: This is to support the following interface implementation
2526        // syntax:
2527        //
2528        //     var r = new java.lang.Runnable() {
2529        //         run: function() { println("run"); }
2530        //     };
2531        //
2532        // The object literal following the "new Constructor()" expression
2533        // is passed as an additional (last) argument to the constructor.
2534        if (!env._no_syntax_extensions && type == LBRACE) {
2535            arguments.add(objectLiteral());
2536        }
2537
2538        final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
2539
2540        return new UnaryNode(newToken, callNode);
2541    }
2542
2543    /**
2544     * Parse member expression.
2545     *
2546     * MemberExpression :
2547     *      PrimaryExpression
2548     *      FunctionExpression
2549     *      MemberExpression [ Expression ]
2550     *      MemberExpression . IdentifierName
2551     *      MemberExpression TemplateLiteral
2552     *      new MemberExpression Arguments
2553     *
2554     * @return Expression node.
2555     */
2556    private Expression memberExpression() {
2557        // Prepare to build operation.
2558        Expression lhs;
2559
2560        switch (type) {
2561        case NEW:
2562            // Get new expression.
2563            lhs = newExpression();
2564            break;
2565
2566        case FUNCTION:
2567            // Get function expression.
2568            lhs = functionExpression(false, false);
2569            break;
2570
2571        default:
2572            // Get primary expression.
2573            lhs = primaryExpression();
2574            break;
2575        }
2576
2577loop:
2578        while (true) {
2579            // Capture token.
2580            final long callToken = token;
2581
2582            switch (type) {
2583            case LBRACKET: {
2584                next();
2585
2586                // Get array index.
2587                final Expression index = expression();
2588
2589                expect(RBRACKET);
2590
2591                // Create indexing node.
2592                lhs = new IndexNode(callToken, finish, lhs, index);
2593
2594                break;
2595            }
2596            case PERIOD: {
2597                if (lhs == null) {
2598                    throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2599                }
2600
2601                next();
2602
2603                final IdentNode property = getIdentifierName();
2604
2605                // Create property access node.
2606                lhs = new AccessNode(callToken, finish, lhs, property.getName());
2607
2608                break;
2609            }
2610            case TEMPLATE:
2611            case TEMPLATE_HEAD: {
2612                // tagged template literal
2613                final int callLine = line;
2614                final List<Expression> arguments = templateLiteralArgumentList();
2615
2616                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2617
2618                break;
2619            }
2620            default:
2621                break loop;
2622            }
2623        }
2624
2625        return lhs;
2626    }
2627
2628    /**
2629     * Arguments :
2630     *      ( )
2631     *      ( ArgumentList )
2632     *
2633     * ArgumentList :
2634     *      AssignmentExpression
2635     *      ArgumentList , AssignmentExpression
2636     *
2637     * See 11.2
2638     *
2639     * Parse function call arguments.
2640     * @return Argument list.
2641     */
2642    private ArrayList<Expression> argumentList() {
2643        // Prepare to accumulate list of arguments.
2644        final ArrayList<Expression> nodeList = new ArrayList<>();
2645        // LPAREN tested in caller.
2646        next();
2647
2648        // Track commas.
2649        boolean first = true;
2650
2651        while (type != RPAREN) {
2652            // Comma prior to every argument except the first.
2653            if (!first) {
2654                expect(COMMARIGHT);
2655            } else {
2656                first = false;
2657            }
2658
2659            // Get argument expression.
2660            nodeList.add(assignmentExpression(false));
2661        }
2662
2663        expect(RPAREN);
2664        return nodeList;
2665    }
2666
2667    private static <T> List<T> optimizeList(final ArrayList<T> list) {
2668        switch(list.size()) {
2669            case 0: {
2670                return Collections.emptyList();
2671            }
2672            case 1: {
2673                return Collections.singletonList(list.get(0));
2674            }
2675            default: {
2676                list.trimToSize();
2677                return list;
2678            }
2679        }
2680    }
2681
2682    /**
2683     * FunctionDeclaration :
2684     *      function Identifier ( FormalParameterList? ) { FunctionBody }
2685     *
2686     * FunctionExpression :
2687     *      function Identifier? ( FormalParameterList? ) { FunctionBody }
2688     *
2689     * See 13
2690     *
2691     * Parse function declaration.
2692     * @param isStatement True if for is a statement.
2693     *
2694     * @return Expression node.
2695     */
2696    private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
2697        final long functionToken = token;
2698        final int  functionLine  = line;
2699        // FUNCTION is tested in caller.
2700        next();
2701
2702        IdentNode name = null;
2703
2704        if (type == IDENT || isNonStrictModeIdent()) {
2705            name = getIdent();
2706            verifyStrictIdent(name, "function name");
2707        } else if (isStatement) {
2708            // Nashorn extension: anonymous function statements.
2709            // Do not allow anonymous function statement if extensions
2710            // are now allowed. But if we are reparsing then anon function
2711            // statement is possible - because it was used as function
2712            // expression in surrounding code.
2713            if (env._no_syntax_extensions && reparsedFunction == null) {
2714                expect(IDENT);
2715            }
2716        }
2717
2718        // name is null, generate anonymous name
2719        boolean isAnonymous = false;
2720        if (name == null) {
2721            final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
2722            name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
2723            isAnonymous = true;
2724        }
2725
2726        expect(LPAREN);
2727        final List<IdentNode> parameters = formalParameterList();
2728        expect(RPAREN);
2729
2730        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters);
2731        lc.push(functionNode);
2732        Block functionBody = null;
2733        // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
2734        // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
2735        hideDefaultName();
2736        try{
2737            functionBody = functionBody(functionNode);
2738        } finally {
2739            defaultNames.pop();
2740            lc.pop(functionNode);
2741        }
2742
2743        if (isStatement) {
2744            if (topLevel || useBlockScope()) {
2745                functionNode.setFlag(FunctionNode.IS_DECLARED);
2746            } else if (isStrictMode) {
2747                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
2748            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
2749                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
2750            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
2751                warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
2752            }
2753            if (isArguments(name)) {
2754               lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
2755            }
2756        }
2757
2758        if (isAnonymous) {
2759            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
2760        }
2761
2762        final int arity = parameters.size();
2763
2764        final boolean strict = functionNode.isStrict();
2765        if (arity > 1) {
2766            final HashSet<String> parametersSet = new HashSet<>(arity);
2767
2768            for (int i = arity - 1; i >= 0; i--) {
2769                final IdentNode parameter = parameters.get(i);
2770                String parameterName = parameter.getName();
2771
2772                if (isArguments(parameterName)) {
2773                    functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2774                }
2775
2776                if (parametersSet.contains(parameterName)) {
2777                    // redefinition of parameter name
2778                    if (strict) {
2779                        throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2780                    }
2781                    // rename in non-strict mode
2782                    parameterName = functionNode.uniqueName(parameterName);
2783                    final long parameterToken = parameter.getToken();
2784                    parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2785                }
2786
2787                parametersSet.add(parameterName);
2788            }
2789        } else if (arity == 1) {
2790            if (isArguments(parameters.get(0))) {
2791                functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2792            }
2793        }
2794
2795        final FunctionNode function = createFunctionNode(
2796                functionNode,
2797                functionToken,
2798                name,
2799                parameters,
2800                FunctionNode.Kind.NORMAL,
2801                functionLine,
2802                functionBody);
2803
2804        if (isStatement) {
2805            if (isAnonymous) {
2806                appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function));
2807                return function;
2808            }
2809
2810            // mark ES6 block functions as lexically scoped
2811            final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
2812            final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
2813            if (topLevel) {
2814                functionDeclarations.add(varNode);
2815            } else if (useBlockScope()) {
2816                prependStatement(varNode); // Hoist to beginning of current block
2817            } else {
2818                appendStatement(varNode);
2819            }
2820        }
2821
2822        return function;
2823    }
2824
2825    private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
2826        final String defaultFunctionName = getDefaultFunctionName();
2827        if (isValidIdentifier(defaultFunctionName)) {
2828            if (isStatement) {
2829                // The name will be used as the LHS of a symbol assignment. We add the anonymous function
2830                // prefix to ensure that it can't clash with another variable.
2831                return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
2832            }
2833            return defaultFunctionName;
2834        }
2835        return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2836    }
2837
2838    private static boolean isValidIdentifier(final String name) {
2839        if(name == null || name.isEmpty()) {
2840            return false;
2841        }
2842        if(!Character.isJavaIdentifierStart(name.charAt(0))) {
2843            return false;
2844        }
2845        for(int i = 1; i < name.length(); ++i) {
2846            if(!Character.isJavaIdentifierPart(name.charAt(i))) {
2847                return false;
2848            }
2849        }
2850        return true;
2851    }
2852
2853    private String getDefaultFunctionName() {
2854        if(!defaultNames.isEmpty()) {
2855            final Object nameExpr = defaultNames.peek();
2856            if(nameExpr instanceof PropertyKey) {
2857                markDefaultNameUsed();
2858                return ((PropertyKey)nameExpr).getPropertyName();
2859            } else if(nameExpr instanceof AccessNode) {
2860                markDefaultNameUsed();
2861                return ((AccessNode)nameExpr).getProperty();
2862            }
2863        }
2864        return null;
2865    }
2866
2867    private void markDefaultNameUsed() {
2868        defaultNames.pop();
2869        hideDefaultName();
2870    }
2871
2872    private void hideDefaultName() {
2873        // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
2874        // from. Can't be null
2875        defaultNames.push("");
2876    }
2877
2878    /**
2879     * FormalParameterList :
2880     *      Identifier
2881     *      FormalParameterList , Identifier
2882     *
2883     * See 13
2884     *
2885     * Parse function parameter list.
2886     * @return List of parameter nodes.
2887     */
2888    private List<IdentNode> formalParameterList() {
2889        return formalParameterList(RPAREN);
2890    }
2891
2892    /**
2893     * Same as the other method of the same name - except that the end
2894     * token type expected is passed as argument to this method.
2895     *
2896     * FormalParameterList :
2897     *      Identifier
2898     *      FormalParameterList , Identifier
2899     *
2900     * See 13
2901     *
2902     * Parse function parameter list.
2903     * @return List of parameter nodes.
2904     */
2905    private List<IdentNode> formalParameterList(final TokenType endType) {
2906        // Prepare to gather parameters.
2907        final ArrayList<IdentNode> parameters = new ArrayList<>();
2908        // Track commas.
2909        boolean first = true;
2910
2911        while (type != endType) {
2912            // Comma prior to every argument except the first.
2913            if (!first) {
2914                expect(COMMARIGHT);
2915            } else {
2916                first = false;
2917            }
2918
2919            // Get and add parameter.
2920            final IdentNode ident = getIdent();
2921
2922            // ECMA 13.1 strict mode restrictions
2923            verifyStrictIdent(ident, "function parameter");
2924
2925            parameters.add(ident);
2926        }
2927
2928        parameters.trimToSize();
2929        return parameters;
2930    }
2931
2932    /**
2933     * FunctionBody :
2934     *      SourceElements?
2935     *
2936     * See 13
2937     *
2938     * Parse function body.
2939     * @return function node (body.)
2940     */
2941    private Block functionBody(final ParserContextFunctionNode functionNode) {
2942        long lastToken = 0L;
2943        ParserContextBlockNode body = null;
2944        final long bodyToken = token;
2945        Block functionBody;
2946        int bodyFinish = 0;
2947
2948        final boolean parseBody;
2949        Object endParserState = null;
2950        try {
2951            // Create a new function block.
2952            body = newBlock();
2953            if (env._debug_scopes) {
2954                // debug scope options forces everything to be in scope
2955                markEval(lc);
2956            }
2957            assert functionNode != null;
2958            final int functionId = functionNode.getId();
2959            parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
2960            // Nashorn extension: expression closures
2961            if (!env._no_syntax_extensions && type != LBRACE) {
2962                /*
2963                 * Example:
2964                 *
2965                 * function square(x) x * x;
2966                 * print(square(3));
2967                 */
2968
2969                // just expression as function body
2970                final Expression expr = assignmentExpression(true);
2971                lastToken = previousToken;
2972                functionNode.setLastToken(previousToken);
2973                assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
2974                // EOL uses length field to store the line number
2975                final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
2976                // Only create the return node if we aren't skipping nested functions. Note that we aren't
2977                // skipping parsing of these extended functions; they're considered to be small anyway. Also,
2978                // they don't end with a single well known token, so it'd be very hard to get correctly (see
2979                // the note below for reasoning on skipping happening before instead of after RBRACE for
2980                // details).
2981                if (parseBody) {
2982                    final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
2983                    appendStatement(returnNode);
2984                }
2985            } else {
2986                expectDontAdvance(LBRACE);
2987                if (parseBody || !skipFunctionBody(functionNode)) {
2988                    next();
2989                    // Gather the function elements.
2990                    final List<Statement> prevFunctionDecls = functionDeclarations;
2991                    functionDeclarations = new ArrayList<>();
2992                    try {
2993                        sourceElements(false);
2994                        addFunctionDeclarations(functionNode);
2995                    } finally {
2996                        functionDeclarations = prevFunctionDecls;
2997                    }
2998
2999                    lastToken = token;
3000                    if (parseBody) {
3001                        // Since the lexer can read ahead and lexify some number of tokens in advance and have
3002                        // them buffered in the TokenStream, we need to produce a lexer state as it was just
3003                        // before it lexified RBRACE, and not whatever is its current (quite possibly well read
3004                        // ahead) state.
3005                        endParserState = new ParserState(Token.descPosition(token), line, linePosition);
3006
3007                        // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
3008                        // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
3009                        // state after it. The reason is that RBRACE is a well-known token that we can expect and
3010                        // will never involve us getting into a weird lexer state, and as such is a great reparse
3011                        // point. Typical example of a weird lexer state after RBRACE would be:
3012                        //     function this_is_skipped() { ... } "use strict";
3013                        // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
3014                        // of compensating for the possibility of a string literal (or similar) after RBRACE,
3015                        // we'll rather just restart parsing from this well-known, friendly token instead.
3016                    }
3017                }
3018                bodyFinish = finish;
3019                functionNode.setLastToken(token);
3020                expect(RBRACE);
3021            }
3022        } finally {
3023            restoreBlock(body);
3024        }
3025
3026        // NOTE: we can only do alterations to the function node after restoreFunctionNode.
3027
3028        if (parseBody) {
3029            functionNode.setEndParserState(endParserState);
3030        } else if (!body.getStatements().isEmpty()){
3031            // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
3032            // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
3033            // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
3034            // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
3035            // nested bodies early if we were supposed to skip 'em.
3036            body.setStatements(Collections.<Statement>emptyList());
3037        }
3038
3039        if (reparsedFunction != null) {
3040            // We restore the flags stored in the function's ScriptFunctionData that we got when we first
3041            // eagerly parsed the code. We're doing it because some flags would be set based on the
3042            // content of the function, or even content of its nested functions, most of which are normally
3043            // skipped during an on-demand compilation.
3044            final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
3045            if (data != null) {
3046                // Data can be null if when we originally parsed the file, we removed the function declaration
3047                // as it was dead code.
3048                functionNode.setFlag(data.getFunctionFlags());
3049                // This compensates for missing markEval() in case the function contains an inner function
3050                // that contains eval(), that now we didn't discover since we skipped the inner function.
3051                if (functionNode.hasNestedEval()) {
3052                    assert functionNode.hasScopeBlock();
3053                    body.setFlag(Block.NEEDS_SCOPE);
3054                }
3055            }
3056        }
3057        functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements());
3058        return functionBody;
3059    }
3060
3061    private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
3062        if (reparsedFunction == null) {
3063            // Not reparsing, so don't skip any function body.
3064            return false;
3065        }
3066        // Skip to the RBRACE of this function, and continue parsing from there.
3067        final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
3068        if (data == null) {
3069            // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
3070            // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
3071            // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
3072            return false;
3073        }
3074        final ParserState parserState = (ParserState)data.getEndParserState();
3075        assert parserState != null;
3076
3077        if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) {
3078            // RBRACE is already in the token stream, so fast forward to it
3079            for (; k < stream.last(); k++) {
3080                final long nextToken = stream.get(k + 1);
3081                if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) {
3082                    token = stream.get(k);
3083                    type = Token.descType(token);
3084                    next();
3085                    assert type == RBRACE && start == parserState.position;
3086                    return true;
3087                }
3088            }
3089        }
3090
3091        stream.reset();
3092        lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
3093        line = parserState.line;
3094        linePosition = parserState.linePosition;
3095        // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
3096        // the RBRACE.
3097        type = SEMICOLON;
3098        k = -1;
3099        next();
3100
3101        return true;
3102    }
3103
3104    /**
3105     * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
3106     * for resuming parsing after skipping a function body.
3107     */
3108    private static class ParserState implements Serializable {
3109        private final int position;
3110        private final int line;
3111        private final int linePosition;
3112
3113        private static final long serialVersionUID = -2382565130754093694L;
3114
3115        ParserState(final int position, final int line, final int linePosition) {
3116            this.position = position;
3117            this.line = line;
3118            this.linePosition = linePosition;
3119        }
3120
3121        Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
3122            final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
3123            newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
3124            return newLexer;
3125        }
3126    }
3127
3128    private void printAST(final FunctionNode functionNode) {
3129        if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
3130            env.getErr().println(new ASTWriter(functionNode));
3131        }
3132
3133        if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
3134            env.getErr().println(new PrintVisitor(functionNode, true, false));
3135        }
3136    }
3137
3138    private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
3139        VarNode lastDecl = null;
3140        for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
3141            Statement decl = functionDeclarations.get(i);
3142            if (lastDecl == null && decl instanceof VarNode) {
3143                decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
3144                functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
3145            }
3146            prependStatement(decl);
3147        }
3148    }
3149
3150    private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
3151        if (earlyError) {
3152            throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
3153        }
3154        final ArrayList<Expression> args = new ArrayList<>();
3155        args.add(lhs);
3156        if (rhs == null) {
3157            args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
3158        } else {
3159            args.add(rhs);
3160        }
3161        args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
3162        return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
3163    }
3164
3165    /**
3166     * PostfixExpression :
3167     *      LeftHandSideExpression
3168     *      LeftHandSideExpression ++ // [no LineTerminator here]
3169     *      LeftHandSideExpression -- // [no LineTerminator here]
3170     *
3171     * See 11.3
3172     *
3173     * UnaryExpression :
3174     *      PostfixExpression
3175     *      delete UnaryExpression
3176     *      void UnaryExpression
3177     *      typeof UnaryExpression
3178     *      ++ UnaryExpression
3179     *      -- UnaryExpression
3180     *      + UnaryExpression
3181     *      - UnaryExpression
3182     *      ~ UnaryExpression
3183     *      ! UnaryExpression
3184     *
3185     * See 11.4
3186     *
3187     * Parse unary expression.
3188     * @return Expression node.
3189     */
3190    private Expression unaryExpression() {
3191        final int  unaryLine  = line;
3192        final long unaryToken = token;
3193
3194        switch (type) {
3195        case DELETE: {
3196            next();
3197            final Expression expr = unaryExpression();
3198            if (expr instanceof BaseNode || expr instanceof IdentNode) {
3199                return new UnaryNode(unaryToken, expr);
3200            }
3201            appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
3202            return LiteralNode.newInstance(unaryToken, finish, true);
3203        }
3204        case VOID:
3205        case TYPEOF:
3206        case ADD:
3207        case SUB:
3208        case BIT_NOT:
3209        case NOT:
3210            next();
3211            final Expression expr = unaryExpression();
3212            return new UnaryNode(unaryToken, expr);
3213
3214        case INCPREFIX:
3215        case DECPREFIX:
3216            final TokenType opType = type;
3217            next();
3218
3219            final Expression lhs = leftHandSideExpression();
3220            // ++, -- without operand..
3221            if (lhs == null) {
3222                throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3223            }
3224
3225            if (!(lhs instanceof AccessNode ||
3226                  lhs instanceof IndexNode ||
3227                  lhs instanceof IdentNode)) {
3228                return referenceError(lhs, null, env._early_lvalue_error);
3229            }
3230
3231            if (lhs instanceof IdentNode) {
3232                if (!checkIdentLValue((IdentNode)lhs)) {
3233                    return referenceError(lhs, null, false);
3234                }
3235                verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3236            }
3237
3238            return incDecExpression(unaryToken, opType, lhs, false);
3239
3240        default:
3241            break;
3242        }
3243
3244        Expression expression = leftHandSideExpression();
3245
3246        if (last != EOL) {
3247            switch (type) {
3248            case INCPREFIX:
3249            case DECPREFIX:
3250                final TokenType opType = type;
3251                final Expression lhs = expression;
3252                // ++, -- without operand..
3253                if (lhs == null) {
3254                    throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3255                }
3256
3257                if (!(lhs instanceof AccessNode ||
3258                   lhs instanceof IndexNode ||
3259                   lhs instanceof IdentNode)) {
3260                    next();
3261                    return referenceError(lhs, null, env._early_lvalue_error);
3262                }
3263                if (lhs instanceof IdentNode) {
3264                    if (!checkIdentLValue((IdentNode)lhs)) {
3265                        next();
3266                        return referenceError(lhs, null, false);
3267                    }
3268                    verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3269                }
3270                expression = incDecExpression(token, type, expression, true);
3271                next();
3272                break;
3273            default:
3274                break;
3275            }
3276        }
3277
3278        if (expression == null) {
3279            throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3280        }
3281
3282        return expression;
3283    }
3284
3285    /**
3286     * {@code
3287     * MultiplicativeExpression :
3288     *      UnaryExpression
3289     *      MultiplicativeExpression * UnaryExpression
3290     *      MultiplicativeExpression / UnaryExpression
3291     *      MultiplicativeExpression % UnaryExpression
3292     *
3293     * See 11.5
3294     *
3295     * AdditiveExpression :
3296     *      MultiplicativeExpression
3297     *      AdditiveExpression + MultiplicativeExpression
3298     *      AdditiveExpression - MultiplicativeExpression
3299     *
3300     * See 11.6
3301     *
3302     * ShiftExpression :
3303     *      AdditiveExpression
3304     *      ShiftExpression << AdditiveExpression
3305     *      ShiftExpression >> AdditiveExpression
3306     *      ShiftExpression >>> AdditiveExpression
3307     *
3308     * See 11.7
3309     *
3310     * RelationalExpression :
3311     *      ShiftExpression
3312     *      RelationalExpression < ShiftExpression
3313     *      RelationalExpression > ShiftExpression
3314     *      RelationalExpression <= ShiftExpression
3315     *      RelationalExpression >= ShiftExpression
3316     *      RelationalExpression instanceof ShiftExpression
3317     *      RelationalExpression in ShiftExpression // if !noIf
3318     *
3319     * See 11.8
3320     *
3321     *      RelationalExpression
3322     *      EqualityExpression == RelationalExpression
3323     *      EqualityExpression != RelationalExpression
3324     *      EqualityExpression === RelationalExpression
3325     *      EqualityExpression !== RelationalExpression
3326     *
3327     * See 11.9
3328     *
3329     * BitwiseANDExpression :
3330     *      EqualityExpression
3331     *      BitwiseANDExpression & EqualityExpression
3332     *
3333     * BitwiseXORExpression :
3334     *      BitwiseANDExpression
3335     *      BitwiseXORExpression ^ BitwiseANDExpression
3336     *
3337     * BitwiseORExpression :
3338     *      BitwiseXORExpression
3339     *      BitwiseORExpression | BitwiseXORExpression
3340     *
3341     * See 11.10
3342     *
3343     * LogicalANDExpression :
3344     *      BitwiseORExpression
3345     *      LogicalANDExpression && BitwiseORExpression
3346     *
3347     * LogicalORExpression :
3348     *      LogicalANDExpression
3349     *      LogicalORExpression || LogicalANDExpression
3350     *
3351     * See 11.11
3352     *
3353     * ConditionalExpression :
3354     *      LogicalORExpression
3355     *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
3356     *
3357     * See 11.12
3358     *
3359     * AssignmentExpression :
3360     *      ConditionalExpression
3361     *      LeftHandSideExpression AssignmentOperator AssignmentExpression
3362     *
3363     * AssignmentOperator :
3364     *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
3365     *
3366     * See 11.13
3367     *
3368     * Expression :
3369     *      AssignmentExpression
3370     *      Expression , AssignmentExpression
3371     *
3372     * See 11.14
3373     * }
3374     *
3375     * Parse expression.
3376     * @return Expression node.
3377     */
3378    protected Expression expression() {
3379        // This method is protected so that subclass can get details
3380        // at expression start point!
3381
3382        // Include commas in expression parsing.
3383        return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
3384    }
3385
3386    private JoinPredecessorExpression joinPredecessorExpression() {
3387        return new JoinPredecessorExpression(expression());
3388    }
3389
3390    private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
3391        // Get the precedence of the next operator.
3392        int precedence = type.getPrecedence();
3393        Expression lhs = exprLhs;
3394
3395        // While greater precedence.
3396        while (type.isOperator(noIn) && precedence >= minPrecedence) {
3397            // Capture the operator token.
3398            final long op = token;
3399
3400            if (type == TERNARY) {
3401                // Skip operator.
3402                next();
3403
3404                // Pass expression. Middle expression of a conditional expression can be a "in"
3405                // expression - even in the contexts where "in" is not permitted.
3406                final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
3407
3408                expect(COLON);
3409
3410                // Fail expression.
3411                final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3412
3413                // Build up node.
3414                lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
3415            } else {
3416                // Skip operator.
3417                next();
3418
3419                 // Get the next primary expression.
3420                Expression rhs;
3421                final boolean isAssign = Token.descType(op) == ASSIGN;
3422                if(isAssign) {
3423                    defaultNames.push(lhs);
3424                }
3425                try {
3426                    rhs = unaryExpression();
3427                    // Get precedence of next operator.
3428                    int nextPrecedence = type.getPrecedence();
3429
3430                    // Subtask greater precedence.
3431                    while (type.isOperator(noIn) &&
3432                           (nextPrecedence > precedence ||
3433                           nextPrecedence == precedence && !type.isLeftAssociative())) {
3434                        rhs = expression(rhs, nextPrecedence, noIn);
3435                        nextPrecedence = type.getPrecedence();
3436                    }
3437                } finally {
3438                    if(isAssign) {
3439                        defaultNames.pop();
3440                    }
3441                }
3442                lhs = verifyAssignment(op, lhs, rhs);
3443            }
3444
3445            precedence = type.getPrecedence();
3446        }
3447
3448        return lhs;
3449    }
3450
3451    protected Expression assignmentExpression(final boolean noIn) {
3452        // This method is protected so that subclass can get details
3453        // at assignment expression start point!
3454
3455        // Exclude commas in expression parsing.
3456        return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3457    }
3458
3459    /**
3460     * Parse an end of line.
3461     */
3462    private void endOfLine() {
3463        switch (type) {
3464        case SEMICOLON:
3465        case EOL:
3466            next();
3467            break;
3468        case RPAREN:
3469        case RBRACKET:
3470        case RBRACE:
3471        case EOF:
3472            break;
3473        default:
3474            if (last != EOL) {
3475                expect(SEMICOLON);
3476            }
3477            break;
3478        }
3479    }
3480
3481    /**
3482     * Parse untagged template literal as string concatenation.
3483     */
3484    private Expression templateLiteral() {
3485        assert type == TEMPLATE || type == TEMPLATE_HEAD;
3486        final boolean noSubstitutionTemplate = type == TEMPLATE;
3487        long lastLiteralToken = token;
3488        LiteralNode<?> literal = getLiteral();
3489        if (noSubstitutionTemplate) {
3490            return literal;
3491        }
3492
3493        Expression concat = literal;
3494        TokenType lastLiteralType;
3495        do {
3496            final Expression expression = expression();
3497            if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
3498                throw error(AbstractParser.message("unterminated.template.expression"), token);
3499            }
3500            concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression);
3501            lastLiteralType = type;
3502            lastLiteralToken = token;
3503            literal = getLiteral();
3504            concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal);
3505        } while (lastLiteralType == TEMPLATE_MIDDLE);
3506        return concat;
3507    }
3508
3509    /**
3510     * Parse tagged template literal as argument list.
3511     * @return argument list for a tag function call (template object, ...substitutions)
3512     */
3513    private List<Expression> templateLiteralArgumentList() {
3514        assert type == TEMPLATE || type == TEMPLATE_HEAD;
3515        final ArrayList<Expression> argumentList = new ArrayList<>();
3516        final ArrayList<Expression> rawStrings = new ArrayList<>();
3517        final ArrayList<Expression> cookedStrings = new ArrayList<>();
3518        argumentList.add(null); // filled at the end
3519
3520        final long templateToken = token;
3521        final boolean hasSubstitutions = type == TEMPLATE_HEAD;
3522        addTemplateLiteralString(rawStrings, cookedStrings);
3523
3524        if (hasSubstitutions) {
3525            TokenType lastLiteralType;
3526            do {
3527                final Expression expression = expression();
3528                if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
3529                    throw error(AbstractParser.message("unterminated.template.expression"), token);
3530                }
3531                argumentList.add(expression);
3532
3533                lastLiteralType = type;
3534                addTemplateLiteralString(rawStrings, cookedStrings);
3535            } while (lastLiteralType == TEMPLATE_MIDDLE);
3536        }
3537
3538        final LiteralNode<Expression[]> rawStringArray = LiteralNode.newInstance(templateToken, finish, rawStrings);
3539        final LiteralNode<Expression[]> cookedStringArray = LiteralNode.newInstance(templateToken, finish, cookedStrings);
3540        final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray);
3541        argumentList.set(0, templateObject);
3542        return optimizeList(argumentList);
3543    }
3544
3545    private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) {
3546        final long stringToken = token;
3547        final String rawString = lexer.valueOfRawString(stringToken);
3548        final String cookedString = (String) getValue();
3549        next();
3550        rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString));
3551        cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
3552    }
3553
3554    @Override
3555    public String toString() {
3556        return "'JavaScript Parsing'";
3557    }
3558
3559    private static void markEval(final ParserContext lc) {
3560        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
3561        boolean flaggedCurrentFn = false;
3562        while (iter.hasNext()) {
3563            final ParserContextFunctionNode fn = iter.next();
3564            if (!flaggedCurrentFn) {
3565                fn.setFlag(FunctionNode.HAS_EVAL);
3566                flaggedCurrentFn = true;
3567            } else {
3568                fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
3569            }
3570            final ParserContextBlockNode body = lc.getFunctionBody(fn);
3571            // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
3572            // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
3573            // this method when the parser skips a nested function.
3574            body.setFlag(Block.NEEDS_SCOPE);
3575            fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
3576        }
3577    }
3578
3579    private void prependStatement(final Statement statement) {
3580        lc.prependStatementToCurrentNode(statement);
3581    }
3582
3583    private void appendStatement(final Statement statement) {
3584        lc.appendStatementToCurrentNode(statement);
3585    }
3586}
3587