Parser.java revision 1423:c13179703f65
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, env._es6, 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, env._es6);
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, env._es6);
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 preceding
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_LEGACY:
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 OCTAL:
1967        case BINARY_NUMBER:
1968        case FLOATING:
1969        case REGEX:
1970        case XML:
1971            return getLiteral();
1972        case EXECSTRING:
1973            return execString(primaryLine, primaryToken);
1974        case FALSE:
1975            next();
1976            return LiteralNode.newInstance(primaryToken, finish, false);
1977        case TRUE:
1978            next();
1979            return LiteralNode.newInstance(primaryToken, finish, true);
1980        case NULL:
1981            next();
1982            return LiteralNode.newInstance(primaryToken, finish);
1983        case LBRACKET:
1984            return arrayLiteral();
1985        case LBRACE:
1986            return objectLiteral();
1987        case LPAREN:
1988            next();
1989
1990            final Expression expression = expression();
1991
1992            expect(RPAREN);
1993
1994            return expression;
1995
1996        default:
1997            // In this context some operator tokens mark the start of a literal.
1998            if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
1999                next();
2000                return getLiteral();
2001            }
2002            if (isNonStrictModeIdent()) {
2003                return getIdent();
2004            }
2005            break;
2006        }
2007
2008        return null;
2009    }
2010
2011    /**
2012     * Convert execString to a call to $EXEC.
2013     *
2014     * @param primaryToken Original string token.
2015     * @return callNode to $EXEC.
2016     */
2017    CallNode execString(final int primaryLine, final long primaryToken) {
2018        // Synthesize an ident to call $EXEC.
2019        final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
2020        // Skip over EXECSTRING.
2021        next();
2022        // Set up argument list for call.
2023        // Skip beginning of edit string expression.
2024        expect(LBRACE);
2025        // Add the following expression to arguments.
2026        final List<Expression> arguments = Collections.singletonList(expression());
2027        // Skip ending of edit string expression.
2028        expect(RBRACE);
2029
2030        return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
2031    }
2032
2033    /**
2034     * ArrayLiteral :
2035     *      [ Elision? ]
2036     *      [ ElementList ]
2037     *      [ ElementList , Elision? ]
2038     *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
2039     *
2040     * ElementList : Elision? AssignmentExpression
2041     *      ElementList , Elision? AssignmentExpression
2042     *
2043     * Elision :
2044     *      ,
2045     *      Elision ,
2046     *
2047     * See 12.1.4
2048     * JavaScript 1.8
2049     *
2050     * Parse array literal.
2051     * @return Expression node.
2052     */
2053    private LiteralNode<Expression[]> arrayLiteral() {
2054        // Capture LBRACKET token.
2055        final long arrayToken = token;
2056        // LBRACKET tested in caller.
2057        next();
2058
2059        // Prepare to accumulate elements.
2060        final List<Expression> elements = new ArrayList<>();
2061        // Track elisions.
2062        boolean elision = true;
2063loop:
2064        while (true) {
2065            switch (type) {
2066            case RBRACKET:
2067                next();
2068
2069                break loop;
2070
2071            case COMMARIGHT:
2072                next();
2073
2074                // If no prior expression
2075                if (elision) {
2076                    elements.add(null);
2077                }
2078
2079                elision = true;
2080
2081                break;
2082
2083            default:
2084                if (!elision) {
2085                    throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2086                }
2087                // Add expression element.
2088                final Expression expression = assignmentExpression(false);
2089
2090                if (expression != null) {
2091                    elements.add(expression);
2092                } else {
2093                    expect(RBRACKET);
2094                }
2095
2096                elision = false;
2097                break;
2098            }
2099        }
2100
2101        return LiteralNode.newInstance(arrayToken, finish, elements);
2102    }
2103
2104    /**
2105     * ObjectLiteral :
2106     *      { }
2107     *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2108     *
2109     * PropertyNameAndValueList :
2110     *      PropertyAssignment
2111     *      PropertyNameAndValueList , PropertyAssignment
2112     *
2113     * See 11.1.5
2114     *
2115     * Parse an object literal.
2116     * @return Expression node.
2117     */
2118    private ObjectNode objectLiteral() {
2119        // Capture LBRACE token.
2120        final long objectToken = token;
2121        // LBRACE tested in caller.
2122        next();
2123
2124        // Object context.
2125        // Prepare to accumulate elements.
2126        final List<PropertyNode> elements = new ArrayList<>();
2127        final Map<String, Integer> map = new HashMap<>();
2128
2129        // Create a block for the object literal.
2130        boolean commaSeen = true;
2131loop:
2132        while (true) {
2133            switch (type) {
2134                case RBRACE:
2135                    next();
2136                    break loop;
2137
2138                case COMMARIGHT:
2139                    if (commaSeen) {
2140                        throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2141                    }
2142                    next();
2143                    commaSeen = true;
2144                    break;
2145
2146                default:
2147                    if (!commaSeen) {
2148                        throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2149                    }
2150
2151                    commaSeen = false;
2152                    // Get and add the next property.
2153                    final PropertyNode property = propertyAssignment();
2154                    final String key = property.getKeyName();
2155                    final Integer existing = map.get(key);
2156
2157                    if (existing == null) {
2158                        map.put(key, elements.size());
2159                        elements.add(property);
2160                        break;
2161                    }
2162
2163                    final PropertyNode existingProperty = elements.get(existing);
2164
2165                    // ECMA section 11.1.5 Object Initialiser
2166                    // point # 4 on property assignment production
2167                    final Expression   value  = property.getValue();
2168                    final FunctionNode getter = property.getGetter();
2169                    final FunctionNode setter = property.getSetter();
2170
2171                    final Expression   prevValue  = existingProperty.getValue();
2172                    final FunctionNode prevGetter = existingProperty.getGetter();
2173                    final FunctionNode prevSetter = existingProperty.getSetter();
2174
2175                    // ECMA 11.1.5 strict mode restrictions
2176                    if (isStrictMode && value != null && prevValue != null) {
2177                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2178                    }
2179
2180                    final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
2181                    final boolean isAccessor     = getter != null     || setter != null;
2182
2183                    // data property redefined as accessor property
2184                    if (prevValue != null && isAccessor) {
2185                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2186                    }
2187
2188                    // accessor property redefined as data
2189                    if (isPrevAccessor && value != null) {
2190                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2191                    }
2192
2193                    if (isAccessor && isPrevAccessor) {
2194                        if (getter != null && prevGetter != null ||
2195                                setter != null && prevSetter != null) {
2196                            throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2197                        }
2198                    }
2199
2200                    if (value != null) {
2201                        elements.add(property);
2202                    } else if (getter != null) {
2203                        elements.set(existing, existingProperty.setGetter(getter));
2204                    } else if (setter != null) {
2205                        elements.set(existing, existingProperty.setSetter(setter));
2206                    }
2207                    break;
2208            }
2209        }
2210
2211        return new ObjectNode(objectToken, finish, elements);
2212    }
2213
2214    /**
2215     * PropertyName :
2216     *      IdentifierName
2217     *      StringLiteral
2218     *      NumericLiteral
2219     *
2220     * See 11.1.5
2221     *
2222     * @return PropertyName node
2223     */
2224    @SuppressWarnings("fallthrough")
2225    private PropertyKey propertyName() {
2226        switch (type) {
2227        case IDENT:
2228            return getIdent().setIsPropertyName();
2229        case OCTAL_LEGACY:
2230            if (isStrictMode) {
2231                throw error(AbstractParser.message("strict.no.octal"), token);
2232            }
2233        case STRING:
2234        case ESCSTRING:
2235        case DECIMAL:
2236        case HEXADECIMAL:
2237        case OCTAL:
2238        case BINARY_NUMBER:
2239        case FLOATING:
2240            return getLiteral();
2241        default:
2242            return getIdentifierName().setIsPropertyName();
2243        }
2244    }
2245
2246    /**
2247     * PropertyAssignment :
2248     *      PropertyName : AssignmentExpression
2249     *      get PropertyName ( ) { FunctionBody }
2250     *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
2251     *
2252     * PropertySetParameterList :
2253     *      Identifier
2254     *
2255     * PropertyName :
2256     *      IdentifierName
2257     *      StringLiteral
2258     *      NumericLiteral
2259     *
2260     * See 11.1.5
2261     *
2262     * Parse an object literal property.
2263     * @return Property or reference node.
2264     */
2265    private PropertyNode propertyAssignment() {
2266        // Capture firstToken.
2267        final long propertyToken = token;
2268        final int  functionLine  = line;
2269
2270        PropertyKey propertyName;
2271
2272        if (type == IDENT) {
2273            // Get IDENT.
2274            final String ident = (String)expectValue(IDENT);
2275
2276            if (type != COLON) {
2277                final long getSetToken = propertyToken;
2278
2279                switch (ident) {
2280                case "get":
2281                    final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
2282                    return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null);
2283
2284                case "set":
2285                    final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
2286                    return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode);
2287                default:
2288                    break;
2289                }
2290            }
2291
2292            propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
2293        } else {
2294            propertyName = propertyName();
2295        }
2296
2297        expect(COLON);
2298
2299        defaultNames.push(propertyName);
2300        try {
2301            return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
2302        } finally {
2303            defaultNames.pop();
2304        }
2305    }
2306
2307    private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
2308        final PropertyKey getIdent = propertyName();
2309        final String getterName = getIdent.getPropertyName();
2310        final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
2311        expect(LPAREN);
2312        expect(RPAREN);
2313
2314        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
2315        lc.push(functionNode);
2316
2317        Block functionBody;
2318
2319
2320        try {
2321            functionBody = functionBody(functionNode);
2322        } finally {
2323            lc.pop(functionNode);
2324        }
2325
2326        final FunctionNode  function = createFunctionNode(
2327                functionNode,
2328                getSetToken,
2329                getNameNode,
2330                Collections.<IdentNode>emptyList(),
2331                FunctionNode.Kind.GETTER,
2332                functionLine,
2333                functionBody);
2334
2335        return new PropertyFunction(getIdent, function);
2336    }
2337
2338    private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
2339        final PropertyKey setIdent = propertyName();
2340        final String setterName = setIdent.getPropertyName();
2341        final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
2342        expect(LPAREN);
2343        // be sloppy and allow missing setter parameter even though
2344        // spec does not permit it!
2345        final IdentNode argIdent;
2346        if (type == IDENT || isNonStrictModeIdent()) {
2347            argIdent = getIdent();
2348            verifyStrictIdent(argIdent, "setter argument");
2349        } else {
2350            argIdent = null;
2351        }
2352        expect(RPAREN);
2353        final List<IdentNode> parameters = new ArrayList<>();
2354        if (argIdent != null) {
2355            parameters.add(argIdent);
2356        }
2357
2358
2359        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
2360        lc.push(functionNode);
2361
2362        Block functionBody;
2363        try {
2364            functionBody = functionBody(functionNode);
2365        } finally {
2366            lc.pop(functionNode);
2367        }
2368
2369
2370        final FunctionNode  function = createFunctionNode(
2371                functionNode,
2372                getSetToken,
2373                setNameNode,
2374                parameters,
2375                FunctionNode.Kind.SETTER,
2376                functionLine,
2377                functionBody);
2378
2379        return new PropertyFunction(setIdent, function);
2380    }
2381
2382    private static class PropertyFunction {
2383        final PropertyKey ident;
2384        final FunctionNode functionNode;
2385
2386        PropertyFunction(final PropertyKey ident, final FunctionNode function) {
2387            this.ident = ident;
2388            this.functionNode = function;
2389        }
2390    }
2391
2392    /**
2393     * LeftHandSideExpression :
2394     *      NewExpression
2395     *      CallExpression
2396     *
2397     * CallExpression :
2398     *      MemberExpression Arguments
2399     *      CallExpression Arguments
2400     *      CallExpression [ Expression ]
2401     *      CallExpression . IdentifierName
2402     *
2403     * See 11.2
2404     *
2405     * Parse left hand side expression.
2406     * @return Expression node.
2407     */
2408    private Expression leftHandSideExpression() {
2409        int  callLine  = line;
2410        long callToken = token;
2411
2412        Expression lhs = memberExpression();
2413
2414        if (type == LPAREN) {
2415            final List<Expression> arguments = optimizeList(argumentList());
2416
2417            // Catch special functions.
2418            if (lhs instanceof IdentNode) {
2419                detectSpecialFunction((IdentNode)lhs);
2420            }
2421
2422            lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2423        }
2424
2425loop:
2426        while (true) {
2427            // Capture token.
2428            callLine  = line;
2429            callToken = token;
2430
2431            switch (type) {
2432            case LPAREN:
2433                // Get NEW or FUNCTION arguments.
2434                final List<Expression> arguments = optimizeList(argumentList());
2435
2436                // Create call node.
2437                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2438
2439                break;
2440
2441            case LBRACKET:
2442                next();
2443
2444                // Get array index.
2445                final Expression rhs = expression();
2446
2447                expect(RBRACKET);
2448
2449                // Create indexing node.
2450                lhs = new IndexNode(callToken, finish, lhs, rhs);
2451
2452                break;
2453
2454            case PERIOD:
2455                next();
2456
2457                final IdentNode property = getIdentifierName();
2458
2459                // Create property access node.
2460                lhs = new AccessNode(callToken, finish, lhs, property.getName());
2461
2462                break;
2463
2464            default:
2465                break loop;
2466            }
2467        }
2468
2469        return lhs;
2470    }
2471
2472    /**
2473     * NewExpression :
2474     *      MemberExpression
2475     *      new NewExpression
2476     *
2477     * See 11.2
2478     *
2479     * Parse new expression.
2480     * @return Expression node.
2481     */
2482    private Expression newExpression() {
2483        final long newToken = token;
2484        // NEW is tested in caller.
2485        next();
2486
2487        // Get function base.
2488        final int  callLine    = line;
2489        final Expression constructor = memberExpression();
2490        if (constructor == null) {
2491            return null;
2492        }
2493        // Get arguments.
2494        ArrayList<Expression> arguments;
2495
2496        // Allow for missing arguments.
2497        if (type == LPAREN) {
2498            arguments = argumentList();
2499        } else {
2500            arguments = new ArrayList<>();
2501        }
2502
2503        // Nashorn extension: This is to support the following interface implementation
2504        // syntax:
2505        //
2506        //     var r = new java.lang.Runnable() {
2507        //         run: function() { println("run"); }
2508        //     };
2509        //
2510        // The object literal following the "new Constructor()" expression
2511        // is passed as an additional (last) argument to the constructor.
2512        if (!env._no_syntax_extensions && type == LBRACE) {
2513            arguments.add(objectLiteral());
2514        }
2515
2516        final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
2517
2518        return new UnaryNode(newToken, callNode);
2519    }
2520
2521    /**
2522     * MemberExpression :
2523     *      PrimaryExpression
2524     *      FunctionExpression
2525     *      MemberExpression [ Expression ]
2526     *      MemberExpression . IdentifierName
2527     *      new MemberExpression Arguments
2528     *
2529     * See 11.2
2530     *
2531     * Parse member expression.
2532     * @return Expression node.
2533     */
2534    private Expression memberExpression() {
2535        // Prepare to build operation.
2536        Expression lhs;
2537
2538        switch (type) {
2539        case NEW:
2540            // Get new expression.
2541            lhs = newExpression();
2542            break;
2543
2544        case FUNCTION:
2545            // Get function expression.
2546            lhs = functionExpression(false, false);
2547            break;
2548
2549        default:
2550            // Get primary expression.
2551            lhs = primaryExpression();
2552            break;
2553        }
2554
2555loop:
2556        while (true) {
2557            // Capture token.
2558            final long callToken = token;
2559
2560            switch (type) {
2561            case LBRACKET: {
2562                next();
2563
2564                // Get array index.
2565                final Expression index = expression();
2566
2567                expect(RBRACKET);
2568
2569                // Create indexing node.
2570                lhs = new IndexNode(callToken, finish, lhs, index);
2571
2572                break;
2573            }
2574            case PERIOD: {
2575                if (lhs == null) {
2576                    throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2577                }
2578
2579                next();
2580
2581                final IdentNode property = getIdentifierName();
2582
2583                // Create property access node.
2584                lhs = new AccessNode(callToken, finish, lhs, property.getName());
2585
2586                break;
2587            }
2588            default:
2589                break loop;
2590            }
2591        }
2592
2593        return lhs;
2594    }
2595
2596    /**
2597     * Arguments :
2598     *      ( )
2599     *      ( ArgumentList )
2600     *
2601     * ArgumentList :
2602     *      AssignmentExpression
2603     *      ArgumentList , AssignmentExpression
2604     *
2605     * See 11.2
2606     *
2607     * Parse function call arguments.
2608     * @return Argument list.
2609     */
2610    private ArrayList<Expression> argumentList() {
2611        // Prepare to accumulate list of arguments.
2612        final ArrayList<Expression> nodeList = new ArrayList<>();
2613        // LPAREN tested in caller.
2614        next();
2615
2616        // Track commas.
2617        boolean first = true;
2618
2619        while (type != RPAREN) {
2620            // Comma prior to every argument except the first.
2621            if (!first) {
2622                expect(COMMARIGHT);
2623            } else {
2624                first = false;
2625            }
2626
2627            // Get argument expression.
2628            nodeList.add(assignmentExpression(false));
2629        }
2630
2631        expect(RPAREN);
2632        return nodeList;
2633    }
2634
2635    private static <T> List<T> optimizeList(final ArrayList<T> list) {
2636        switch(list.size()) {
2637            case 0: {
2638                return Collections.emptyList();
2639            }
2640            case 1: {
2641                return Collections.singletonList(list.get(0));
2642            }
2643            default: {
2644                list.trimToSize();
2645                return list;
2646            }
2647        }
2648    }
2649
2650    /**
2651     * FunctionDeclaration :
2652     *      function Identifier ( FormalParameterList? ) { FunctionBody }
2653     *
2654     * FunctionExpression :
2655     *      function Identifier? ( FormalParameterList? ) { FunctionBody }
2656     *
2657     * See 13
2658     *
2659     * Parse function declaration.
2660     * @param isStatement True if for is a statement.
2661     *
2662     * @return Expression node.
2663     */
2664    private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
2665        final long functionToken = token;
2666        final int  functionLine  = line;
2667        // FUNCTION is tested in caller.
2668        next();
2669
2670        IdentNode name = null;
2671
2672        if (type == IDENT || isNonStrictModeIdent()) {
2673            name = getIdent();
2674            verifyStrictIdent(name, "function name");
2675        } else if (isStatement) {
2676            // Nashorn extension: anonymous function statements.
2677            // Do not allow anonymous function statement if extensions
2678            // are now allowed. But if we are reparsing then anon function
2679            // statement is possible - because it was used as function
2680            // expression in surrounding code.
2681            if (env._no_syntax_extensions && reparsedFunction == null) {
2682                expect(IDENT);
2683            }
2684        }
2685
2686        // name is null, generate anonymous name
2687        boolean isAnonymous = false;
2688        if (name == null) {
2689            final String tmpName = getDefaultValidFunctionName(functionLine, isStatement);
2690            name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
2691            isAnonymous = true;
2692        }
2693
2694        expect(LPAREN);
2695        final List<IdentNode> parameters = formalParameterList();
2696        expect(RPAREN);
2697
2698        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters);
2699        lc.push(functionNode);
2700        Block functionBody = null;
2701        // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
2702        // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
2703        hideDefaultName();
2704        try{
2705            functionBody = functionBody(functionNode);
2706        } finally {
2707            defaultNames.pop();
2708            lc.pop(functionNode);
2709        }
2710
2711        if (isStatement) {
2712            if (topLevel || useBlockScope()) {
2713                functionNode.setFlag(FunctionNode.IS_DECLARED);
2714            } else if (isStrictMode) {
2715                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
2716            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
2717                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
2718            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
2719                warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
2720            }
2721            if (isArguments(name)) {
2722               lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
2723            }
2724        }
2725
2726        if (isAnonymous) {
2727            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
2728        }
2729
2730        final int arity = parameters.size();
2731
2732        final boolean strict = functionNode.isStrict();
2733        if (arity > 1) {
2734            final HashSet<String> parametersSet = new HashSet<>(arity);
2735
2736            for (int i = arity - 1; i >= 0; i--) {
2737                final IdentNode parameter = parameters.get(i);
2738                String parameterName = parameter.getName();
2739
2740                if (isArguments(parameterName)) {
2741                    functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2742                }
2743
2744                if (parametersSet.contains(parameterName)) {
2745                    // redefinition of parameter name
2746                    if (strict) {
2747                        throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2748                    }
2749                    // rename in non-strict mode
2750                    parameterName = functionNode.uniqueName(parameterName);
2751                    final long parameterToken = parameter.getToken();
2752                    parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2753                }
2754
2755                parametersSet.add(parameterName);
2756            }
2757        } else if (arity == 1) {
2758            if (isArguments(parameters.get(0))) {
2759                functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2760            }
2761        }
2762
2763        final FunctionNode function = createFunctionNode(
2764                functionNode,
2765                functionToken,
2766                name,
2767                parameters,
2768                FunctionNode.Kind.NORMAL,
2769                functionLine,
2770                functionBody);
2771
2772        if (isStatement) {
2773            if (isAnonymous) {
2774                appendStatement(new ExpressionStatement(functionLine, functionToken, finish, function));
2775                return function;
2776            }
2777
2778            // mark ES6 block functions as lexically scoped
2779            final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
2780            final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
2781            if (topLevel) {
2782                functionDeclarations.add(varNode);
2783            } else if (useBlockScope()) {
2784                prependStatement(varNode); // Hoist to beginning of current block
2785            } else {
2786                appendStatement(varNode);
2787            }
2788        }
2789
2790        return function;
2791    }
2792
2793    private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
2794        final String defaultFunctionName = getDefaultFunctionName();
2795        if (isValidIdentifier(defaultFunctionName)) {
2796            if (isStatement) {
2797                // The name will be used as the LHS of a symbol assignment. We add the anonymous function
2798                // prefix to ensure that it can't clash with another variable.
2799                return ANON_FUNCTION_PREFIX.symbolName() + defaultFunctionName;
2800            }
2801            return defaultFunctionName;
2802        }
2803        return ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2804    }
2805
2806    private static boolean isValidIdentifier(final String name) {
2807        if(name == null || name.isEmpty()) {
2808            return false;
2809        }
2810        if(!Character.isJavaIdentifierStart(name.charAt(0))) {
2811            return false;
2812        }
2813        for(int i = 1; i < name.length(); ++i) {
2814            if(!Character.isJavaIdentifierPart(name.charAt(i))) {
2815                return false;
2816            }
2817        }
2818        return true;
2819    }
2820
2821    private String getDefaultFunctionName() {
2822        if(!defaultNames.isEmpty()) {
2823            final Object nameExpr = defaultNames.peek();
2824            if(nameExpr instanceof PropertyKey) {
2825                markDefaultNameUsed();
2826                return ((PropertyKey)nameExpr).getPropertyName();
2827            } else if(nameExpr instanceof AccessNode) {
2828                markDefaultNameUsed();
2829                return ((AccessNode)nameExpr).getProperty();
2830            }
2831        }
2832        return null;
2833    }
2834
2835    private void markDefaultNameUsed() {
2836        defaultNames.pop();
2837        hideDefaultName();
2838    }
2839
2840    private void hideDefaultName() {
2841        // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
2842        // from. Can't be null
2843        defaultNames.push("");
2844    }
2845
2846    /**
2847     * FormalParameterList :
2848     *      Identifier
2849     *      FormalParameterList , Identifier
2850     *
2851     * See 13
2852     *
2853     * Parse function parameter list.
2854     * @return List of parameter nodes.
2855     */
2856    private List<IdentNode> formalParameterList() {
2857        return formalParameterList(RPAREN);
2858    }
2859
2860    /**
2861     * Same as the other method of the same name - except that the end
2862     * token type expected is passed as argument to this method.
2863     *
2864     * FormalParameterList :
2865     *      Identifier
2866     *      FormalParameterList , Identifier
2867     *
2868     * See 13
2869     *
2870     * Parse function parameter list.
2871     * @return List of parameter nodes.
2872     */
2873    private List<IdentNode> formalParameterList(final TokenType endType) {
2874        // Prepare to gather parameters.
2875        final ArrayList<IdentNode> parameters = new ArrayList<>();
2876        // Track commas.
2877        boolean first = true;
2878
2879        while (type != endType) {
2880            // Comma prior to every argument except the first.
2881            if (!first) {
2882                expect(COMMARIGHT);
2883            } else {
2884                first = false;
2885            }
2886
2887            // Get and add parameter.
2888            final IdentNode ident = getIdent();
2889
2890            // ECMA 13.1 strict mode restrictions
2891            verifyStrictIdent(ident, "function parameter");
2892
2893            parameters.add(ident);
2894        }
2895
2896        parameters.trimToSize();
2897        return parameters;
2898    }
2899
2900    /**
2901     * FunctionBody :
2902     *      SourceElements?
2903     *
2904     * See 13
2905     *
2906     * Parse function body.
2907     * @return function node (body.)
2908     */
2909    private Block functionBody(final ParserContextFunctionNode functionNode) {
2910        long lastToken = 0L;
2911        ParserContextBlockNode body = null;
2912        final long bodyToken = token;
2913        Block functionBody;
2914        int bodyFinish = 0;
2915
2916        final boolean parseBody;
2917        Object endParserState = null;
2918        try {
2919            // Create a new function block.
2920            body = newBlock();
2921            assert functionNode != null;
2922            final int functionId = functionNode.getId();
2923            parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
2924            // Nashorn extension: expression closures
2925            if (!env._no_syntax_extensions && type != LBRACE) {
2926                /*
2927                 * Example:
2928                 *
2929                 * function square(x) x * x;
2930                 * print(square(3));
2931                 */
2932
2933                // just expression as function body
2934                final Expression expr = assignmentExpression(true);
2935                lastToken = previousToken;
2936                functionNode.setLastToken(previousToken);
2937                assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
2938                // EOL uses length field to store the line number
2939                final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
2940                // Only create the return node if we aren't skipping nested functions. Note that we aren't
2941                // skipping parsing of these extended functions; they're considered to be small anyway. Also,
2942                // they don't end with a single well known token, so it'd be very hard to get correctly (see
2943                // the note below for reasoning on skipping happening before instead of after RBRACE for
2944                // details).
2945                if (parseBody) {
2946                    final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
2947                    appendStatement(returnNode);
2948                }
2949            } else {
2950                expectDontAdvance(LBRACE);
2951                if (parseBody || !skipFunctionBody(functionNode)) {
2952                    next();
2953                    // Gather the function elements.
2954                    final List<Statement> prevFunctionDecls = functionDeclarations;
2955                    functionDeclarations = new ArrayList<>();
2956                    try {
2957                        sourceElements(false);
2958                        addFunctionDeclarations(functionNode);
2959                    } finally {
2960                        functionDeclarations = prevFunctionDecls;
2961                    }
2962
2963                    lastToken = token;
2964                    if (parseBody) {
2965                        // Since the lexer can read ahead and lexify some number of tokens in advance and have
2966                        // them buffered in the TokenStream, we need to produce a lexer state as it was just
2967                        // before it lexified RBRACE, and not whatever is its current (quite possibly well read
2968                        // ahead) state.
2969                        endParserState = new ParserState(Token.descPosition(token), line, linePosition);
2970
2971                        // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
2972                        // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
2973                        // state after it. The reason is that RBRACE is a well-known token that we can expect and
2974                        // will never involve us getting into a weird lexer state, and as such is a great reparse
2975                        // point. Typical example of a weird lexer state after RBRACE would be:
2976                        //     function this_is_skipped() { ... } "use strict";
2977                        // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
2978                        // of compensating for the possibility of a string literal (or similar) after RBRACE,
2979                        // we'll rather just restart parsing from this well-known, friendly token instead.
2980                    }
2981                }
2982                bodyFinish = finish;
2983                functionNode.setLastToken(token);
2984                expect(RBRACE);
2985            }
2986        } finally {
2987            restoreBlock(body);
2988        }
2989
2990        // NOTE: we can only do alterations to the function node after restoreFunctionNode.
2991
2992        if (parseBody) {
2993            functionNode.setEndParserState(endParserState);
2994        } else if (!body.getStatements().isEmpty()){
2995            // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
2996            // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
2997            // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
2998            // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
2999            // nested bodies early if we were supposed to skip 'em.
3000            body.setStatements(Collections.<Statement>emptyList());
3001        }
3002
3003        if (reparsedFunction != null) {
3004            // We restore the flags stored in the function's ScriptFunctionData that we got when we first
3005            // eagerly parsed the code. We're doing it because some flags would be set based on the
3006            // content of the function, or even content of its nested functions, most of which are normally
3007            // skipped during an on-demand compilation.
3008            final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
3009            if (data != null) {
3010                // Data can be null if when we originally parsed the file, we removed the function declaration
3011                // as it was dead code.
3012                functionNode.setFlag(data.getFunctionFlags());
3013                // This compensates for missing markEval() in case the function contains an inner function
3014                // that contains eval(), that now we didn't discover since we skipped the inner function.
3015                if (functionNode.hasNestedEval()) {
3016                    assert functionNode.hasScopeBlock();
3017                    body.setFlag(Block.NEEDS_SCOPE);
3018                }
3019            }
3020        }
3021        functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements());
3022        return functionBody;
3023    }
3024
3025    private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
3026        if (reparsedFunction == null) {
3027            // Not reparsing, so don't skip any function body.
3028            return false;
3029        }
3030        // Skip to the RBRACE of this function, and continue parsing from there.
3031        final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
3032        if (data == null) {
3033            // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
3034            // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
3035            // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
3036            return false;
3037        }
3038        final ParserState parserState = (ParserState)data.getEndParserState();
3039        assert parserState != null;
3040
3041        stream.reset();
3042        lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions, env._es6);
3043        line = parserState.line;
3044        linePosition = parserState.linePosition;
3045        // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
3046        // the RBRACE.
3047        type = SEMICOLON;
3048        k = -1;
3049        next();
3050
3051        return true;
3052    }
3053
3054    /**
3055     * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
3056     * for resuming parsing after skipping a function body.
3057     */
3058    private static class ParserState implements Serializable {
3059        private final int position;
3060        private final int line;
3061        private final int linePosition;
3062
3063        private static final long serialVersionUID = -2382565130754093694L;
3064
3065        ParserState(final int position, final int line, final int linePosition) {
3066            this.position = position;
3067            this.line = line;
3068            this.linePosition = linePosition;
3069        }
3070
3071        Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting, final boolean es6) {
3072            final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, es6, true);
3073            newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
3074            return newLexer;
3075        }
3076    }
3077
3078    private void printAST(final FunctionNode functionNode) {
3079        if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
3080            env.getErr().println(new ASTWriter(functionNode));
3081        }
3082
3083        if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
3084            env.getErr().println(new PrintVisitor(functionNode, true, false));
3085        }
3086    }
3087
3088    private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
3089        VarNode lastDecl = null;
3090        for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
3091            Statement decl = functionDeclarations.get(i);
3092            if (lastDecl == null && decl instanceof VarNode) {
3093                decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
3094                functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
3095            }
3096            prependStatement(decl);
3097        }
3098    }
3099
3100    private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
3101        if (earlyError) {
3102            throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
3103        }
3104        final ArrayList<Expression> args = new ArrayList<>();
3105        args.add(lhs);
3106        if (rhs == null) {
3107            args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
3108        } else {
3109            args.add(rhs);
3110        }
3111        args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
3112        return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
3113    }
3114
3115    /**
3116     * PostfixExpression :
3117     *      LeftHandSideExpression
3118     *      LeftHandSideExpression ++ // [no LineTerminator here]
3119     *      LeftHandSideExpression -- // [no LineTerminator here]
3120     *
3121     * See 11.3
3122     *
3123     * UnaryExpression :
3124     *      PostfixExpression
3125     *      delete UnaryExpression
3126     *      void UnaryExpression
3127     *      typeof UnaryExpression
3128     *      ++ UnaryExpression
3129     *      -- UnaryExpression
3130     *      + UnaryExpression
3131     *      - UnaryExpression
3132     *      ~ UnaryExpression
3133     *      ! UnaryExpression
3134     *
3135     * See 11.4
3136     *
3137     * Parse unary expression.
3138     * @return Expression node.
3139     */
3140    private Expression unaryExpression() {
3141        final int  unaryLine  = line;
3142        final long unaryToken = token;
3143
3144        switch (type) {
3145        case DELETE: {
3146            next();
3147            final Expression expr = unaryExpression();
3148            if (expr instanceof BaseNode || expr instanceof IdentNode) {
3149                return new UnaryNode(unaryToken, expr);
3150            }
3151            appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
3152            return LiteralNode.newInstance(unaryToken, finish, true);
3153        }
3154        case VOID:
3155        case TYPEOF:
3156        case ADD:
3157        case SUB:
3158        case BIT_NOT:
3159        case NOT:
3160            next();
3161            final Expression expr = unaryExpression();
3162            return new UnaryNode(unaryToken, expr);
3163
3164        case INCPREFIX:
3165        case DECPREFIX:
3166            final TokenType opType = type;
3167            next();
3168
3169            final Expression lhs = leftHandSideExpression();
3170            // ++, -- without operand..
3171            if (lhs == null) {
3172                throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3173            }
3174
3175            if (!(lhs instanceof AccessNode ||
3176                  lhs instanceof IndexNode ||
3177                  lhs instanceof IdentNode)) {
3178                return referenceError(lhs, null, env._early_lvalue_error);
3179            }
3180
3181            if (lhs instanceof IdentNode) {
3182                if (!checkIdentLValue((IdentNode)lhs)) {
3183                    return referenceError(lhs, null, false);
3184                }
3185                verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3186            }
3187
3188            return incDecExpression(unaryToken, opType, lhs, false);
3189
3190        default:
3191            break;
3192        }
3193
3194        Expression expression = leftHandSideExpression();
3195
3196        if (last != EOL) {
3197            switch (type) {
3198            case INCPREFIX:
3199            case DECPREFIX:
3200                final TokenType opType = type;
3201                final Expression lhs = expression;
3202                // ++, -- without operand..
3203                if (lhs == null) {
3204                    throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3205                }
3206
3207                if (!(lhs instanceof AccessNode ||
3208                   lhs instanceof IndexNode ||
3209                   lhs instanceof IdentNode)) {
3210                    next();
3211                    return referenceError(lhs, null, env._early_lvalue_error);
3212                }
3213                if (lhs instanceof IdentNode) {
3214                    if (!checkIdentLValue((IdentNode)lhs)) {
3215                        next();
3216                        return referenceError(lhs, null, false);
3217                    }
3218                    verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3219                }
3220                expression = incDecExpression(token, type, expression, true);
3221                next();
3222                break;
3223            default:
3224                break;
3225            }
3226        }
3227
3228        if (expression == null) {
3229            throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3230        }
3231
3232        return expression;
3233    }
3234
3235    /**
3236     * {@code
3237     * MultiplicativeExpression :
3238     *      UnaryExpression
3239     *      MultiplicativeExpression * UnaryExpression
3240     *      MultiplicativeExpression / UnaryExpression
3241     *      MultiplicativeExpression % UnaryExpression
3242     *
3243     * See 11.5
3244     *
3245     * AdditiveExpression :
3246     *      MultiplicativeExpression
3247     *      AdditiveExpression + MultiplicativeExpression
3248     *      AdditiveExpression - MultiplicativeExpression
3249     *
3250     * See 11.6
3251     *
3252     * ShiftExpression :
3253     *      AdditiveExpression
3254     *      ShiftExpression << AdditiveExpression
3255     *      ShiftExpression >> AdditiveExpression
3256     *      ShiftExpression >>> AdditiveExpression
3257     *
3258     * See 11.7
3259     *
3260     * RelationalExpression :
3261     *      ShiftExpression
3262     *      RelationalExpression < ShiftExpression
3263     *      RelationalExpression > ShiftExpression
3264     *      RelationalExpression <= ShiftExpression
3265     *      RelationalExpression >= ShiftExpression
3266     *      RelationalExpression instanceof ShiftExpression
3267     *      RelationalExpression in ShiftExpression // if !noIf
3268     *
3269     * See 11.8
3270     *
3271     *      RelationalExpression
3272     *      EqualityExpression == RelationalExpression
3273     *      EqualityExpression != RelationalExpression
3274     *      EqualityExpression === RelationalExpression
3275     *      EqualityExpression !== RelationalExpression
3276     *
3277     * See 11.9
3278     *
3279     * BitwiseANDExpression :
3280     *      EqualityExpression
3281     *      BitwiseANDExpression & EqualityExpression
3282     *
3283     * BitwiseXORExpression :
3284     *      BitwiseANDExpression
3285     *      BitwiseXORExpression ^ BitwiseANDExpression
3286     *
3287     * BitwiseORExpression :
3288     *      BitwiseXORExpression
3289     *      BitwiseORExpression | BitwiseXORExpression
3290     *
3291     * See 11.10
3292     *
3293     * LogicalANDExpression :
3294     *      BitwiseORExpression
3295     *      LogicalANDExpression && BitwiseORExpression
3296     *
3297     * LogicalORExpression :
3298     *      LogicalANDExpression
3299     *      LogicalORExpression || LogicalANDExpression
3300     *
3301     * See 11.11
3302     *
3303     * ConditionalExpression :
3304     *      LogicalORExpression
3305     *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
3306     *
3307     * See 11.12
3308     *
3309     * AssignmentExpression :
3310     *      ConditionalExpression
3311     *      LeftHandSideExpression AssignmentOperator AssignmentExpression
3312     *
3313     * AssignmentOperator :
3314     *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
3315     *
3316     * See 11.13
3317     *
3318     * Expression :
3319     *      AssignmentExpression
3320     *      Expression , AssignmentExpression
3321     *
3322     * See 11.14
3323     * }
3324     *
3325     * Parse expression.
3326     * @return Expression node.
3327     */
3328    protected Expression expression() {
3329        // This method is protected so that subclass can get details
3330        // at expression start point!
3331
3332        // Include commas in expression parsing.
3333        return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
3334    }
3335
3336    private JoinPredecessorExpression joinPredecessorExpression() {
3337        return new JoinPredecessorExpression(expression());
3338    }
3339
3340    private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
3341        // Get the precedence of the next operator.
3342        int precedence = type.getPrecedence();
3343        Expression lhs = exprLhs;
3344
3345        // While greater precedence.
3346        while (type.isOperator(noIn) && precedence >= minPrecedence) {
3347            // Capture the operator token.
3348            final long op = token;
3349
3350            if (type == TERNARY) {
3351                // Skip operator.
3352                next();
3353
3354                // Pass expression. Middle expression of a conditional expression can be a "in"
3355                // expression - even in the contexts where "in" is not permitted.
3356                final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
3357
3358                expect(COLON);
3359
3360                // Fail expression.
3361                final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3362
3363                // Build up node.
3364                lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
3365            } else {
3366                // Skip operator.
3367                next();
3368
3369                 // Get the next primary expression.
3370                Expression rhs;
3371                final boolean isAssign = Token.descType(op) == ASSIGN;
3372                if(isAssign) {
3373                    defaultNames.push(lhs);
3374                }
3375                try {
3376                    rhs = unaryExpression();
3377                    // Get precedence of next operator.
3378                    int nextPrecedence = type.getPrecedence();
3379
3380                    // Subtask greater precedence.
3381                    while (type.isOperator(noIn) &&
3382                           (nextPrecedence > precedence ||
3383                           nextPrecedence == precedence && !type.isLeftAssociative())) {
3384                        rhs = expression(rhs, nextPrecedence, noIn);
3385                        nextPrecedence = type.getPrecedence();
3386                    }
3387                } finally {
3388                    if(isAssign) {
3389                        defaultNames.pop();
3390                    }
3391                }
3392                lhs = verifyAssignment(op, lhs, rhs);
3393            }
3394
3395            precedence = type.getPrecedence();
3396        }
3397
3398        return lhs;
3399    }
3400
3401    protected Expression assignmentExpression(final boolean noIn) {
3402        // This method is protected so that subclass can get details
3403        // at assignment expression start point!
3404
3405        // Exclude commas in expression parsing.
3406        return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3407    }
3408
3409    /**
3410     * Parse an end of line.
3411     */
3412    private void endOfLine() {
3413        switch (type) {
3414        case SEMICOLON:
3415        case EOL:
3416            next();
3417            break;
3418        case RPAREN:
3419        case RBRACKET:
3420        case RBRACE:
3421        case EOF:
3422            break;
3423        default:
3424            if (last != EOL) {
3425                expect(SEMICOLON);
3426            }
3427            break;
3428        }
3429    }
3430
3431    @Override
3432    public String toString() {
3433        return "'JavaScript Parsing'";
3434    }
3435
3436    private static void markEval(final ParserContext lc) {
3437        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
3438        boolean flaggedCurrentFn = false;
3439        while (iter.hasNext()) {
3440            final ParserContextFunctionNode fn = iter.next();
3441            if (!flaggedCurrentFn) {
3442                fn.setFlag(FunctionNode.HAS_EVAL);
3443                flaggedCurrentFn = true;
3444            } else {
3445                fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
3446            }
3447            final ParserContextBlockNode body = lc.getFunctionBody(fn);
3448            // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
3449            // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
3450            // this method when the parser skips a nested function.
3451            body.setFlag(Block.NEEDS_SCOPE);
3452            fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
3453        }
3454    }
3455
3456    private void prependStatement(final Statement statement) {
3457        lc.prependStatementToCurrentNode(statement);
3458    }
3459
3460    private void appendStatement(final Statement statement) {
3461        lc.appendStatementToCurrentNode(statement);
3462    }
3463}
3464