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