Parser.java revision 1118:e26843ca558b
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        final Block functionBody = functionBody(functionNode);
2295
2296        lc.pop(functionNode);
2297
2298        final FunctionNode  function = createFunctionNode(
2299                functionNode,
2300                getSetToken,
2301                getNameNode,
2302                Collections.<IdentNode>emptyList(),
2303                FunctionNode.Kind.GETTER,
2304                functionLine,
2305                functionBody);
2306
2307        return new PropertyFunction(getIdent, function);
2308    }
2309
2310    private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
2311        final PropertyKey setIdent = propertyName();
2312        final String setterName = setIdent.getPropertyName();
2313        final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
2314        expect(LPAREN);
2315        // be sloppy and allow missing setter parameter even though
2316        // spec does not permit it!
2317        final IdentNode argIdent;
2318        if (type == IDENT || isNonStrictModeIdent()) {
2319            argIdent = getIdent();
2320            verifyStrictIdent(argIdent, "setter argument");
2321        } else {
2322            argIdent = null;
2323        }
2324        expect(RPAREN);
2325        final List<IdentNode> parameters = new ArrayList<>();
2326        if (argIdent != null) {
2327            parameters.add(argIdent);
2328        }
2329
2330
2331        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
2332        lc.push(functionNode);
2333
2334        final Block functionBody = functionBody(functionNode);
2335
2336        lc.pop(functionNode);
2337
2338        final FunctionNode  function = createFunctionNode(
2339                functionNode,
2340                getSetToken,
2341                setNameNode,
2342                parameters,
2343                FunctionNode.Kind.SETTER,
2344                functionLine,
2345                functionBody);
2346
2347        return new PropertyFunction(setIdent, function);
2348    }
2349
2350    private static class PropertyFunction {
2351        final PropertyKey ident;
2352        final FunctionNode functionNode;
2353
2354        PropertyFunction(final PropertyKey ident, final FunctionNode function) {
2355            this.ident = ident;
2356            this.functionNode = function;
2357        }
2358    }
2359
2360    /**
2361     * LeftHandSideExpression :
2362     *      NewExpression
2363     *      CallExpression
2364     *
2365     * CallExpression :
2366     *      MemberExpression Arguments
2367     *      CallExpression Arguments
2368     *      CallExpression [ Expression ]
2369     *      CallExpression . IdentifierName
2370     *
2371     * See 11.2
2372     *
2373     * Parse left hand side expression.
2374     * @return Expression node.
2375     */
2376    private Expression leftHandSideExpression() {
2377        int  callLine  = line;
2378        long callToken = token;
2379
2380        Expression lhs = memberExpression();
2381
2382        if (type == LPAREN) {
2383            final List<Expression> arguments = optimizeList(argumentList());
2384
2385            // Catch special functions.
2386            if (lhs instanceof IdentNode) {
2387                detectSpecialFunction((IdentNode)lhs);
2388            }
2389
2390            lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2391        }
2392
2393loop:
2394        while (true) {
2395            // Capture token.
2396            callLine  = line;
2397            callToken = token;
2398
2399            switch (type) {
2400            case LPAREN:
2401                // Get NEW or FUNCTION arguments.
2402                final List<Expression> arguments = optimizeList(argumentList());
2403
2404                // Create call node.
2405                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2406
2407                break;
2408
2409            case LBRACKET:
2410                next();
2411
2412                // Get array index.
2413                final Expression rhs = expression();
2414
2415                expect(RBRACKET);
2416
2417                // Create indexing node.
2418                lhs = new IndexNode(callToken, finish, lhs, rhs);
2419
2420                break;
2421
2422            case PERIOD:
2423                next();
2424
2425                final IdentNode property = getIdentifierName();
2426
2427                // Create property access node.
2428                lhs = new AccessNode(callToken, finish, lhs, property.getName());
2429
2430                break;
2431
2432            default:
2433                break loop;
2434            }
2435        }
2436
2437        return lhs;
2438    }
2439
2440    /**
2441     * NewExpression :
2442     *      MemberExpression
2443     *      new NewExpression
2444     *
2445     * See 11.2
2446     *
2447     * Parse new expression.
2448     * @return Expression node.
2449     */
2450    private Expression newExpression() {
2451        final long newToken = token;
2452        // NEW is tested in caller.
2453        next();
2454
2455        // Get function base.
2456        final int  callLine    = line;
2457        final Expression constructor = memberExpression();
2458        if (constructor == null) {
2459            return null;
2460        }
2461        // Get arguments.
2462        ArrayList<Expression> arguments;
2463
2464        // Allow for missing arguments.
2465        if (type == LPAREN) {
2466            arguments = argumentList();
2467        } else {
2468            arguments = new ArrayList<>();
2469        }
2470
2471        // Nashorn extension: This is to support the following interface implementation
2472        // syntax:
2473        //
2474        //     var r = new java.lang.Runnable() {
2475        //         run: function() { println("run"); }
2476        //     };
2477        //
2478        // The object literal following the "new Constructor()" expresssion
2479        // is passed as an additional (last) argument to the constructor.
2480        if (!env._no_syntax_extensions && type == LBRACE) {
2481            arguments.add(objectLiteral());
2482        }
2483
2484        final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
2485
2486        return new UnaryNode(newToken, callNode);
2487    }
2488
2489    /**
2490     * MemberExpression :
2491     *      PrimaryExpression
2492     *      FunctionExpression
2493     *      MemberExpression [ Expression ]
2494     *      MemberExpression . IdentifierName
2495     *      new MemberExpression Arguments
2496     *
2497     * See 11.2
2498     *
2499     * Parse member expression.
2500     * @return Expression node.
2501     */
2502    private Expression memberExpression() {
2503        // Prepare to build operation.
2504        Expression lhs;
2505
2506        switch (type) {
2507        case NEW:
2508            // Get new expression.
2509            lhs = newExpression();
2510            break;
2511
2512        case FUNCTION:
2513            // Get function expression.
2514            lhs = functionExpression(false, false);
2515            break;
2516
2517        default:
2518            // Get primary expression.
2519            lhs = primaryExpression();
2520            break;
2521        }
2522
2523loop:
2524        while (true) {
2525            // Capture token.
2526            final long callToken = token;
2527
2528            switch (type) {
2529            case LBRACKET:
2530                next();
2531
2532                // Get array index.
2533                final Expression index = expression();
2534
2535                expect(RBRACKET);
2536
2537                // Create indexing node.
2538                lhs = new IndexNode(callToken, finish, lhs, index);
2539
2540                break;
2541
2542            case PERIOD:
2543                if (lhs == null) {
2544                    throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2545                }
2546
2547                next();
2548
2549                final IdentNode property = getIdentifierName();
2550
2551                // Create property access node.
2552                lhs = new AccessNode(callToken, finish, lhs, property.getName());
2553
2554                break;
2555
2556            default:
2557                break loop;
2558            }
2559        }
2560
2561        return lhs;
2562    }
2563
2564    /**
2565     * Arguments :
2566     *      ( )
2567     *      ( ArgumentList )
2568     *
2569     * ArgumentList :
2570     *      AssignmentExpression
2571     *      ArgumentList , AssignmentExpression
2572     *
2573     * See 11.2
2574     *
2575     * Parse function call arguments.
2576     * @return Argument list.
2577     */
2578    private ArrayList<Expression> argumentList() {
2579        // Prepare to accumulate list of arguments.
2580        final ArrayList<Expression> nodeList = new ArrayList<>();
2581        // LPAREN tested in caller.
2582        next();
2583
2584        // Track commas.
2585        boolean first = true;
2586
2587        while (type != RPAREN) {
2588            // Comma prior to every argument except the first.
2589            if (!first) {
2590                expect(COMMARIGHT);
2591            } else {
2592                first = false;
2593            }
2594
2595            // Get argument expression.
2596            nodeList.add(assignmentExpression(false));
2597        }
2598
2599        expect(RPAREN);
2600        return nodeList;
2601    }
2602
2603    private static <T> List<T> optimizeList(final ArrayList<T> list) {
2604        switch(list.size()) {
2605            case 0: {
2606                return Collections.emptyList();
2607            }
2608            case 1: {
2609                return Collections.singletonList(list.get(0));
2610            }
2611            default: {
2612                list.trimToSize();
2613                return list;
2614            }
2615        }
2616    }
2617
2618    /**
2619     * FunctionDeclaration :
2620     *      function Identifier ( FormalParameterList? ) { FunctionBody }
2621     *
2622     * FunctionExpression :
2623     *      function Identifier? ( FormalParameterList? ) { FunctionBody }
2624     *
2625     * See 13
2626     *
2627     * Parse function declaration.
2628     * @param isStatement True if for is a statement.
2629     *
2630     * @return Expression node.
2631     */
2632    private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
2633        final long functionToken = token;
2634        final int  functionLine  = line;
2635        // FUNCTION is tested in caller.
2636        next();
2637
2638        IdentNode name = null;
2639
2640        if (type == IDENT || isNonStrictModeIdent()) {
2641            name = getIdent();
2642            verifyStrictIdent(name, "function name");
2643        } else if (isStatement) {
2644            // Nashorn extension: anonymous function statements
2645            if (env._no_syntax_extensions) {
2646                expect(IDENT);
2647            }
2648        }
2649
2650        // name is null, generate anonymous name
2651        boolean isAnonymous = false;
2652        if (name == null) {
2653            final String tmpName = getDefaultValidFunctionName(functionLine);
2654            name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
2655            isAnonymous = true;
2656        }
2657
2658        expect(LPAREN);
2659        final List<IdentNode> parameters = formalParameterList();
2660        expect(RPAREN);
2661
2662        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters);
2663        lc.push(functionNode);
2664        Block functionBody = null;
2665        try{
2666            functionBody = functionBody(functionNode);
2667        } finally {
2668            lc.pop(functionNode);
2669        }
2670
2671        if (isStatement) {
2672            if (topLevel || useBlockScope()) {
2673                functionNode.setFlag(FunctionNode.IS_DECLARED);
2674            } else if (isStrictMode) {
2675                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
2676            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
2677                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
2678            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
2679                warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
2680            }
2681            if (isArguments(name)) {
2682               lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
2683            }
2684        }
2685
2686        if (isAnonymous) {
2687            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
2688        }
2689
2690        final int arity = parameters.size();
2691
2692        final boolean strict = functionNode.isStrict();
2693        if (arity > 1) {
2694            final HashSet<String> parametersSet = new HashSet<>(arity);
2695
2696            for (int i = arity - 1; i >= 0; i--) {
2697                final IdentNode parameter = parameters.get(i);
2698                String parameterName = parameter.getName();
2699
2700                if (isArguments(parameterName)) {
2701                    functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2702                }
2703
2704                if (parametersSet.contains(parameterName)) {
2705                    // redefinition of parameter name
2706                    if (strict) {
2707                        throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2708                    }
2709                    // rename in non-strict mode
2710                    parameterName = functionNode.uniqueName(parameterName);
2711                    final long parameterToken = parameter.getToken();
2712                    parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2713                }
2714
2715                parametersSet.add(parameterName);
2716            }
2717        } else if (arity == 1) {
2718            if (isArguments(parameters.get(0))) {
2719                functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2720            }
2721        }
2722
2723        final FunctionNode function = createFunctionNode(
2724                functionNode,
2725                functionToken,
2726                name,
2727                parameters,
2728                FunctionNode.Kind.NORMAL,
2729                functionLine,
2730                functionBody);
2731
2732        if (isStatement) {
2733            // mark ES6 block functions as lexically scoped
2734            final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
2735            final VarNode varNode  = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
2736            if (topLevel) {
2737                functionDeclarations.add(varNode);
2738            } else if (useBlockScope()) {
2739                prependStatement(varNode); // Hoist to beginning of current block
2740            } else {
2741                appendStatement(varNode);
2742            }
2743        }
2744
2745        return function;
2746    }
2747
2748    private String getDefaultValidFunctionName(final int functionLine) {
2749        final String defaultFunctionName = getDefaultFunctionName();
2750        return isValidIdentifier(defaultFunctionName) ? defaultFunctionName : ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2751    }
2752
2753    private static boolean isValidIdentifier(final String name) {
2754        if(name == null || name.isEmpty()) {
2755            return false;
2756        }
2757        if(!Character.isJavaIdentifierStart(name.charAt(0))) {
2758            return false;
2759        }
2760        for(int i = 1; i < name.length(); ++i) {
2761            if(!Character.isJavaIdentifierPart(name.charAt(i))) {
2762                return false;
2763            }
2764        }
2765        return true;
2766    }
2767
2768    private String getDefaultFunctionName() {
2769        if(!defaultNames.isEmpty()) {
2770            final Object nameExpr = defaultNames.peek();
2771            if(nameExpr instanceof PropertyKey) {
2772                markDefaultNameUsed();
2773                return ((PropertyKey)nameExpr).getPropertyName();
2774            } else if(nameExpr instanceof AccessNode) {
2775                markDefaultNameUsed();
2776                return ((AccessNode)nameExpr).getProperty();
2777            }
2778        }
2779        return null;
2780    }
2781
2782    private void markDefaultNameUsed() {
2783        defaultNames.pop();
2784        // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
2785        // from. Can't be null
2786        defaultNames.push("");
2787    }
2788
2789    /**
2790     * FormalParameterList :
2791     *      Identifier
2792     *      FormalParameterList , Identifier
2793     *
2794     * See 13
2795     *
2796     * Parse function parameter list.
2797     * @return List of parameter nodes.
2798     */
2799    private List<IdentNode> formalParameterList() {
2800        return formalParameterList(RPAREN);
2801    }
2802
2803    /**
2804     * Same as the other method of the same name - except that the end
2805     * token type expected is passed as argument to this method.
2806     *
2807     * FormalParameterList :
2808     *      Identifier
2809     *      FormalParameterList , Identifier
2810     *
2811     * See 13
2812     *
2813     * Parse function parameter list.
2814     * @return List of parameter nodes.
2815     */
2816    private List<IdentNode> formalParameterList(final TokenType endType) {
2817        // Prepare to gather parameters.
2818        final ArrayList<IdentNode> parameters = new ArrayList<>();
2819        // Track commas.
2820        boolean first = true;
2821
2822        while (type != endType) {
2823            // Comma prior to every argument except the first.
2824            if (!first) {
2825                expect(COMMARIGHT);
2826            } else {
2827                first = false;
2828            }
2829
2830            // Get and add parameter.
2831            final IdentNode ident = getIdent();
2832
2833            // ECMA 13.1 strict mode restrictions
2834            verifyStrictIdent(ident, "function parameter");
2835
2836            parameters.add(ident);
2837        }
2838
2839        parameters.trimToSize();
2840        return parameters;
2841    }
2842
2843    /**
2844     * FunctionBody :
2845     *      SourceElements?
2846     *
2847     * See 13
2848     *
2849     * Parse function body.
2850     * @return function node (body.)
2851     */
2852    private Block functionBody(final ParserContextFunctionNode functionNode) {
2853        long lastToken = 0L;
2854        ParserContextBlockNode body = null;
2855        final long bodyToken = token;
2856        Block functionBody;
2857        int bodyFinish = 0;
2858
2859
2860        final boolean parseBody;
2861        Object endParserState = null;
2862        try {
2863            // Create a new function block.
2864            body = newBlock();
2865            assert functionNode != null;
2866            final int functionId = functionNode.getId();
2867            parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
2868            // Nashorn extension: expression closures
2869            if (!env._no_syntax_extensions && type != LBRACE) {
2870                /*
2871                 * Example:
2872                 *
2873                 * function square(x) x * x;
2874                 * print(square(3));
2875                 */
2876
2877                // just expression as function body
2878                final Expression expr = assignmentExpression(true);
2879                lastToken = previousToken;
2880                functionNode.setLastToken(previousToken);
2881                assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
2882                // EOL uses length field to store the line number
2883                final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
2884                // Only create the return node if we aren't skipping nested functions. Note that we aren't
2885                // skipping parsing of these extended functions; they're considered to be small anyway. Also,
2886                // they don't end with a single well known token, so it'd be very hard to get correctly (see
2887                // the note below for reasoning on skipping happening before instead of after RBRACE for
2888                // details).
2889                if (parseBody) {
2890                    final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
2891                    appendStatement(returnNode);
2892                }
2893            } else {
2894                expectDontAdvance(LBRACE);
2895                if (parseBody || !skipFunctionBody(functionNode)) {
2896                    next();
2897                    // Gather the function elements.
2898                    final List<Statement> prevFunctionDecls = functionDeclarations;
2899                    functionDeclarations = new ArrayList<>();
2900                    try {
2901                        sourceElements(false);
2902                        addFunctionDeclarations(functionNode);
2903                    } finally {
2904                        functionDeclarations = prevFunctionDecls;
2905                    }
2906
2907                    lastToken = token;
2908                    if (parseBody) {
2909                        // Since the lexer can read ahead and lexify some number of tokens in advance and have
2910                        // them buffered in the TokenStream, we need to produce a lexer state as it was just
2911                        // before it lexified RBRACE, and not whatever is its current (quite possibly well read
2912                        // ahead) state.
2913                        endParserState = new ParserState(Token.descPosition(token), line, linePosition);
2914
2915                        // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
2916                        // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
2917                        // state after it. The reason is that RBRACE is a well-known token that we can expect and
2918                        // will never involve us getting into a weird lexer state, and as such is a great reparse
2919                        // point. Typical example of a weird lexer state after RBRACE would be:
2920                        //     function this_is_skipped() { ... } "use strict";
2921                        // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
2922                        // of compensating for the possibility of a string literal (or similar) after RBRACE,
2923                        // we'll rather just restart parsing from this well-known, friendly token instead.
2924                    }
2925                }
2926                bodyFinish = finish;
2927                functionNode.setLastToken(token);
2928                expect(RBRACE);
2929            }
2930        } finally {
2931            restoreBlock(body);
2932        }
2933
2934        // NOTE: we can only do alterations to the function node after restoreFunctionNode.
2935
2936        if (parseBody) {
2937            functionNode.setEndParserState(endParserState);
2938        } else if (!body.getStatements().isEmpty()){
2939            // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
2940            // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
2941            // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
2942            // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
2943            // nested bodies early if we were supposed to skip 'em.
2944            body.setStatements(Collections.<Statement>emptyList());
2945        }
2946
2947        if (reparsedFunction != null) {
2948            // We restore the flags stored in the function's ScriptFunctionData that we got when we first
2949            // eagerly parsed the code. We're doing it because some flags would be set based on the
2950            // content of the function, or even content of its nested functions, most of which are normally
2951            // skipped during an on-demand compilation.
2952            final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
2953            if (data != null) {
2954                // Data can be null if when we originally parsed the file, we removed the function declaration
2955                // as it was dead code.
2956                functionNode.setFlag(data.getFunctionFlags());
2957                // This compensates for missing markEval() in case the function contains an inner function
2958                // that contains eval(), that now we didn't discover since we skipped the inner function.
2959                if (functionNode.hasNestedEval()) {
2960                    assert functionNode.hasScopeBlock();
2961                    body.setFlag(Block.NEEDS_SCOPE);
2962                }
2963            }
2964        }
2965        functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements());
2966        return functionBody;
2967    }
2968
2969    private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
2970        if (reparsedFunction == null) {
2971            // Not reparsing, so don't skip any function body.
2972            return false;
2973        }
2974        // Skip to the RBRACE of this function, and continue parsing from there.
2975        final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
2976        if (data == null) {
2977            // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
2978            // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
2979            // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
2980            return false;
2981        }
2982        final ParserState parserState = (ParserState)data.getEndParserState();
2983        assert parserState != null;
2984
2985        stream.reset();
2986        lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions);
2987        line = parserState.line;
2988        linePosition = parserState.linePosition;
2989        // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
2990        // the RBRACE.
2991        type = SEMICOLON;
2992        k = -1;
2993        next();
2994
2995        return true;
2996    }
2997
2998    /**
2999     * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
3000     * for resuming parsing after skipping a function body.
3001     */
3002    private static class ParserState implements Serializable {
3003        private final int position;
3004        private final int line;
3005        private final int linePosition;
3006
3007        private static final long serialVersionUID = -2382565130754093694L;
3008
3009        ParserState(final int position, final int line, final int linePosition) {
3010            this.position = position;
3011            this.line = line;
3012            this.linePosition = linePosition;
3013        }
3014
3015        Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting) {
3016            final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, true);
3017            newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
3018            return newLexer;
3019        }
3020    }
3021
3022    private void printAST(final FunctionNode functionNode) {
3023        if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
3024            env.getErr().println(new ASTWriter(functionNode));
3025        }
3026
3027        if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
3028            env.getErr().println(new PrintVisitor(functionNode, true, false));
3029        }
3030    }
3031
3032    private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
3033        VarNode lastDecl = null;
3034        for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
3035            Statement decl = functionDeclarations.get(i);
3036            if (lastDecl == null && decl instanceof VarNode) {
3037                decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
3038                functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
3039            }
3040            prependStatement(decl);
3041        }
3042    }
3043
3044    private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
3045        if (earlyError) {
3046            throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
3047        }
3048        final ArrayList<Expression> args = new ArrayList<>();
3049        args.add(lhs);
3050        if (rhs == null) {
3051            args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
3052        } else {
3053            args.add(rhs);
3054        }
3055        args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
3056        return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
3057    }
3058
3059    /*
3060     * parse LHS [a, b, ..., c].
3061     *
3062     * JavaScript 1.8.
3063     */
3064    //private Node destructureExpression() {
3065    //    return null;
3066    //}
3067
3068    /**
3069     * PostfixExpression :
3070     *      LeftHandSideExpression
3071     *      LeftHandSideExpression ++ // [no LineTerminator here]
3072     *      LeftHandSideExpression -- // [no LineTerminator here]
3073     *
3074     * See 11.3
3075     *
3076     * UnaryExpression :
3077     *      PostfixExpression
3078     *      delete UnaryExpression
3079     *      Node UnaryExpression
3080     *      typeof UnaryExpression
3081     *      ++ UnaryExpression
3082     *      -- UnaryExpression
3083     *      + UnaryExpression
3084     *      - UnaryExpression
3085     *      ~ UnaryExpression
3086     *      ! UnaryExpression
3087     *
3088     * See 11.4
3089     *
3090     * Parse unary expression.
3091     * @return Expression node.
3092     */
3093    private Expression unaryExpression() {
3094        final int  unaryLine  = line;
3095        final long unaryToken = token;
3096
3097        switch (type) {
3098        case DELETE: {
3099            next();
3100            final Expression expr = unaryExpression();
3101            if (expr instanceof BaseNode || expr instanceof IdentNode) {
3102                return new UnaryNode(unaryToken, expr);
3103            }
3104            appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
3105            return LiteralNode.newInstance(unaryToken, finish, true);
3106        }
3107        case VOID:
3108        case TYPEOF:
3109        case ADD:
3110        case SUB:
3111        case BIT_NOT:
3112        case NOT:
3113            next();
3114            final Expression expr = unaryExpression();
3115            return new UnaryNode(unaryToken, expr);
3116
3117        case INCPREFIX:
3118        case DECPREFIX:
3119            final TokenType opType = type;
3120            next();
3121
3122            final Expression lhs = leftHandSideExpression();
3123            // ++, -- without operand..
3124            if (lhs == null) {
3125                throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3126            }
3127
3128            if (!(lhs instanceof AccessNode ||
3129                  lhs instanceof IndexNode ||
3130                  lhs instanceof IdentNode)) {
3131                return referenceError(lhs, null, env._early_lvalue_error);
3132            }
3133
3134            if (lhs instanceof IdentNode) {
3135                if (!checkIdentLValue((IdentNode)lhs)) {
3136                    return referenceError(lhs, null, false);
3137                }
3138                verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3139            }
3140
3141            return incDecExpression(unaryToken, opType, lhs, false);
3142
3143        default:
3144            break;
3145        }
3146
3147        Expression expression = leftHandSideExpression();
3148
3149        if (last != EOL) {
3150            switch (type) {
3151            case INCPREFIX:
3152            case DECPREFIX:
3153                final TokenType opType = type;
3154                final Expression lhs = expression;
3155                // ++, -- without operand..
3156                if (lhs == null) {
3157                    throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3158                }
3159
3160                if (!(lhs instanceof AccessNode ||
3161                   lhs instanceof IndexNode ||
3162                   lhs instanceof IdentNode)) {
3163                    next();
3164                    return referenceError(lhs, null, env._early_lvalue_error);
3165                }
3166                if (lhs instanceof IdentNode) {
3167                    if (!checkIdentLValue((IdentNode)lhs)) {
3168                        next();
3169                        return referenceError(lhs, null, false);
3170                    }
3171                    verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3172                }
3173                expression = incDecExpression(token, type, expression, true);
3174                next();
3175                break;
3176            default:
3177                break;
3178            }
3179        }
3180
3181        if (expression == null) {
3182            throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3183        }
3184
3185        return expression;
3186    }
3187
3188    /**
3189     * MultiplicativeExpression :
3190     *      UnaryExpression
3191     *      MultiplicativeExpression * UnaryExpression
3192     *      MultiplicativeExpression / UnaryExpression
3193     *      MultiplicativeExpression % UnaryExpression
3194     *
3195     * See 11.5
3196     *
3197     * AdditiveExpression :
3198     *      MultiplicativeExpression
3199     *      AdditiveExpression + MultiplicativeExpression
3200     *      AdditiveExpression - MultiplicativeExpression
3201     *
3202     * See 11.6
3203     *
3204     * ShiftExpression :
3205     *      AdditiveExpression
3206     *      ShiftExpression << AdditiveExpression
3207     *      ShiftExpression >> AdditiveExpression
3208     *      ShiftExpression >>> AdditiveExpression
3209     *
3210     * See 11.7
3211     *
3212     * RelationalExpression :
3213     *      ShiftExpression
3214     *      RelationalExpression < ShiftExpression
3215     *      RelationalExpression > ShiftExpression
3216     *      RelationalExpression <= ShiftExpression
3217     *      RelationalExpression >= ShiftExpression
3218     *      RelationalExpression instanceof ShiftExpression
3219     *      RelationalExpression in ShiftExpression // if !noIf
3220     *
3221     * See 11.8
3222     *
3223     *      RelationalExpression
3224     *      EqualityExpression == RelationalExpression
3225     *      EqualityExpression != RelationalExpression
3226     *      EqualityExpression === RelationalExpression
3227     *      EqualityExpression !== RelationalExpression
3228     *
3229     * See 11.9
3230     *
3231     * BitwiseANDExpression :
3232     *      EqualityExpression
3233     *      BitwiseANDExpression & EqualityExpression
3234     *
3235     * BitwiseXORExpression :
3236     *      BitwiseANDExpression
3237     *      BitwiseXORExpression ^ BitwiseANDExpression
3238     *
3239     * BitwiseORExpression :
3240     *      BitwiseXORExpression
3241     *      BitwiseORExpression | BitwiseXORExpression
3242     *
3243     * See 11.10
3244     *
3245     * LogicalANDExpression :
3246     *      BitwiseORExpression
3247     *      LogicalANDExpression && BitwiseORExpression
3248     *
3249     * LogicalORExpression :
3250     *      LogicalANDExpression
3251     *      LogicalORExpression || LogicalANDExpression
3252     *
3253     * See 11.11
3254     *
3255     * ConditionalExpression :
3256     *      LogicalORExpression
3257     *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
3258     *
3259     * See 11.12
3260     *
3261     * AssignmentExpression :
3262     *      ConditionalExpression
3263     *      LeftHandSideExpression AssignmentOperator AssignmentExpression
3264     *
3265     * AssignmentOperator :
3266     *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
3267     *
3268     * See 11.13
3269     *
3270     * Expression :
3271     *      AssignmentExpression
3272     *      Expression , AssignmentExpression
3273     *
3274     * See 11.14
3275     *
3276     * Parse expression.
3277     * @return Expression node.
3278     */
3279    private Expression expression() {
3280        // TODO - Destructuring array.
3281        // Include commas in expression parsing.
3282        return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
3283    }
3284
3285    private JoinPredecessorExpression joinPredecessorExpression() {
3286        return new JoinPredecessorExpression(expression());
3287    }
3288
3289    private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
3290        // Get the precedence of the next operator.
3291        int precedence = type.getPrecedence();
3292        Expression lhs = exprLhs;
3293
3294        // While greater precedence.
3295        while (type.isOperator(noIn) && precedence >= minPrecedence) {
3296            // Capture the operator token.
3297            final long op = token;
3298
3299            if (type == TERNARY) {
3300                // Skip operator.
3301                next();
3302
3303                // Pass expression. Middle expression of a conditional expression can be a "in"
3304                // expression - even in the contexts where "in" is not permitted.
3305                final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
3306
3307                expect(COLON);
3308
3309                // Fail expression.
3310                final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3311
3312                // Build up node.
3313                lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
3314            } else {
3315                // Skip operator.
3316                next();
3317
3318                 // Get the next primary expression.
3319                Expression rhs;
3320                final boolean isAssign = Token.descType(op) == ASSIGN;
3321                if(isAssign) {
3322                    defaultNames.push(lhs);
3323                }
3324                try {
3325                    rhs = unaryExpression();
3326                    // Get precedence of next operator.
3327                    int nextPrecedence = type.getPrecedence();
3328
3329                    // Subtask greater precedence.
3330                    while (type.isOperator(noIn) &&
3331                           (nextPrecedence > precedence ||
3332                           nextPrecedence == precedence && !type.isLeftAssociative())) {
3333                        rhs = expression(rhs, nextPrecedence, noIn);
3334                        nextPrecedence = type.getPrecedence();
3335                    }
3336                } finally {
3337                    if(isAssign) {
3338                        defaultNames.pop();
3339                    }
3340                }
3341                lhs = verifyAssignment(op, lhs, rhs);
3342            }
3343
3344            precedence = type.getPrecedence();
3345        }
3346
3347        return lhs;
3348    }
3349
3350    private Expression assignmentExpression(final boolean noIn) {
3351        // TODO - Handle decompose.
3352        // Exclude commas in expression parsing.
3353        return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3354    }
3355
3356    /**
3357     * Parse an end of line.
3358     */
3359    private void endOfLine() {
3360        switch (type) {
3361        case SEMICOLON:
3362        case EOL:
3363            next();
3364            break;
3365        case RPAREN:
3366        case RBRACKET:
3367        case RBRACE:
3368        case EOF:
3369            break;
3370        default:
3371            if (last != EOL) {
3372                expect(SEMICOLON);
3373            }
3374            break;
3375        }
3376    }
3377
3378    @Override
3379    public String toString() {
3380        return "'JavaScript Parsing'";
3381    }
3382
3383    private static void markEval(final ParserContext lc) {
3384        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
3385        boolean flaggedCurrentFn = false;
3386        while (iter.hasNext()) {
3387            final ParserContextFunctionNode fn = iter.next();
3388            if (!flaggedCurrentFn) {
3389                fn.setFlag(FunctionNode.HAS_EVAL);
3390                flaggedCurrentFn = true;
3391            } else {
3392                fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
3393            }
3394            final ParserContextBlockNode body = lc.getFunctionBody(fn);
3395            // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
3396            // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
3397            // this method when the parser skips a nested function.
3398            body.setFlag(Block.NEEDS_SCOPE);
3399            fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
3400        }
3401    }
3402
3403    private void prependStatement(final Statement statement) {
3404        lc.prependStatementToCurrentNode(statement);
3405    }
3406
3407    private void appendStatement(final Statement statement) {
3408        lc.appendStatementToCurrentNode(statement);
3409    }
3410}
3411