Parser.java revision 1494:c7ef0fb26eff
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, true);
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, true);
950                break;
951            }
952            if (env._const_as_var && type == CONST) {
953                variableStatement(TokenType.VAR, true);
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, final boolean isStatement) {
1070        return variableStatement(varType, isStatement, -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) {
1108                throw error(AbstractParser.message("missing.const.assignment", name.getName()));
1109            }
1110
1111            // Allocate var node.
1112            final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name.setIsDeclaredHere(), init, varFlags);
1113            vars.add(var);
1114            appendStatement(var);
1115
1116            if (type != COMMARIGHT) {
1117                break;
1118            }
1119            next();
1120        }
1121
1122        // If is a statement then handle end of line.
1123        if (isStatement) {
1124            endOfLine();
1125        }
1126
1127        return vars;
1128    }
1129
1130    /**
1131     * EmptyStatement :
1132     *      ;
1133     *
1134     * See 12.3
1135     *
1136     * Parse an empty statement.
1137     */
1138    private void emptyStatement() {
1139        if (env._empty_statements) {
1140            appendStatement(new EmptyNode(line, token, Token.descPosition(token) + Token.descLength(token)));
1141        }
1142
1143        // SEMICOLON checked in caller.
1144        next();
1145    }
1146
1147    /**
1148     * ExpressionStatement :
1149     *      Expression ; // [lookahead ~( or  function )]
1150     *
1151     * See 12.4
1152     *
1153     * Parse an expression used in a statement block.
1154     */
1155    private void expressionStatement() {
1156        // Lookahead checked in caller.
1157        final int  expressionLine  = line;
1158        final long expressionToken = token;
1159
1160        // Get expression and add as statement.
1161        final Expression expression = expression();
1162
1163        ExpressionStatement expressionStatement = null;
1164        if (expression != null) {
1165            expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
1166            appendStatement(expressionStatement);
1167        } else {
1168            expect(null);
1169        }
1170
1171        endOfLine();
1172    }
1173
1174    /**
1175     * IfStatement :
1176     *      if ( Expression ) Statement else Statement
1177     *      if ( Expression ) Statement
1178     *
1179     * See 12.5
1180     *
1181     * Parse an IF statement.
1182     */
1183    private void ifStatement() {
1184        // Capture IF token.
1185        final int  ifLine  = line;
1186        final long ifToken = token;
1187         // IF tested in caller.
1188        next();
1189
1190        expect(LPAREN);
1191        final Expression test = expression();
1192        expect(RPAREN);
1193        final Block pass = getStatement();
1194
1195        Block fail = null;
1196        if (type == ELSE) {
1197            next();
1198            fail = getStatement();
1199        }
1200
1201        appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1202    }
1203
1204    /**
1205     * ... IterationStatement:
1206     *           ...
1207     *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1208     *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1209     *           for ( LeftHandSideExpression in Expression ) Statement
1210     *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1211     *
1212     * See 12.6
1213     *
1214     * Parse a FOR statement.
1215     */
1216    private void forStatement() {
1217        final long forToken = token;
1218        final int forLine = line;
1219        // start position of this for statement. This is used
1220        // for sort order for variables declared in the initializer
1221        // part of this 'for' statement (if any).
1222        final int forStart = Token.descPosition(forToken);
1223        // When ES6 for-let is enabled we create a container block to capture the LET.
1224        final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1225
1226        // Create FOR node, capturing FOR token.
1227        final ParserContextLoopNode forNode = new ParserContextLoopNode();
1228        lc.push(forNode);
1229        Block body = null;
1230        List<VarNode> vars = null;
1231        Expression init = null;
1232        JoinPredecessorExpression test = null;
1233        JoinPredecessorExpression modify = null;
1234
1235        int flags = 0;
1236
1237        try {
1238            // FOR tested in caller.
1239            next();
1240
1241            // Nashorn extension: for each expression.
1242            // iterate property values rather than property names.
1243            if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1244                flags |= ForNode.IS_FOR_EACH;
1245                next();
1246            }
1247
1248            expect(LPAREN);
1249
1250
1251            switch (type) {
1252            case VAR:
1253                // Var declaration captured in for outer block.
1254                vars = variableStatement(type, false, forStart);
1255                break;
1256            case SEMICOLON:
1257                break;
1258            default:
1259                if (useBlockScope() && (type == LET || type == CONST)) {
1260                    if (type == LET) {
1261                        flags |= ForNode.PER_ITERATION_SCOPE;
1262                    }
1263                    // LET/CONST declaration captured in container block created above.
1264                    vars = variableStatement(type, false, forStart);
1265                    break;
1266                }
1267                if (env._const_as_var && type == CONST) {
1268                    // Var declaration captured in for outer block.
1269                    vars = variableStatement(TokenType.VAR, false, forStart);
1270                    break;
1271                }
1272
1273                init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1274                break;
1275            }
1276
1277            switch (type) {
1278            case SEMICOLON:
1279                // for (init; test; modify)
1280
1281                // for each (init; test; modify) is invalid
1282                if ((flags & ForNode.IS_FOR_EACH) != 0) {
1283                    throw error(AbstractParser.message("for.each.without.in"), token);
1284                }
1285
1286                expect(SEMICOLON);
1287                if (type != SEMICOLON) {
1288                    test = joinPredecessorExpression();
1289                }
1290                expect(SEMICOLON);
1291                if (type != RPAREN) {
1292                    modify = joinPredecessorExpression();
1293                }
1294                break;
1295
1296            case IN:
1297                flags |= ForNode.IS_FOR_IN;
1298                test = new JoinPredecessorExpression();
1299                if (vars != null) {
1300                    // for (var i in obj)
1301                    if (vars.size() == 1) {
1302                        init = new IdentNode(vars.get(0).getName());
1303                    } else {
1304                        // for (var i, j in obj) is invalid
1305                        throw error(AbstractParser.message("many.vars.in.for.in.loop"), vars.get(1).getToken());
1306                    }
1307
1308                } else {
1309                    // for (expr in obj)
1310                    assert init != null : "for..in init expression can not be null here";
1311
1312                    // check if initial expression is a valid L-value
1313                    if (!(init instanceof AccessNode ||
1314                          init instanceof IndexNode ||
1315                          init instanceof IdentNode)) {
1316                        throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
1317                    }
1318
1319                    if (init instanceof IdentNode) {
1320                        if (!checkIdentLValue((IdentNode)init)) {
1321                            throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
1322                        }
1323                        verifyStrictIdent((IdentNode)init, "for-in iterator");
1324                    }
1325                }
1326
1327                next();
1328
1329                // Get the collection expression.
1330                modify = joinPredecessorExpression();
1331                break;
1332
1333            default:
1334                expect(SEMICOLON);
1335                break;
1336            }
1337
1338            expect(RPAREN);
1339
1340            // Set the for body.
1341            body = getStatement();
1342        } finally {
1343            lc.pop(forNode);
1344
1345            if (vars != null) {
1346                for (final VarNode var : vars) {
1347                    appendStatement(var);
1348                }
1349            }
1350            if (body != null) {
1351                appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
1352            }
1353            if (outer != null) {
1354                restoreBlock(outer);
1355                if (body != null) {
1356                    appendStatement(new BlockStatement(forLine, new Block(
1357                                    outer.getToken(),
1358                                    body.getFinish(),
1359                                    outer.getStatements())));
1360                }
1361            }
1362        }
1363    }
1364
1365    /**
1366     * ...IterationStatement :
1367     *           ...
1368     *           while ( Expression ) Statement
1369     *           ...
1370     *
1371     * See 12.6
1372     *
1373     * Parse while statement.
1374     */
1375    private void whileStatement() {
1376        // Capture WHILE token.
1377        final long whileToken = token;
1378        final int whileLine = line;
1379        // WHILE tested in caller.
1380        next();
1381
1382        final ParserContextLoopNode whileNode = new ParserContextLoopNode();
1383        lc.push(whileNode);
1384
1385        JoinPredecessorExpression test = null;
1386        Block body = null;
1387
1388        try {
1389            expect(LPAREN);
1390            test = joinPredecessorExpression();
1391            expect(RPAREN);
1392            body = getStatement();
1393        } finally {
1394            lc.pop(whileNode);
1395        }
1396
1397        if (body != null) {
1398            appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
1399        }
1400    }
1401
1402    /**
1403     * ...IterationStatement :
1404     *           ...
1405     *           do Statement while( Expression ) ;
1406     *           ...
1407     *
1408     * See 12.6
1409     *
1410     * Parse DO WHILE statement.
1411     */
1412    private void doStatement() {
1413        // Capture DO token.
1414        final long doToken = token;
1415        int doLine = 0;
1416        // DO tested in the caller.
1417        next();
1418
1419        final ParserContextLoopNode doWhileNode = new ParserContextLoopNode();
1420        lc.push(doWhileNode);
1421
1422        Block body = null;
1423        JoinPredecessorExpression test = null;
1424
1425        try {
1426           // Get DO body.
1427            body = getStatement();
1428
1429            expect(WHILE);
1430            expect(LPAREN);
1431            doLine = line;
1432            test = joinPredecessorExpression();
1433            expect(RPAREN);
1434
1435            if (type == SEMICOLON) {
1436                endOfLine();
1437            }
1438        } finally {
1439            lc.pop(doWhileNode);
1440        }
1441
1442        appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
1443    }
1444
1445    /**
1446     * ContinueStatement :
1447     *      continue Identifier? ; // [no LineTerminator here]
1448     *
1449     * See 12.7
1450     *
1451     * Parse CONTINUE statement.
1452     */
1453    private void continueStatement() {
1454        // Capture CONTINUE token.
1455        final int  continueLine  = line;
1456        final long continueToken = token;
1457        // CONTINUE tested in caller.
1458        nextOrEOL();
1459
1460        ParserContextLabelNode labelNode = null;
1461
1462        // SEMICOLON or label.
1463        switch (type) {
1464        case RBRACE:
1465        case SEMICOLON:
1466        case EOL:
1467        case EOF:
1468            break;
1469
1470        default:
1471            final IdentNode ident = getIdent();
1472            labelNode = lc.findLabel(ident.getName());
1473
1474            if (labelNode == null) {
1475                throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1476            }
1477
1478            break;
1479        }
1480
1481        final String labelName = labelNode == null ? null : labelNode.getLabelName();
1482        final ParserContextLoopNode targetNode = lc.getContinueTo(labelName);
1483
1484        if (targetNode == null) {
1485            throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
1486        }
1487
1488        endOfLine();
1489
1490        // Construct and add CONTINUE node.
1491        appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
1492    }
1493
1494    /**
1495     * BreakStatement :
1496     *      break Identifier? ; // [no LineTerminator here]
1497     *
1498     * See 12.8
1499     *
1500     */
1501    private void breakStatement() {
1502        // Capture BREAK token.
1503        final int  breakLine  = line;
1504        final long breakToken = token;
1505        // BREAK tested in caller.
1506        nextOrEOL();
1507
1508        ParserContextLabelNode labelNode = null;
1509
1510        // SEMICOLON or label.
1511        switch (type) {
1512        case RBRACE:
1513        case SEMICOLON:
1514        case EOL:
1515        case EOF:
1516            break;
1517
1518        default:
1519            final IdentNode ident = getIdent();
1520            labelNode = lc.findLabel(ident.getName());
1521
1522            if (labelNode == null) {
1523                throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1524            }
1525
1526            break;
1527        }
1528
1529        //either an explicit label - then get its node or just a "break" - get first breakable
1530        //targetNode is what we are breaking out from.
1531        final String labelName = labelNode == null ? null : labelNode.getLabelName();
1532        final ParserContextBreakableNode targetNode = lc.getBreakable(labelName);
1533        if (targetNode == null) {
1534            throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
1535        }
1536
1537        endOfLine();
1538
1539        // Construct and add BREAK node.
1540        appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
1541    }
1542
1543    /**
1544     * ReturnStatement :
1545     *      return Expression? ; // [no LineTerminator here]
1546     *
1547     * See 12.9
1548     *
1549     * Parse RETURN statement.
1550     */
1551    private void returnStatement() {
1552        // check for return outside function
1553        if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT) {
1554            throw error(AbstractParser.message("invalid.return"));
1555        }
1556
1557        // Capture RETURN token.
1558        final int  returnLine  = line;
1559        final long returnToken = token;
1560        // RETURN tested in caller.
1561        nextOrEOL();
1562
1563        Expression expression = null;
1564
1565        // SEMICOLON or expression.
1566        switch (type) {
1567        case RBRACE:
1568        case SEMICOLON:
1569        case EOL:
1570        case EOF:
1571            break;
1572
1573        default:
1574            expression = expression();
1575            break;
1576        }
1577
1578        endOfLine();
1579
1580        // Construct and add RETURN node.
1581        appendStatement(new ReturnNode(returnLine, returnToken, finish, expression));
1582    }
1583
1584    /**
1585     * YieldStatement :
1586     *      yield Expression? ; // [no LineTerminator here]
1587     *
1588     * JavaScript 1.8
1589     *
1590     * Parse YIELD statement.
1591     */
1592    private void yieldStatement() {
1593        // Capture YIELD token.
1594        final int  yieldLine  = line;
1595        final long yieldToken = token;
1596        // YIELD tested in caller.
1597        nextOrEOL();
1598
1599        Expression expression = null;
1600
1601        // SEMICOLON or expression.
1602        switch (type) {
1603        case RBRACE:
1604        case SEMICOLON:
1605        case EOL:
1606        case EOF:
1607            break;
1608
1609        default:
1610            expression = expression();
1611            break;
1612        }
1613
1614        endOfLine();
1615
1616        // Construct and add YIELD node.
1617        appendStatement(new ReturnNode(yieldLine, yieldToken, finish, expression));
1618    }
1619
1620    /**
1621     * WithStatement :
1622     *      with ( Expression ) Statement
1623     *
1624     * See 12.10
1625     *
1626     * Parse WITH statement.
1627     */
1628    private void withStatement() {
1629        // Capture WITH token.
1630        final int  withLine  = line;
1631        final long withToken = token;
1632        // WITH tested in caller.
1633        next();
1634
1635        // ECMA 12.10.1 strict mode restrictions
1636        if (isStrictMode) {
1637            throw error(AbstractParser.message("strict.no.with"), withToken);
1638        }
1639
1640        expect(LPAREN);
1641        final Expression expression = expression();
1642        expect(RPAREN);
1643        final Block body = getStatement();
1644
1645        appendStatement(new WithNode(withLine, withToken, finish, expression, body));
1646    }
1647
1648    /**
1649     * SwitchStatement :
1650     *      switch ( Expression ) CaseBlock
1651     *
1652     * CaseBlock :
1653     *      { CaseClauses? }
1654     *      { CaseClauses? DefaultClause CaseClauses }
1655     *
1656     * CaseClauses :
1657     *      CaseClause
1658     *      CaseClauses CaseClause
1659     *
1660     * CaseClause :
1661     *      case Expression : StatementList?
1662     *
1663     * DefaultClause :
1664     *      default : StatementList?
1665     *
1666     * See 12.11
1667     *
1668     * Parse SWITCH statement.
1669     */
1670    private void switchStatement() {
1671        final int  switchLine  = line;
1672        final long switchToken = token;
1673        // SWITCH tested in caller.
1674        next();
1675
1676        // Create and add switch statement.
1677        final ParserContextSwitchNode switchNode= new ParserContextSwitchNode();
1678        lc.push(switchNode);
1679
1680        CaseNode defaultCase = null;
1681        // Prepare to accumulate cases.
1682        final List<CaseNode> cases = new ArrayList<>();
1683
1684        Expression expression = null;
1685
1686        try {
1687            expect(LPAREN);
1688            expression = expression();
1689            expect(RPAREN);
1690
1691            expect(LBRACE);
1692
1693
1694            while (type != RBRACE) {
1695                // Prepare for next case.
1696                Expression caseExpression = null;
1697                final long caseToken = token;
1698
1699                switch (type) {
1700                case CASE:
1701                    next();
1702                    caseExpression = expression();
1703                    break;
1704
1705                case DEFAULT:
1706                    if (defaultCase != null) {
1707                        throw error(AbstractParser.message("duplicate.default.in.switch"));
1708                    }
1709                    next();
1710                    break;
1711
1712                default:
1713                    // Force an error.
1714                    expect(CASE);
1715                    break;
1716                }
1717
1718                expect(COLON);
1719
1720                // Get CASE body.
1721                final Block statements = getBlock(false);
1722                final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
1723
1724                if (caseExpression == null) {
1725                    defaultCase = caseNode;
1726                }
1727
1728                cases.add(caseNode);
1729            }
1730
1731            next();
1732        } finally {
1733            lc.pop(switchNode);
1734        }
1735
1736        appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase));
1737    }
1738
1739    /**
1740     * LabelledStatement :
1741     *      Identifier : Statement
1742     *
1743     * See 12.12
1744     *
1745     * Parse label statement.
1746     */
1747    private void labelStatement() {
1748        // Capture label token.
1749        final long labelToken = token;
1750        // Get label ident.
1751        final IdentNode ident = getIdent();
1752
1753        expect(COLON);
1754
1755        if (lc.findLabel(ident.getName()) != null) {
1756            throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
1757        }
1758
1759        final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName());
1760        Block body = null;
1761        try {
1762            lc.push(labelNode);
1763            body = getStatement();
1764        } finally {
1765            assert lc.peek() instanceof ParserContextLabelNode;
1766            lc.pop(labelNode);
1767        }
1768
1769        appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
1770    }
1771
1772    /**
1773     * ThrowStatement :
1774     *      throw Expression ; // [no LineTerminator here]
1775     *
1776     * See 12.13
1777     *
1778     * Parse throw statement.
1779     */
1780    private void throwStatement() {
1781        // Capture THROW token.
1782        final int  throwLine  = line;
1783        final long throwToken = token;
1784        // THROW tested in caller.
1785        nextOrEOL();
1786
1787        Expression expression = null;
1788
1789        // SEMICOLON or expression.
1790        switch (type) {
1791        case RBRACE:
1792        case SEMICOLON:
1793        case EOL:
1794            break;
1795
1796        default:
1797            expression = expression();
1798            break;
1799        }
1800
1801        if (expression == null) {
1802            throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
1803        }
1804
1805        endOfLine();
1806
1807        appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
1808    }
1809
1810    /**
1811     * TryStatement :
1812     *      try Block Catch
1813     *      try Block Finally
1814     *      try Block Catch Finally
1815     *
1816     * Catch :
1817     *      catch( Identifier if Expression ) Block
1818     *      catch( Identifier ) Block
1819     *
1820     * Finally :
1821     *      finally Block
1822     *
1823     * See 12.14
1824     *
1825     * Parse TRY statement.
1826     */
1827    private void tryStatement() {
1828        // Capture TRY token.
1829        final int  tryLine  = line;
1830        final long tryToken = token;
1831        // TRY tested in caller.
1832        next();
1833
1834        // Container block needed to act as target for labeled break statements
1835        final int startLine = line;
1836        final ParserContextBlockNode outer = newBlock();
1837        // Create try.
1838
1839        try {
1840            final Block       tryBody     = getBlock(true);
1841            final List<Block> catchBlocks = new ArrayList<>();
1842
1843            while (type == CATCH) {
1844                final int  catchLine  = line;
1845                final long catchToken = token;
1846                next();
1847                expect(LPAREN);
1848                final IdentNode exception = getIdent();
1849
1850                // ECMA 12.4.1 strict mode restrictions
1851                verifyStrictIdent(exception, "catch argument");
1852
1853                // Nashorn extension: catch clause can have optional
1854                // condition. So, a single try can have more than one
1855                // catch clause each with it's own condition.
1856                final Expression ifExpression;
1857                if (!env._no_syntax_extensions && type == IF) {
1858                    next();
1859                    // Get the exception condition.
1860                    ifExpression = expression();
1861                } else {
1862                    ifExpression = null;
1863                }
1864
1865                expect(RPAREN);
1866
1867                final ParserContextBlockNode catchBlock = newBlock();
1868                try {
1869                    // Get CATCH body.
1870                    final Block catchBody = getBlock(true);
1871                    final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
1872                    appendStatement(catchNode);
1873                } finally {
1874                    restoreBlock(catchBlock);
1875                    catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags() | Block.IS_SYNTHETIC, catchBlock.getStatements()));
1876                }
1877
1878                // If unconditional catch then should to be the end.
1879                if (ifExpression == null) {
1880                    break;
1881                }
1882            }
1883
1884            // Prepare to capture finally statement.
1885            Block finallyStatements = null;
1886
1887            if (type == FINALLY) {
1888                next();
1889                finallyStatements = getBlock(true);
1890            }
1891
1892            // Need at least one catch or a finally.
1893            if (catchBlocks.isEmpty() && finallyStatements == null) {
1894                throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
1895            }
1896
1897            final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
1898            // Add try.
1899            assert lc.peek() == outer;
1900            appendStatement(tryNode);
1901        } finally {
1902            restoreBlock(outer);
1903        }
1904
1905        appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags() | Block.IS_SYNTHETIC, outer.getStatements())));
1906    }
1907
1908    /**
1909     * DebuggerStatement :
1910     *      debugger ;
1911     *
1912     * See 12.15
1913     *
1914     * Parse debugger statement.
1915     */
1916    private void  debuggerStatement() {
1917        // Capture DEBUGGER token.
1918        final int  debuggerLine  = line;
1919        final long debuggerToken = token;
1920        // DEBUGGER tested in caller.
1921        next();
1922        endOfLine();
1923        appendStatement(new DebuggerNode(debuggerLine, debuggerToken, finish));
1924    }
1925
1926    /**
1927     * PrimaryExpression :
1928     *      this
1929     *      Identifier
1930     *      Literal
1931     *      ArrayLiteral
1932     *      ObjectLiteral
1933     *      RegularExpressionLiteral
1934     *      TemplateLiteral
1935     *      ( Expression )
1936     *
1937     * Parse primary expression.
1938     * @return Expression node.
1939     */
1940    @SuppressWarnings("fallthrough")
1941    private Expression primaryExpression() {
1942        // Capture first token.
1943        final int  primaryLine  = line;
1944        final long primaryToken = token;
1945
1946        switch (type) {
1947        case THIS:
1948            final String name = type.getName();
1949            next();
1950            lc.getCurrentFunction().setFlag(FunctionNode.USES_THIS);
1951            return new IdentNode(primaryToken, finish, name);
1952        case IDENT:
1953            final IdentNode ident = getIdent();
1954            if (ident == null) {
1955                break;
1956            }
1957            detectSpecialProperty(ident);
1958            return ident;
1959        case OCTAL_LEGACY:
1960            if (isStrictMode) {
1961               throw error(AbstractParser.message("strict.no.octal"), token);
1962            }
1963        case STRING:
1964        case ESCSTRING:
1965        case DECIMAL:
1966        case HEXADECIMAL:
1967        case OCTAL:
1968        case BINARY_NUMBER:
1969        case FLOATING:
1970        case REGEX:
1971        case XML:
1972            return getLiteral();
1973        case EXECSTRING:
1974            return execString(primaryLine, primaryToken);
1975        case FALSE:
1976            next();
1977            return LiteralNode.newInstance(primaryToken, finish, false);
1978        case TRUE:
1979            next();
1980            return LiteralNode.newInstance(primaryToken, finish, true);
1981        case NULL:
1982            next();
1983            return LiteralNode.newInstance(primaryToken, finish);
1984        case LBRACKET:
1985            return arrayLiteral();
1986        case LBRACE:
1987            return objectLiteral();
1988        case LPAREN:
1989            next();
1990
1991            final Expression expression = expression();
1992
1993            expect(RPAREN);
1994
1995            return expression;
1996        case TEMPLATE:
1997        case TEMPLATE_HEAD:
1998            return templateLiteral();
1999
2000        default:
2001            // In this context some operator tokens mark the start of a literal.
2002            if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
2003                next();
2004                return getLiteral();
2005            }
2006            if (isNonStrictModeIdent()) {
2007                return getIdent();
2008            }
2009            break;
2010        }
2011
2012        return null;
2013    }
2014
2015    /**
2016     * Convert execString to a call to $EXEC.
2017     *
2018     * @param primaryToken Original string token.
2019     * @return callNode to $EXEC.
2020     */
2021    CallNode execString(final int primaryLine, final long primaryToken) {
2022        // Synthesize an ident to call $EXEC.
2023        final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
2024        // Skip over EXECSTRING.
2025        next();
2026        // Set up argument list for call.
2027        // Skip beginning of edit string expression.
2028        expect(LBRACE);
2029        // Add the following expression to arguments.
2030        final List<Expression> arguments = Collections.singletonList(expression());
2031        // Skip ending of edit string expression.
2032        expect(RBRACE);
2033
2034        return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
2035    }
2036
2037    /**
2038     * ArrayLiteral :
2039     *      [ Elision? ]
2040     *      [ ElementList ]
2041     *      [ ElementList , Elision? ]
2042     *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
2043     *
2044     * ElementList : Elision? AssignmentExpression
2045     *      ElementList , Elision? AssignmentExpression
2046     *
2047     * Elision :
2048     *      ,
2049     *      Elision ,
2050     *
2051     * See 12.1.4
2052     * JavaScript 1.8
2053     *
2054     * Parse array literal.
2055     * @return Expression node.
2056     */
2057    private LiteralNode<Expression[]> arrayLiteral() {
2058        // Capture LBRACKET token.
2059        final long arrayToken = token;
2060        // LBRACKET tested in caller.
2061        next();
2062
2063        // Prepare to accumulate elements.
2064        final List<Expression> elements = new ArrayList<>();
2065        // Track elisions.
2066        boolean elision = true;
2067loop:
2068        while (true) {
2069            switch (type) {
2070            case RBRACKET:
2071                next();
2072
2073                break loop;
2074
2075            case COMMARIGHT:
2076                next();
2077
2078                // If no prior expression
2079                if (elision) {
2080                    elements.add(null);
2081                }
2082
2083                elision = true;
2084
2085                break;
2086
2087            default:
2088                if (!elision) {
2089                    throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2090                }
2091                // Add expression element.
2092                final Expression expression = assignmentExpression(false);
2093
2094                if (expression != null) {
2095                    elements.add(expression);
2096                } else {
2097                    expect(RBRACKET);
2098                }
2099
2100                elision = false;
2101                break;
2102            }
2103        }
2104
2105        return LiteralNode.newInstance(arrayToken, finish, elements);
2106    }
2107
2108    /**
2109     * ObjectLiteral :
2110     *      { }
2111     *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2112     *
2113     * PropertyNameAndValueList :
2114     *      PropertyAssignment
2115     *      PropertyNameAndValueList , PropertyAssignment
2116     *
2117     * See 11.1.5
2118     *
2119     * Parse an object literal.
2120     * @return Expression node.
2121     */
2122    private ObjectNode objectLiteral() {
2123        // Capture LBRACE token.
2124        final long objectToken = token;
2125        // LBRACE tested in caller.
2126        next();
2127
2128        // Object context.
2129        // Prepare to accumulate elements.
2130        final List<PropertyNode> elements = new ArrayList<>();
2131        final Map<String, Integer> map = new HashMap<>();
2132
2133        // Create a block for the object literal.
2134        boolean commaSeen = true;
2135loop:
2136        while (true) {
2137            switch (type) {
2138                case RBRACE:
2139                    next();
2140                    break loop;
2141
2142                case COMMARIGHT:
2143                    if (commaSeen) {
2144                        throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2145                    }
2146                    next();
2147                    commaSeen = true;
2148                    break;
2149
2150                default:
2151                    if (!commaSeen) {
2152                        throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2153                    }
2154
2155                    commaSeen = false;
2156                    // Get and add the next property.
2157                    final PropertyNode property = propertyAssignment();
2158                    final String key = property.getKeyName();
2159                    final Integer existing = map.get(key);
2160
2161                    if (existing == null) {
2162                        map.put(key, elements.size());
2163                        elements.add(property);
2164                        break;
2165                    }
2166
2167                    final PropertyNode existingProperty = elements.get(existing);
2168
2169                    // ECMA section 11.1.5 Object Initialiser
2170                    // point # 4 on property assignment production
2171                    final Expression   value  = property.getValue();
2172                    final FunctionNode getter = property.getGetter();
2173                    final FunctionNode setter = property.getSetter();
2174
2175                    final Expression   prevValue  = existingProperty.getValue();
2176                    final FunctionNode prevGetter = existingProperty.getGetter();
2177                    final FunctionNode prevSetter = existingProperty.getSetter();
2178
2179                    // ECMA 11.1.5 strict mode restrictions
2180                    if (isStrictMode && value != null && prevValue != null) {
2181                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2182                    }
2183
2184                    final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
2185                    final boolean isAccessor     = getter != null     || setter != null;
2186
2187                    // data property redefined as accessor property
2188                    if (prevValue != null && isAccessor) {
2189                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2190                    }
2191
2192                    // accessor property redefined as data
2193                    if (isPrevAccessor && value != null) {
2194                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2195                    }
2196
2197                    if (isAccessor && isPrevAccessor) {
2198                        if (getter != null && prevGetter != null ||
2199                                setter != null && prevSetter != null) {
2200                            throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2201                        }
2202                    }
2203
2204                    if (value != null) {
2205                        elements.add(property);
2206                    } else if (getter != null) {
2207                        elements.set(existing, existingProperty.setGetter(getter));
2208                    } else if (setter != null) {
2209                        elements.set(existing, existingProperty.setSetter(setter));
2210                    }
2211                    break;
2212            }
2213        }
2214
2215        return new ObjectNode(objectToken, finish, elements);
2216    }
2217
2218    /**
2219     * PropertyName :
2220     *      IdentifierName
2221     *      StringLiteral
2222     *      NumericLiteral
2223     *
2224     * See 11.1.5
2225     *
2226     * @return PropertyName node
2227     */
2228    @SuppressWarnings("fallthrough")
2229    private PropertyKey propertyName() {
2230        switch (type) {
2231        case IDENT:
2232            return getIdent().setIsPropertyName();
2233        case OCTAL_LEGACY:
2234            if (isStrictMode) {
2235                throw error(AbstractParser.message("strict.no.octal"), token);
2236            }
2237        case STRING:
2238        case ESCSTRING:
2239        case DECIMAL:
2240        case HEXADECIMAL:
2241        case OCTAL:
2242        case BINARY_NUMBER:
2243        case FLOATING:
2244            return getLiteral();
2245        default:
2246            return getIdentifierName().setIsPropertyName();
2247        }
2248    }
2249
2250    /**
2251     * PropertyAssignment :
2252     *      PropertyName : AssignmentExpression
2253     *      get PropertyName ( ) { FunctionBody }
2254     *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
2255     *
2256     * PropertySetParameterList :
2257     *      Identifier
2258     *
2259     * PropertyName :
2260     *      IdentifierName
2261     *      StringLiteral
2262     *      NumericLiteral
2263     *
2264     * See 11.1.5
2265     *
2266     * Parse an object literal property.
2267     * @return Property or reference node.
2268     */
2269    private PropertyNode propertyAssignment() {
2270        // Capture firstToken.
2271        final long propertyToken = token;
2272        final int  functionLine  = line;
2273
2274        PropertyKey propertyName;
2275
2276        if (type == IDENT) {
2277            // Get IDENT.
2278            final String ident = (String)expectValue(IDENT);
2279
2280            if (type != COLON) {
2281                final long getSetToken = propertyToken;
2282
2283                switch (ident) {
2284                case "get":
2285                    final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
2286                    return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null);
2287
2288                case "set":
2289                    final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
2290                    return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode);
2291                default:
2292                    break;
2293                }
2294            }
2295
2296            propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
2297        } else {
2298            propertyName = propertyName();
2299        }
2300
2301        expect(COLON);
2302
2303        defaultNames.push(propertyName);
2304        try {
2305            return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
2306        } finally {
2307            defaultNames.pop();
2308        }
2309    }
2310
2311    private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
2312        final PropertyKey getIdent = propertyName();
2313        final String getterName = getIdent.getPropertyName();
2314        final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
2315        expect(LPAREN);
2316        expect(RPAREN);
2317
2318        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
2319        lc.push(functionNode);
2320
2321        Block functionBody;
2322
2323
2324        try {
2325            functionBody = functionBody(functionNode);
2326        } finally {
2327            lc.pop(functionNode);
2328        }
2329
2330        final FunctionNode  function = createFunctionNode(
2331                functionNode,
2332                getSetToken,
2333                getNameNode,
2334                Collections.<IdentNode>emptyList(),
2335                FunctionNode.Kind.GETTER,
2336                functionLine,
2337                functionBody);
2338
2339        return new PropertyFunction(getIdent, function);
2340    }
2341
2342    private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
2343        final PropertyKey setIdent = propertyName();
2344        final String setterName = setIdent.getPropertyName();
2345        final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
2346        expect(LPAREN);
2347        // be sloppy and allow missing setter parameter even though
2348        // spec does not permit it!
2349        final IdentNode argIdent;
2350        if (type == IDENT || isNonStrictModeIdent()) {
2351            argIdent = getIdent();
2352            verifyStrictIdent(argIdent, "setter argument");
2353        } else {
2354            argIdent = null;
2355        }
2356        expect(RPAREN);
2357        final List<IdentNode> parameters = new ArrayList<>();
2358        if (argIdent != null) {
2359            parameters.add(argIdent);
2360        }
2361
2362
2363        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
2364        lc.push(functionNode);
2365
2366        Block functionBody;
2367        try {
2368            functionBody = functionBody(functionNode);
2369        } finally {
2370            lc.pop(functionNode);
2371        }
2372
2373
2374        final FunctionNode  function = createFunctionNode(
2375                functionNode,
2376                getSetToken,
2377                setNameNode,
2378                parameters,
2379                FunctionNode.Kind.SETTER,
2380                functionLine,
2381                functionBody);
2382
2383        return new PropertyFunction(setIdent, function);
2384    }
2385
2386    private static class PropertyFunction {
2387        final PropertyKey ident;
2388        final FunctionNode functionNode;
2389
2390        PropertyFunction(final PropertyKey ident, final FunctionNode function) {
2391            this.ident = ident;
2392            this.functionNode = function;
2393        }
2394    }
2395
2396    /**
2397     * Parse left hand side expression.
2398     *
2399     * LeftHandSideExpression :
2400     *      NewExpression
2401     *      CallExpression
2402     *
2403     * CallExpression :
2404     *      MemberExpression Arguments
2405     *      CallExpression Arguments
2406     *      CallExpression [ Expression ]
2407     *      CallExpression . IdentifierName
2408     *      CallExpression TemplateLiteral
2409     *
2410     * @return Expression node.
2411     */
2412    private Expression leftHandSideExpression() {
2413        int  callLine  = line;
2414        long callToken = token;
2415
2416        Expression lhs = memberExpression();
2417
2418        if (type == LPAREN) {
2419            final List<Expression> arguments = optimizeList(argumentList());
2420
2421            // Catch special functions.
2422            if (lhs instanceof IdentNode) {
2423                detectSpecialFunction((IdentNode)lhs);
2424            }
2425
2426            lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2427        }
2428
2429loop:
2430        while (true) {
2431            // Capture token.
2432            callLine  = line;
2433            callToken = token;
2434
2435            switch (type) {
2436            case LPAREN: {
2437                // Get NEW or FUNCTION arguments.
2438                final List<Expression> arguments = optimizeList(argumentList());
2439
2440                // Create call node.
2441                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2442
2443                break;
2444            }
2445            case LBRACKET: {
2446                next();
2447
2448                // Get array index.
2449                final Expression rhs = expression();
2450
2451                expect(RBRACKET);
2452
2453                // Create indexing node.
2454                lhs = new IndexNode(callToken, finish, lhs, rhs);
2455
2456                break;
2457            }
2458            case PERIOD: {
2459                next();
2460
2461                final IdentNode property = getIdentifierName();
2462
2463                // Create property access node.
2464                lhs = new AccessNode(callToken, finish, lhs, property.getName());
2465
2466                break;
2467            }
2468            case TEMPLATE:
2469            case TEMPLATE_HEAD: {
2470                // tagged template literal
2471                final List<Expression> arguments = templateLiteralArgumentList();
2472
2473                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2474
2475                break;
2476            }
2477            default:
2478                break loop;
2479            }
2480        }
2481
2482        return lhs;
2483    }
2484
2485    /**
2486     * NewExpression :
2487     *      MemberExpression
2488     *      new NewExpression
2489     *
2490     * See 11.2
2491     *
2492     * Parse new expression.
2493     * @return Expression node.
2494     */
2495    private Expression newExpression() {
2496        final long newToken = token;
2497        // NEW is tested in caller.
2498        next();
2499
2500        // Get function base.
2501        final int  callLine    = line;
2502        final Expression constructor = memberExpression();
2503        if (constructor == null) {
2504            return null;
2505        }
2506        // Get arguments.
2507        ArrayList<Expression> arguments;
2508
2509        // Allow for missing arguments.
2510        if (type == LPAREN) {
2511            arguments = argumentList();
2512        } else {
2513            arguments = new ArrayList<>();
2514        }
2515
2516        // Nashorn extension: This is to support the following interface implementation
2517        // syntax:
2518        //
2519        //     var r = new java.lang.Runnable() {
2520        //         run: function() { println("run"); }
2521        //     };
2522        //
2523        // The object literal following the "new Constructor()" expression
2524        // is passed as an additional (last) argument to the constructor.
2525        if (!env._no_syntax_extensions && type == LBRACE) {
2526            arguments.add(objectLiteral());
2527        }
2528
2529        final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
2530
2531        return new UnaryNode(newToken, callNode);
2532    }
2533
2534    /**
2535     * Parse member expression.
2536     *
2537     * MemberExpression :
2538     *      PrimaryExpression
2539     *      FunctionExpression
2540     *      MemberExpression [ Expression ]
2541     *      MemberExpression . IdentifierName
2542     *      MemberExpression TemplateLiteral
2543     *      new MemberExpression Arguments
2544     *
2545     * @return Expression node.
2546     */
2547    private Expression memberExpression() {
2548        // Prepare to build operation.
2549        Expression lhs;
2550
2551        switch (type) {
2552        case NEW:
2553            // Get new expression.
2554            lhs = newExpression();
2555            break;
2556
2557        case FUNCTION:
2558            // Get function expression.
2559            lhs = functionExpression(false, false);
2560            break;
2561
2562        default:
2563            // Get primary expression.
2564            lhs = primaryExpression();
2565            break;
2566        }
2567
2568loop:
2569        while (true) {
2570            // Capture token.
2571            final long callToken = token;
2572
2573            switch (type) {
2574            case LBRACKET: {
2575                next();
2576
2577                // Get array index.
2578                final Expression index = expression();
2579
2580                expect(RBRACKET);
2581
2582                // Create indexing node.
2583                lhs = new IndexNode(callToken, finish, lhs, index);
2584
2585                break;
2586            }
2587            case PERIOD: {
2588                if (lhs == null) {
2589                    throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2590                }
2591
2592                next();
2593
2594                final IdentNode property = getIdentifierName();
2595
2596                // Create property access node.
2597                lhs = new AccessNode(callToken, finish, lhs, property.getName());
2598
2599                break;
2600            }
2601            case TEMPLATE:
2602            case TEMPLATE_HEAD: {
2603                // tagged template literal
2604                final int callLine = line;
2605                final List<Expression> arguments = templateLiteralArgumentList();
2606
2607                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2608
2609                break;
2610            }
2611            default:
2612                break loop;
2613            }
2614        }
2615
2616        return lhs;
2617    }
2618
2619    /**
2620     * Arguments :
2621     *      ( )
2622     *      ( ArgumentList )
2623     *
2624     * ArgumentList :
2625     *      AssignmentExpression
2626     *      ArgumentList , AssignmentExpression
2627     *
2628     * See 11.2
2629     *
2630     * Parse function call arguments.
2631     * @return Argument list.
2632     */
2633    private ArrayList<Expression> argumentList() {
2634        // Prepare to accumulate list of arguments.
2635        final ArrayList<Expression> nodeList = new ArrayList<>();
2636        // LPAREN tested in caller.
2637        next();
2638
2639        // Track commas.
2640        boolean first = true;
2641
2642        while (type != RPAREN) {
2643            // Comma prior to every argument except the first.
2644            if (!first) {
2645                expect(COMMARIGHT);
2646            } else {
2647                first = false;
2648            }
2649
2650            // Get argument expression.
2651            nodeList.add(assignmentExpression(false));
2652        }
2653
2654        expect(RPAREN);
2655        return nodeList;
2656    }
2657
2658    private static <T> List<T> optimizeList(final ArrayList<T> list) {
2659        switch(list.size()) {
2660            case 0: {
2661                return Collections.emptyList();
2662            }
2663            case 1: {
2664                return Collections.singletonList(list.get(0));
2665            }
2666            default: {
2667                list.trimToSize();
2668                return list;
2669            }
2670        }
2671    }
2672
2673    /**
2674     * FunctionDeclaration :
2675     *      function Identifier ( FormalParameterList? ) { FunctionBody }
2676     *
2677     * FunctionExpression :
2678     *      function Identifier? ( FormalParameterList? ) { FunctionBody }
2679     *
2680     * See 13
2681     *
2682     * Parse function declaration.
2683     * @param isStatement True if for is a statement.
2684     *
2685     * @return Expression node.
2686     */
2687    private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
2688        final long functionToken = token;
2689        final int  functionLine  = line;
2690        // FUNCTION is tested in caller.
2691        next();
2692
2693        IdentNode name = null;
2694
2695        if (type == IDENT || isNonStrictModeIdent()) {
2696            name = getIdent();
2697            verifyStrictIdent(name, "function name");
2698        } else if (isStatement) {
2699            // Nashorn extension: anonymous function statements.
2700            // Do not allow anonymous function statement if extensions
2701            // are now allowed. But if we are reparsing then anon function
2702            // statement is possible - because it was used as function
2703            // expression in surrounding code.
2704            if (env._no_syntax_extensions && reparsedFunction == null) {
2705                expect(IDENT);
2706            }
2707        }
2708
2709        // name is null, generate anonymous name
2710        boolean isAnonymous = false;
2711        if (name == null) {
2712            final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
2713            name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
2714            isAnonymous = true;
2715        }
2716
2717        expect(LPAREN);
2718        final List<IdentNode> parameters = formalParameterList();
2719        expect(RPAREN);
2720
2721        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters);
2722        lc.push(functionNode);
2723        Block functionBody = null;
2724        // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
2725        // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
2726        hideDefaultName();
2727        try{
2728            functionBody = functionBody(functionNode);
2729        } finally {
2730            defaultNames.pop();
2731            lc.pop(functionNode);
2732        }
2733
2734        if (isStatement) {
2735            if (topLevel || useBlockScope()) {
2736                functionNode.setFlag(FunctionNode.IS_DECLARED);
2737            } else if (isStrictMode) {
2738                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
2739            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
2740                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
2741            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
2742                warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
2743            }
2744            if (isArguments(name)) {
2745               lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
2746            }
2747        }
2748
2749        if (isAnonymous) {
2750            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
2751        }
2752
2753        final int arity = parameters.size();
2754
2755        final boolean strict = functionNode.isStrict();
2756        if (arity > 1) {
2757            final HashSet<String> parametersSet = new HashSet<>(arity);
2758
2759            for (int i = arity - 1; i >= 0; i--) {
2760                final IdentNode parameter = parameters.get(i);
2761                String parameterName = parameter.getName();
2762
2763                if (isArguments(parameterName)) {
2764                    functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2765                }
2766
2767                if (parametersSet.contains(parameterName)) {
2768                    // redefinition of parameter name
2769                    if (strict) {
2770                        throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2771                    }
2772                    // rename in non-strict mode
2773                    parameterName = functionNode.uniqueName(parameterName);
2774                    final long parameterToken = parameter.getToken();
2775                    parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2776                }
2777
2778                parametersSet.add(parameterName);
2779            }
2780        } else if (arity == 1) {
2781            if (isArguments(parameters.get(0))) {
2782                functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2783            }
2784        }
2785
2786        final FunctionNode function = createFunctionNode(
2787                functionNode,
2788                functionToken,
2789                name,
2790                parameters,
2791                FunctionNode.Kind.NORMAL,
2792                functionLine,
2793                functionBody);
2794
2795        if (isStatement) {
2796            if (isAnonymous) {
2797                appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function));
2798                return function;
2799            }
2800
2801            // mark ES6 block functions as lexically scoped
2802            final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
2803            final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
2804            if (topLevel) {
2805                functionDeclarations.add(varNode);
2806            } else if (useBlockScope()) {
2807                prependStatement(varNode); // Hoist to beginning of current block
2808            } else {
2809                appendStatement(varNode);
2810            }
2811        }
2812
2813        return function;
2814    }
2815
2816    private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
2817        final String defaultFunctionName = getDefaultFunctionName();
2818        if (isValidIdentifier(defaultFunctionName)) {
2819            if (isStatement) {
2820                // The name will be used as the LHS of a symbol assignment. We add the anonymous function
2821                // prefix to ensure that it can't clash with another variable.
2822                return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
2823            }
2824            return defaultFunctionName;
2825        }
2826        return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2827    }
2828
2829    private static boolean isValidIdentifier(final String name) {
2830        if(name == null || name.isEmpty()) {
2831            return false;
2832        }
2833        if(!Character.isJavaIdentifierStart(name.charAt(0))) {
2834            return false;
2835        }
2836        for(int i = 1; i < name.length(); ++i) {
2837            if(!Character.isJavaIdentifierPart(name.charAt(i))) {
2838                return false;
2839            }
2840        }
2841        return true;
2842    }
2843
2844    private String getDefaultFunctionName() {
2845        if(!defaultNames.isEmpty()) {
2846            final Object nameExpr = defaultNames.peek();
2847            if(nameExpr instanceof PropertyKey) {
2848                markDefaultNameUsed();
2849                return ((PropertyKey)nameExpr).getPropertyName();
2850            } else if(nameExpr instanceof AccessNode) {
2851                markDefaultNameUsed();
2852                return ((AccessNode)nameExpr).getProperty();
2853            }
2854        }
2855        return null;
2856    }
2857
2858    private void markDefaultNameUsed() {
2859        defaultNames.pop();
2860        hideDefaultName();
2861    }
2862
2863    private void hideDefaultName() {
2864        // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
2865        // from. Can't be null
2866        defaultNames.push("");
2867    }
2868
2869    /**
2870     * FormalParameterList :
2871     *      Identifier
2872     *      FormalParameterList , Identifier
2873     *
2874     * See 13
2875     *
2876     * Parse function parameter list.
2877     * @return List of parameter nodes.
2878     */
2879    private List<IdentNode> formalParameterList() {
2880        return formalParameterList(RPAREN);
2881    }
2882
2883    /**
2884     * Same as the other method of the same name - except that the end
2885     * token type expected is passed as argument to this method.
2886     *
2887     * FormalParameterList :
2888     *      Identifier
2889     *      FormalParameterList , Identifier
2890     *
2891     * See 13
2892     *
2893     * Parse function parameter list.
2894     * @return List of parameter nodes.
2895     */
2896    private List<IdentNode> formalParameterList(final TokenType endType) {
2897        // Prepare to gather parameters.
2898        final ArrayList<IdentNode> parameters = new ArrayList<>();
2899        // Track commas.
2900        boolean first = true;
2901
2902        while (type != endType) {
2903            // Comma prior to every argument except the first.
2904            if (!first) {
2905                expect(COMMARIGHT);
2906            } else {
2907                first = false;
2908            }
2909
2910            // Get and add parameter.
2911            final IdentNode ident = getIdent();
2912
2913            // ECMA 13.1 strict mode restrictions
2914            verifyStrictIdent(ident, "function parameter");
2915
2916            parameters.add(ident);
2917        }
2918
2919        parameters.trimToSize();
2920        return parameters;
2921    }
2922
2923    /**
2924     * FunctionBody :
2925     *      SourceElements?
2926     *
2927     * See 13
2928     *
2929     * Parse function body.
2930     * @return function node (body.)
2931     */
2932    private Block functionBody(final ParserContextFunctionNode functionNode) {
2933        long lastToken = 0L;
2934        ParserContextBlockNode body = null;
2935        final long bodyToken = token;
2936        Block functionBody;
2937        int bodyFinish = 0;
2938
2939        final boolean parseBody;
2940        Object endParserState = null;
2941        try {
2942            // Create a new function block.
2943            body = newBlock();
2944            assert functionNode != null;
2945            final int functionId = functionNode.getId();
2946            parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
2947            // Nashorn extension: expression closures
2948            if (!env._no_syntax_extensions && type != LBRACE) {
2949                /*
2950                 * Example:
2951                 *
2952                 * function square(x) x * x;
2953                 * print(square(3));
2954                 */
2955
2956                // just expression as function body
2957                final Expression expr = assignmentExpression(true);
2958                lastToken = previousToken;
2959                functionNode.setLastToken(previousToken);
2960                assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
2961                // EOL uses length field to store the line number
2962                final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
2963                // Only create the return node if we aren't skipping nested functions. Note that we aren't
2964                // skipping parsing of these extended functions; they're considered to be small anyway. Also,
2965                // they don't end with a single well known token, so it'd be very hard to get correctly (see
2966                // the note below for reasoning on skipping happening before instead of after RBRACE for
2967                // details).
2968                if (parseBody) {
2969                    final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
2970                    appendStatement(returnNode);
2971                }
2972            } else {
2973                expectDontAdvance(LBRACE);
2974                if (parseBody || !skipFunctionBody(functionNode)) {
2975                    next();
2976                    // Gather the function elements.
2977                    final List<Statement> prevFunctionDecls = functionDeclarations;
2978                    functionDeclarations = new ArrayList<>();
2979                    try {
2980                        sourceElements(false);
2981                        addFunctionDeclarations(functionNode);
2982                    } finally {
2983                        functionDeclarations = prevFunctionDecls;
2984                    }
2985
2986                    lastToken = token;
2987                    if (parseBody) {
2988                        // Since the lexer can read ahead and lexify some number of tokens in advance and have
2989                        // them buffered in the TokenStream, we need to produce a lexer state as it was just
2990                        // before it lexified RBRACE, and not whatever is its current (quite possibly well read
2991                        // ahead) state.
2992                        endParserState = new ParserState(Token.descPosition(token), line, linePosition);
2993
2994                        // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
2995                        // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
2996                        // state after it. The reason is that RBRACE is a well-known token that we can expect and
2997                        // will never involve us getting into a weird lexer state, and as such is a great reparse
2998                        // point. Typical example of a weird lexer state after RBRACE would be:
2999                        //     function this_is_skipped() { ... } "use strict";
3000                        // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
3001                        // of compensating for the possibility of a string literal (or similar) after RBRACE,
3002                        // we'll rather just restart parsing from this well-known, friendly token instead.
3003                    }
3004                }
3005                bodyFinish = finish;
3006                functionNode.setLastToken(token);
3007                expect(RBRACE);
3008            }
3009        } finally {
3010            restoreBlock(body);
3011        }
3012
3013        // NOTE: we can only do alterations to the function node after restoreFunctionNode.
3014
3015        if (parseBody) {
3016            functionNode.setEndParserState(endParserState);
3017        } else if (!body.getStatements().isEmpty()){
3018            // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
3019            // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
3020            // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
3021            // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
3022            // nested bodies early if we were supposed to skip 'em.
3023            body.setStatements(Collections.<Statement>emptyList());
3024        }
3025
3026        if (reparsedFunction != null) {
3027            // We restore the flags stored in the function's ScriptFunctionData that we got when we first
3028            // eagerly parsed the code. We're doing it because some flags would be set based on the
3029            // content of the function, or even content of its nested functions, most of which are normally
3030            // skipped during an on-demand compilation.
3031            final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
3032            if (data != null) {
3033                // Data can be null if when we originally parsed the file, we removed the function declaration
3034                // as it was dead code.
3035                functionNode.setFlag(data.getFunctionFlags());
3036                // This compensates for missing markEval() in case the function contains an inner function
3037                // that contains eval(), that now we didn't discover since we skipped the inner function.
3038                if (functionNode.hasNestedEval()) {
3039                    assert functionNode.hasScopeBlock();
3040                    body.setFlag(Block.NEEDS_SCOPE);
3041                }
3042            }
3043        }
3044        functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements());
3045        return functionBody;
3046    }
3047
3048    private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
3049        if (reparsedFunction == null) {
3050            // Not reparsing, so don't skip any function body.
3051            return false;
3052        }
3053        // Skip to the RBRACE of this function, and continue parsing from there.
3054        final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
3055        if (data == null) {
3056            // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
3057            // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
3058            // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
3059            return false;
3060        }
3061        final ParserState parserState = (ParserState)data.getEndParserState();
3062        assert parserState != null;
3063
3064        if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) {
3065            // RBRACE is already in the token stream, so fast forward to it
3066            for (; k < stream.last(); k++) {
3067                long nextToken = stream.get(k + 1);
3068                if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) {
3069                    token = stream.get(k);
3070                    type = Token.descType(token);
3071                    next();
3072                    assert type == RBRACE && start == parserState.position;
3073                    return true;
3074                }
3075            }
3076        }
3077
3078        stream.reset();
3079        lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
3080        line = parserState.line;
3081        linePosition = parserState.linePosition;
3082        // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
3083        // the RBRACE.
3084        type = SEMICOLON;
3085        k = -1;
3086        next();
3087
3088        return true;
3089    }
3090
3091    /**
3092     * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
3093     * for resuming parsing after skipping a function body.
3094     */
3095    private static class ParserState implements Serializable {
3096        private final int position;
3097        private final int line;
3098        private final int linePosition;
3099
3100        private static final long serialVersionUID = -2382565130754093694L;
3101
3102        ParserState(final int position, final int line, final int linePosition) {
3103            this.position = position;
3104            this.line = line;
3105            this.linePosition = linePosition;
3106        }
3107
3108        Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
3109            final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
3110            newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
3111            return newLexer;
3112        }
3113    }
3114
3115    private void printAST(final FunctionNode functionNode) {
3116        if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
3117            env.getErr().println(new ASTWriter(functionNode));
3118        }
3119
3120        if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
3121            env.getErr().println(new PrintVisitor(functionNode, true, false));
3122        }
3123    }
3124
3125    private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
3126        VarNode lastDecl = null;
3127        for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
3128            Statement decl = functionDeclarations.get(i);
3129            if (lastDecl == null && decl instanceof VarNode) {
3130                decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
3131                functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
3132            }
3133            prependStatement(decl);
3134        }
3135    }
3136
3137    private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
3138        if (earlyError) {
3139            throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
3140        }
3141        final ArrayList<Expression> args = new ArrayList<>();
3142        args.add(lhs);
3143        if (rhs == null) {
3144            args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
3145        } else {
3146            args.add(rhs);
3147        }
3148        args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
3149        return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
3150    }
3151
3152    /**
3153     * PostfixExpression :
3154     *      LeftHandSideExpression
3155     *      LeftHandSideExpression ++ // [no LineTerminator here]
3156     *      LeftHandSideExpression -- // [no LineTerminator here]
3157     *
3158     * See 11.3
3159     *
3160     * UnaryExpression :
3161     *      PostfixExpression
3162     *      delete UnaryExpression
3163     *      void UnaryExpression
3164     *      typeof UnaryExpression
3165     *      ++ UnaryExpression
3166     *      -- UnaryExpression
3167     *      + UnaryExpression
3168     *      - UnaryExpression
3169     *      ~ UnaryExpression
3170     *      ! UnaryExpression
3171     *
3172     * See 11.4
3173     *
3174     * Parse unary expression.
3175     * @return Expression node.
3176     */
3177    private Expression unaryExpression() {
3178        final int  unaryLine  = line;
3179        final long unaryToken = token;
3180
3181        switch (type) {
3182        case DELETE: {
3183            next();
3184            final Expression expr = unaryExpression();
3185            if (expr instanceof BaseNode || expr instanceof IdentNode) {
3186                return new UnaryNode(unaryToken, expr);
3187            }
3188            appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
3189            return LiteralNode.newInstance(unaryToken, finish, true);
3190        }
3191        case VOID:
3192        case TYPEOF:
3193        case ADD:
3194        case SUB:
3195        case BIT_NOT:
3196        case NOT:
3197            next();
3198            final Expression expr = unaryExpression();
3199            return new UnaryNode(unaryToken, expr);
3200
3201        case INCPREFIX:
3202        case DECPREFIX:
3203            final TokenType opType = type;
3204            next();
3205
3206            final Expression lhs = leftHandSideExpression();
3207            // ++, -- without operand..
3208            if (lhs == null) {
3209                throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3210            }
3211
3212            if (!(lhs instanceof AccessNode ||
3213                  lhs instanceof IndexNode ||
3214                  lhs instanceof IdentNode)) {
3215                return referenceError(lhs, null, env._early_lvalue_error);
3216            }
3217
3218            if (lhs instanceof IdentNode) {
3219                if (!checkIdentLValue((IdentNode)lhs)) {
3220                    return referenceError(lhs, null, false);
3221                }
3222                verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3223            }
3224
3225            return incDecExpression(unaryToken, opType, lhs, false);
3226
3227        default:
3228            break;
3229        }
3230
3231        Expression expression = leftHandSideExpression();
3232
3233        if (last != EOL) {
3234            switch (type) {
3235            case INCPREFIX:
3236            case DECPREFIX:
3237                final TokenType opType = type;
3238                final Expression lhs = expression;
3239                // ++, -- without operand..
3240                if (lhs == null) {
3241                    throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3242                }
3243
3244                if (!(lhs instanceof AccessNode ||
3245                   lhs instanceof IndexNode ||
3246                   lhs instanceof IdentNode)) {
3247                    next();
3248                    return referenceError(lhs, null, env._early_lvalue_error);
3249                }
3250                if (lhs instanceof IdentNode) {
3251                    if (!checkIdentLValue((IdentNode)lhs)) {
3252                        next();
3253                        return referenceError(lhs, null, false);
3254                    }
3255                    verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3256                }
3257                expression = incDecExpression(token, type, expression, true);
3258                next();
3259                break;
3260            default:
3261                break;
3262            }
3263        }
3264
3265        if (expression == null) {
3266            throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3267        }
3268
3269        return expression;
3270    }
3271
3272    /**
3273     * {@code
3274     * MultiplicativeExpression :
3275     *      UnaryExpression
3276     *      MultiplicativeExpression * UnaryExpression
3277     *      MultiplicativeExpression / UnaryExpression
3278     *      MultiplicativeExpression % UnaryExpression
3279     *
3280     * See 11.5
3281     *
3282     * AdditiveExpression :
3283     *      MultiplicativeExpression
3284     *      AdditiveExpression + MultiplicativeExpression
3285     *      AdditiveExpression - MultiplicativeExpression
3286     *
3287     * See 11.6
3288     *
3289     * ShiftExpression :
3290     *      AdditiveExpression
3291     *      ShiftExpression << AdditiveExpression
3292     *      ShiftExpression >> AdditiveExpression
3293     *      ShiftExpression >>> AdditiveExpression
3294     *
3295     * See 11.7
3296     *
3297     * RelationalExpression :
3298     *      ShiftExpression
3299     *      RelationalExpression < ShiftExpression
3300     *      RelationalExpression > ShiftExpression
3301     *      RelationalExpression <= ShiftExpression
3302     *      RelationalExpression >= ShiftExpression
3303     *      RelationalExpression instanceof ShiftExpression
3304     *      RelationalExpression in ShiftExpression // if !noIf
3305     *
3306     * See 11.8
3307     *
3308     *      RelationalExpression
3309     *      EqualityExpression == RelationalExpression
3310     *      EqualityExpression != RelationalExpression
3311     *      EqualityExpression === RelationalExpression
3312     *      EqualityExpression !== RelationalExpression
3313     *
3314     * See 11.9
3315     *
3316     * BitwiseANDExpression :
3317     *      EqualityExpression
3318     *      BitwiseANDExpression & EqualityExpression
3319     *
3320     * BitwiseXORExpression :
3321     *      BitwiseANDExpression
3322     *      BitwiseXORExpression ^ BitwiseANDExpression
3323     *
3324     * BitwiseORExpression :
3325     *      BitwiseXORExpression
3326     *      BitwiseORExpression | BitwiseXORExpression
3327     *
3328     * See 11.10
3329     *
3330     * LogicalANDExpression :
3331     *      BitwiseORExpression
3332     *      LogicalANDExpression && BitwiseORExpression
3333     *
3334     * LogicalORExpression :
3335     *      LogicalANDExpression
3336     *      LogicalORExpression || LogicalANDExpression
3337     *
3338     * See 11.11
3339     *
3340     * ConditionalExpression :
3341     *      LogicalORExpression
3342     *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
3343     *
3344     * See 11.12
3345     *
3346     * AssignmentExpression :
3347     *      ConditionalExpression
3348     *      LeftHandSideExpression AssignmentOperator AssignmentExpression
3349     *
3350     * AssignmentOperator :
3351     *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
3352     *
3353     * See 11.13
3354     *
3355     * Expression :
3356     *      AssignmentExpression
3357     *      Expression , AssignmentExpression
3358     *
3359     * See 11.14
3360     * }
3361     *
3362     * Parse expression.
3363     * @return Expression node.
3364     */
3365    protected Expression expression() {
3366        // This method is protected so that subclass can get details
3367        // at expression start point!
3368
3369        // Include commas in expression parsing.
3370        return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
3371    }
3372
3373    private JoinPredecessorExpression joinPredecessorExpression() {
3374        return new JoinPredecessorExpression(expression());
3375    }
3376
3377    private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
3378        // Get the precedence of the next operator.
3379        int precedence = type.getPrecedence();
3380        Expression lhs = exprLhs;
3381
3382        // While greater precedence.
3383        while (type.isOperator(noIn) && precedence >= minPrecedence) {
3384            // Capture the operator token.
3385            final long op = token;
3386
3387            if (type == TERNARY) {
3388                // Skip operator.
3389                next();
3390
3391                // Pass expression. Middle expression of a conditional expression can be a "in"
3392                // expression - even in the contexts where "in" is not permitted.
3393                final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
3394
3395                expect(COLON);
3396
3397                // Fail expression.
3398                final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3399
3400                // Build up node.
3401                lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
3402            } else {
3403                // Skip operator.
3404                next();
3405
3406                 // Get the next primary expression.
3407                Expression rhs;
3408                final boolean isAssign = Token.descType(op) == ASSIGN;
3409                if(isAssign) {
3410                    defaultNames.push(lhs);
3411                }
3412                try {
3413                    rhs = unaryExpression();
3414                    // Get precedence of next operator.
3415                    int nextPrecedence = type.getPrecedence();
3416
3417                    // Subtask greater precedence.
3418                    while (type.isOperator(noIn) &&
3419                           (nextPrecedence > precedence ||
3420                           nextPrecedence == precedence && !type.isLeftAssociative())) {
3421                        rhs = expression(rhs, nextPrecedence, noIn);
3422                        nextPrecedence = type.getPrecedence();
3423                    }
3424                } finally {
3425                    if(isAssign) {
3426                        defaultNames.pop();
3427                    }
3428                }
3429                lhs = verifyAssignment(op, lhs, rhs);
3430            }
3431
3432            precedence = type.getPrecedence();
3433        }
3434
3435        return lhs;
3436    }
3437
3438    protected Expression assignmentExpression(final boolean noIn) {
3439        // This method is protected so that subclass can get details
3440        // at assignment expression start point!
3441
3442        // Exclude commas in expression parsing.
3443        return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3444    }
3445
3446    /**
3447     * Parse an end of line.
3448     */
3449    private void endOfLine() {
3450        switch (type) {
3451        case SEMICOLON:
3452        case EOL:
3453            next();
3454            break;
3455        case RPAREN:
3456        case RBRACKET:
3457        case RBRACE:
3458        case EOF:
3459            break;
3460        default:
3461            if (last != EOL) {
3462                expect(SEMICOLON);
3463            }
3464            break;
3465        }
3466    }
3467
3468    /**
3469     * Parse untagged template literal as string concatenation.
3470     */
3471    private Expression templateLiteral() {
3472        assert type == TEMPLATE || type == TEMPLATE_HEAD;
3473        final boolean noSubstitutionTemplate = type == TEMPLATE;
3474        long lastLiteralToken = token;
3475        LiteralNode<?> literal = getLiteral();
3476        if (noSubstitutionTemplate) {
3477            return literal;
3478        }
3479
3480        Expression concat = literal;
3481        TokenType lastLiteralType;
3482        do {
3483            Expression expression = expression();
3484            if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
3485                throw error(AbstractParser.message("unterminated.template.expression"), token);
3486            }
3487            concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression);
3488            lastLiteralType = type;
3489            lastLiteralToken = token;
3490            literal = getLiteral();
3491            concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal);
3492        } while (lastLiteralType == TEMPLATE_MIDDLE);
3493        return concat;
3494    }
3495
3496    /**
3497     * Parse tagged template literal as argument list.
3498     * @return argument list for a tag function call (template object, ...substitutions)
3499     */
3500    private List<Expression> templateLiteralArgumentList() {
3501        assert type == TEMPLATE || type == TEMPLATE_HEAD;
3502        final ArrayList<Expression> argumentList = new ArrayList<>();
3503        final ArrayList<Expression> rawStrings = new ArrayList<>();
3504        final ArrayList<Expression> cookedStrings = new ArrayList<>();
3505        argumentList.add(null); // filled at the end
3506
3507        final long templateToken = token;
3508        final boolean hasSubstitutions = type == TEMPLATE_HEAD;
3509        addTemplateLiteralString(rawStrings, cookedStrings);
3510
3511        if (hasSubstitutions) {
3512            TokenType lastLiteralType;
3513            do {
3514                Expression expression = expression();
3515                if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
3516                    throw error(AbstractParser.message("unterminated.template.expression"), token);
3517                }
3518                argumentList.add(expression);
3519
3520                lastLiteralType = type;
3521                addTemplateLiteralString(rawStrings, cookedStrings);
3522            } while (lastLiteralType == TEMPLATE_MIDDLE);
3523        }
3524
3525        final LiteralNode<Expression[]> rawStringArray = LiteralNode.newInstance(templateToken, finish, rawStrings);
3526        final LiteralNode<Expression[]> cookedStringArray = LiteralNode.newInstance(templateToken, finish, cookedStrings);
3527        final RuntimeNode templateObject = new RuntimeNode(templateToken, finish, RuntimeNode.Request.GET_TEMPLATE_OBJECT, rawStringArray, cookedStringArray);
3528        argumentList.set(0, templateObject);
3529        return optimizeList(argumentList);
3530    }
3531
3532    private void addTemplateLiteralString(final ArrayList<Expression> rawStrings, final ArrayList<Expression> cookedStrings) {
3533        final long stringToken = token;
3534        final String rawString = lexer.valueOfRawString(stringToken);
3535        final String cookedString = (String) getValue();
3536        next();
3537        rawStrings.add(LiteralNode.newInstance(stringToken, finish, rawString));
3538        cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
3539    }
3540
3541    @Override
3542    public String toString() {
3543        return "'JavaScript Parsing'";
3544    }
3545
3546    private static void markEval(final ParserContext lc) {
3547        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
3548        boolean flaggedCurrentFn = false;
3549        while (iter.hasNext()) {
3550            final ParserContextFunctionNode fn = iter.next();
3551            if (!flaggedCurrentFn) {
3552                fn.setFlag(FunctionNode.HAS_EVAL);
3553                flaggedCurrentFn = true;
3554            } else {
3555                fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
3556            }
3557            final ParserContextBlockNode body = lc.getFunctionBody(fn);
3558            // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
3559            // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
3560            // this method when the parser skips a nested function.
3561            body.setFlag(Block.NEEDS_SCOPE);
3562            fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
3563        }
3564    }
3565
3566    private void prependStatement(final Statement statement) {
3567        lc.prependStatementToCurrentNode(statement);
3568    }
3569
3570    private void appendStatement(final Statement statement) {
3571        lc.appendStatementToCurrentNode(statement);
3572    }
3573}
3574