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