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