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