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