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