Parser.java revision 1115:a723569d0559
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();
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);
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);
864    }
865
866    /**
867     * @param topLevel does this statement occur at the "top level" of a script or a function?
868     */
869    private void statement(final boolean topLevel, final boolean allowPropertyFunction) {
870        if (type == FUNCTION) {
871            // As per spec (ECMA section 12), function declarations as arbitrary statement
872            // is not "portable". Implementation can issue a warning or disallow the same.
873            functionExpression(true, topLevel);
874            return;
875        }
876
877        switch (type) {
878        case LBRACE:
879            block();
880            break;
881        case VAR:
882            variableStatement(type, true);
883            break;
884        case SEMICOLON:
885            emptyStatement();
886            break;
887        case IF:
888            ifStatement();
889            break;
890        case FOR:
891            forStatement();
892            break;
893        case WHILE:
894            whileStatement();
895            break;
896        case DO:
897            doStatement();
898            break;
899        case CONTINUE:
900            continueStatement();
901            break;
902        case BREAK:
903            breakStatement();
904            break;
905        case RETURN:
906            returnStatement();
907            break;
908        case YIELD:
909            yieldStatement();
910            break;
911        case WITH:
912            withStatement();
913            break;
914        case SWITCH:
915            switchStatement();
916            break;
917        case THROW:
918            throwStatement();
919            break;
920        case TRY:
921            tryStatement();
922            break;
923        case DEBUGGER:
924            debuggerStatement();
925            break;
926        case RPAREN:
927        case RBRACKET:
928        case EOF:
929            expect(SEMICOLON);
930            break;
931        default:
932            if (useBlockScope() && (type == LET || type == CONST)) {
933                variableStatement(type, true);
934                break;
935            }
936            if (env._const_as_var && type == CONST) {
937                variableStatement(TokenType.VAR, true);
938                break;
939            }
940
941            if (type == IDENT || isNonStrictModeIdent()) {
942                if (T(k + 1) == COLON) {
943                    labelStatement();
944                    return;
945                }
946                if(allowPropertyFunction) {
947                    final String ident = (String)getValue();
948                    final long propertyToken = token;
949                    final int propertyLine = line;
950                    if("get".equals(ident)) {
951                        next();
952                        addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
953                        return;
954                    } else if("set".equals(ident)) {
955                        next();
956                        addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
957                        return;
958                    }
959                }
960            }
961
962            expressionStatement();
963            break;
964        }
965    }
966
967    private void addPropertyFunctionStatement(final PropertyFunction propertyFunction) {
968        final FunctionNode fn = propertyFunction.functionNode;
969        functionDeclarations.add(new ExpressionStatement(fn.getLineNumber(), fn.getToken(), finish, fn));
970    }
971
972    /**
973     * block :
974     *      { StatementList? }
975     *
976     * see 12.1
977     *
978     * Parse a statement block.
979     */
980    private void block() {
981        appendStatement(new BlockStatement(line, getBlock(true)));
982    }
983
984    /**
985     * StatementList :
986     *      Statement
987     *      StatementList Statement
988     *
989     * See 12.1
990     *
991     * Parse a list of statements.
992     */
993    private void statementList() {
994        // Accumulate statements until end of list. */
995loop:
996        while (type != EOF) {
997            switch (type) {
998            case EOF:
999            case CASE:
1000            case DEFAULT:
1001            case RBRACE:
1002                break loop;
1003            default:
1004                break;
1005            }
1006
1007            // Get next statement.
1008            statement();
1009        }
1010    }
1011
1012    /**
1013     * Make sure that in strict mode, the identifier name used is allowed.
1014     *
1015     * @param ident         Identifier that is verified
1016     * @param contextString String used in error message to give context to the user
1017     */
1018    private void verifyStrictIdent(final IdentNode ident, final String contextString) {
1019        if (isStrictMode) {
1020            switch (ident.getName()) {
1021            case "eval":
1022            case "arguments":
1023                throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1024            default:
1025                break;
1026            }
1027
1028            if (ident.isFutureStrictName()) {
1029                throw error(AbstractParser.message("strict.name", ident.getName(), contextString), ident.getToken());
1030            }
1031        }
1032    }
1033
1034    /**
1035     * VariableStatement :
1036     *      var VariableDeclarationList ;
1037     *
1038     * VariableDeclarationList :
1039     *      VariableDeclaration
1040     *      VariableDeclarationList , VariableDeclaration
1041     *
1042     * VariableDeclaration :
1043     *      Identifier Initializer?
1044     *
1045     * Initializer :
1046     *      = AssignmentExpression
1047     *
1048     * See 12.2
1049     *
1050     * Parse a VAR statement.
1051     * @param isStatement True if a statement (not used in a FOR.)
1052     */
1053    private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement) {
1054        // VAR tested in caller.
1055        next();
1056
1057        final List<VarNode> vars = new ArrayList<>();
1058        int varFlags = VarNode.IS_STATEMENT;
1059        if (varType == LET) {
1060            varFlags |= VarNode.IS_LET;
1061        } else if (varType == CONST) {
1062            varFlags |= VarNode.IS_CONST;
1063        }
1064
1065        while (true) {
1066            // Get starting token.
1067            final int  varLine  = line;
1068            final long varToken = token;
1069            // Get name of var.
1070            final IdentNode name = getIdent();
1071            verifyStrictIdent(name, "variable name");
1072
1073            // Assume no init.
1074            Expression init = null;
1075
1076            // Look for initializer assignment.
1077            if (type == ASSIGN) {
1078                next();
1079
1080                // Get initializer expression. Suppress IN if not statement.
1081                defaultNames.push(name);
1082                try {
1083                    init = assignmentExpression(!isStatement);
1084                } finally {
1085                    defaultNames.pop();
1086                }
1087            } else if (varType == CONST) {
1088                throw error(AbstractParser.message("missing.const.assignment", name.getName()));
1089            }
1090
1091            // Allocate var node.
1092            final VarNode var = new VarNode(varLine, varToken, finish, name.setIsDeclaredHere(), init, varFlags);
1093            vars.add(var);
1094            appendStatement(var);
1095
1096            if (type != COMMARIGHT) {
1097                break;
1098            }
1099            next();
1100        }
1101
1102        // If is a statement then handle end of line.
1103        if (isStatement) {
1104            endOfLine();
1105        }
1106
1107        return vars;
1108    }
1109
1110    /**
1111     * EmptyStatement :
1112     *      ;
1113     *
1114     * See 12.3
1115     *
1116     * Parse an empty statement.
1117     */
1118    private void emptyStatement() {
1119        if (env._empty_statements) {
1120            appendStatement(new EmptyNode(line, token, Token.descPosition(token) + Token.descLength(token)));
1121        }
1122
1123        // SEMICOLON checked in caller.
1124        next();
1125    }
1126
1127    /**
1128     * ExpressionStatement :
1129     *      Expression ; // [lookahead ~( or  function )]
1130     *
1131     * See 12.4
1132     *
1133     * Parse an expression used in a statement block.
1134     */
1135    private void expressionStatement() {
1136        // Lookahead checked in caller.
1137        final int  expressionLine  = line;
1138        final long expressionToken = token;
1139
1140        // Get expression and add as statement.
1141        final Expression expression = expression();
1142
1143        ExpressionStatement expressionStatement = null;
1144        if (expression != null) {
1145            expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
1146            appendStatement(expressionStatement);
1147        } else {
1148            expect(null);
1149        }
1150
1151        endOfLine();
1152    }
1153
1154    /**
1155     * IfStatement :
1156     *      if ( Expression ) Statement else Statement
1157     *      if ( Expression ) Statement
1158     *
1159     * See 12.5
1160     *
1161     * Parse an IF statement.
1162     */
1163    private void ifStatement() {
1164        // Capture IF token.
1165        final int  ifLine  = line;
1166        final long ifToken = token;
1167         // IF tested in caller.
1168        next();
1169
1170        expect(LPAREN);
1171        final Expression test = expression();
1172        expect(RPAREN);
1173        final Block pass = getStatement();
1174
1175        Block fail = null;
1176        if (type == ELSE) {
1177            next();
1178            fail = getStatement();
1179        }
1180
1181        appendStatement(new IfNode(ifLine, ifToken, fail != null ? fail.getFinish() : pass.getFinish(), test, pass, fail));
1182    }
1183
1184    /**
1185     * ... IterationStatement:
1186     *           ...
1187     *           for ( Expression[NoIn]?; Expression? ; Expression? ) Statement
1188     *           for ( var VariableDeclarationList[NoIn]; Expression? ; Expression? ) Statement
1189     *           for ( LeftHandSideExpression in Expression ) Statement
1190     *           for ( var VariableDeclaration[NoIn] in Expression ) Statement
1191     *
1192     * See 12.6
1193     *
1194     * Parse a FOR statement.
1195     */
1196    private void forStatement() {
1197        final long forToken = token;
1198        final int forLine = line;
1199        // When ES6 for-let is enabled we create a container block to capture the LET.
1200        final int startLine = start;
1201        final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null;
1202
1203
1204        // Create FOR node, capturing FOR token.
1205        final ParserContextLoopNode forNode = new ParserContextLoopNode();
1206        lc.push(forNode);
1207        Block body = null;
1208        List<VarNode> vars = null;
1209        Expression init = null;
1210        JoinPredecessorExpression test = null;
1211        JoinPredecessorExpression modify = null;
1212
1213        int flags = 0;
1214
1215        try {
1216            // FOR tested in caller.
1217            next();
1218
1219            // Nashorn extension: for each expression.
1220            // iterate property values rather than property names.
1221            if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) {
1222                flags |= ForNode.IS_FOR_EACH;
1223                next();
1224            }
1225
1226            expect(LPAREN);
1227
1228
1229            switch (type) {
1230            case VAR:
1231                // Var statements captured in for outer block.
1232                vars = variableStatement(type, false);
1233                break;
1234            case SEMICOLON:
1235                break;
1236            default:
1237                if (useBlockScope() && (type == LET || type == CONST)) {
1238                    // LET/CONST captured in container block created above.
1239                    vars = variableStatement(type, false);
1240                    break;
1241                }
1242                if (env._const_as_var && type == CONST) {
1243                    // Var statements captured in for outer block.
1244                    vars = variableStatement(TokenType.VAR, false);
1245                    break;
1246                }
1247
1248                init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true);
1249                break;
1250            }
1251
1252            switch (type) {
1253            case SEMICOLON:
1254                // for (init; test; modify)
1255
1256                // for each (init; test; modify) is invalid
1257                if ((flags & ForNode.IS_FOR_EACH) != 0) {
1258                    throw error(AbstractParser.message("for.each.without.in"), token);
1259                }
1260
1261                expect(SEMICOLON);
1262                if (type != SEMICOLON) {
1263                    test = joinPredecessorExpression();
1264                }
1265                expect(SEMICOLON);
1266                if (type != RPAREN) {
1267                    modify = joinPredecessorExpression();
1268                }
1269                break;
1270
1271            case IN:
1272                flags |= ForNode.IS_FOR_IN;
1273                test = new JoinPredecessorExpression();
1274                if (vars != null) {
1275                    // for (var i in obj)
1276                    if (vars.size() == 1) {
1277                        init = new IdentNode(vars.get(0).getName());
1278                    } else {
1279                        // for (var i, j in obj) is invalid
1280                        throw error(AbstractParser.message("many.vars.in.for.in.loop"), vars.get(1).getToken());
1281                    }
1282
1283                } else {
1284                    // for (expr in obj)
1285                    assert init != null : "for..in init expression can not be null here";
1286
1287                    // check if initial expression is a valid L-value
1288                    if (!(init instanceof AccessNode ||
1289                          init instanceof IndexNode ||
1290                          init instanceof IdentNode)) {
1291                        throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
1292                    }
1293
1294                    if (init instanceof IdentNode) {
1295                        if (!checkIdentLValue((IdentNode)init)) {
1296                            throw error(AbstractParser.message("not.lvalue.for.in.loop"), init.getToken());
1297                        }
1298                        verifyStrictIdent((IdentNode)init, "for-in iterator");
1299                    }
1300                }
1301
1302                next();
1303
1304                // Get the collection expression.
1305                modify = joinPredecessorExpression();
1306                break;
1307
1308            default:
1309                expect(SEMICOLON);
1310                break;
1311            }
1312
1313            expect(RPAREN);
1314
1315            // Set the for body.
1316            body = getStatement();
1317        } finally {
1318            lc.pop(forNode);
1319            if (vars != null) {
1320                for (final VarNode var : vars) {
1321                    appendStatement(var);
1322                }
1323            }
1324            if (body != null) {
1325                appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
1326            }
1327            if (outer != null) {
1328                restoreBlock(outer);
1329                appendStatement(new BlockStatement(startLine, new Block(
1330                        outer.getToken(),
1331                        body.getFinish(),
1332                        outer.getStatements())));
1333            }
1334        }
1335    }
1336
1337    /**
1338     * ...IterationStatement :
1339     *           ...
1340     *           while ( Expression ) Statement
1341     *           ...
1342     *
1343     * See 12.6
1344     *
1345     * Parse while statement.
1346     */
1347    private void whileStatement() {
1348        // Capture WHILE token.
1349        final long whileToken = token;
1350        final int whileLine = line;
1351        // WHILE tested in caller.
1352        next();
1353
1354        final ParserContextLoopNode whileNode = new ParserContextLoopNode();
1355        lc.push(whileNode);
1356
1357        JoinPredecessorExpression test = null;
1358        Block body = null;
1359
1360        try {
1361            expect(LPAREN);
1362            test = joinPredecessorExpression();
1363            expect(RPAREN);
1364            body = getStatement();
1365        } finally {
1366            lc.pop(whileNode);
1367            if (body != null){
1368              appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body));
1369            }
1370        }
1371    }
1372
1373    /**
1374     * ...IterationStatement :
1375     *           ...
1376     *           do Statement while( Expression ) ;
1377     *           ...
1378     *
1379     * See 12.6
1380     *
1381     * Parse DO WHILE statement.
1382     */
1383    private void doStatement() {
1384        // Capture DO token.
1385        final long doToken = token;
1386        int doLine = 0;
1387        // DO tested in the caller.
1388        next();
1389
1390        final ParserContextLoopNode doWhileNode = new ParserContextLoopNode();
1391        lc.push(doWhileNode);
1392
1393        Block body = null;
1394        JoinPredecessorExpression test = null;
1395
1396        try {
1397           // Get DO body.
1398            body = getStatement();
1399
1400            expect(WHILE);
1401            expect(LPAREN);
1402            doLine = line;
1403            test = joinPredecessorExpression();
1404            expect(RPAREN);
1405
1406            if (type == SEMICOLON) {
1407                endOfLine();
1408            }
1409        } finally {
1410            lc.pop(doWhileNode);
1411            appendStatement(new WhileNode(doLine, doToken, finish, true, test, body));
1412        }
1413    }
1414
1415    /**
1416     * ContinueStatement :
1417     *      continue Identifier? ; // [no LineTerminator here]
1418     *
1419     * See 12.7
1420     *
1421     * Parse CONTINUE statement.
1422     */
1423    private void continueStatement() {
1424        // Capture CONTINUE token.
1425        final int  continueLine  = line;
1426        final long continueToken = token;
1427        // CONTINUE tested in caller.
1428        nextOrEOL();
1429
1430        ParserContextLabelNode labelNode = null;
1431
1432        // SEMICOLON or label.
1433        switch (type) {
1434        case RBRACE:
1435        case SEMICOLON:
1436        case EOL:
1437        case EOF:
1438            break;
1439
1440        default:
1441            final IdentNode ident = getIdent();
1442            labelNode = lc.findLabel(ident.getName());
1443
1444            if (labelNode == null) {
1445                throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1446            }
1447
1448            break;
1449        }
1450
1451        final String labelName = labelNode == null ? null : labelNode.getLabelName();
1452        final ParserContextLoopNode targetNode = lc.getContinueTo(labelName);
1453
1454        if (targetNode == null) {
1455            throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
1456        }
1457
1458        endOfLine();
1459
1460        // Construct and add CONTINUE node.
1461        appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
1462    }
1463
1464    /**
1465     * BreakStatement :
1466     *      break Identifier? ; // [no LineTerminator here]
1467     *
1468     * See 12.8
1469     *
1470     */
1471    private void breakStatement() {
1472        // Capture BREAK token.
1473        final int  breakLine  = line;
1474        final long breakToken = token;
1475        // BREAK tested in caller.
1476        nextOrEOL();
1477
1478        ParserContextLabelNode labelNode = null;
1479
1480        // SEMICOLON or label.
1481        switch (type) {
1482        case RBRACE:
1483        case SEMICOLON:
1484        case EOL:
1485        case EOF:
1486            break;
1487
1488        default:
1489            final IdentNode ident = getIdent();
1490            labelNode = lc.findLabel(ident.getName());
1491
1492            if (labelNode == null) {
1493                throw error(AbstractParser.message("undefined.label", ident.getName()), ident.getToken());
1494            }
1495
1496            break;
1497        }
1498
1499        //either an explicit label - then get its node or just a "break" - get first breakable
1500        //targetNode is what we are breaking out from.
1501        final String labelName = labelNode == null ? null : labelNode.getLabelName();
1502        final ParserContextBreakableNode targetNode = lc.getBreakable(labelName);
1503        if (targetNode == null) {
1504            throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
1505        }
1506
1507        endOfLine();
1508
1509        // Construct and add BREAK node.
1510        appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
1511    }
1512
1513    /**
1514     * ReturnStatement :
1515     *      return Expression? ; // [no LineTerminator here]
1516     *
1517     * See 12.9
1518     *
1519     * Parse RETURN statement.
1520     */
1521    private void returnStatement() {
1522        // check for return outside function
1523        if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT) {
1524            throw error(AbstractParser.message("invalid.return"));
1525        }
1526
1527        // Capture RETURN token.
1528        final int  returnLine  = line;
1529        final long returnToken = token;
1530        // RETURN tested in caller.
1531        nextOrEOL();
1532
1533        Expression expression = null;
1534
1535        // SEMICOLON or expression.
1536        switch (type) {
1537        case RBRACE:
1538        case SEMICOLON:
1539        case EOL:
1540        case EOF:
1541            break;
1542
1543        default:
1544            expression = expression();
1545            break;
1546        }
1547
1548        endOfLine();
1549
1550        // Construct and add RETURN node.
1551        appendStatement(new ReturnNode(returnLine, returnToken, finish, expression));
1552    }
1553
1554    /**
1555     * YieldStatement :
1556     *      yield Expression? ; // [no LineTerminator here]
1557     *
1558     * JavaScript 1.8
1559     *
1560     * Parse YIELD statement.
1561     */
1562    private void yieldStatement() {
1563        // Capture YIELD token.
1564        final int  yieldLine  = line;
1565        final long yieldToken = token;
1566        // YIELD tested in caller.
1567        nextOrEOL();
1568
1569        Expression expression = null;
1570
1571        // SEMICOLON or expression.
1572        switch (type) {
1573        case RBRACE:
1574        case SEMICOLON:
1575        case EOL:
1576        case EOF:
1577            break;
1578
1579        default:
1580            expression = expression();
1581            break;
1582        }
1583
1584        endOfLine();
1585
1586        // Construct and add YIELD node.
1587        appendStatement(new ReturnNode(yieldLine, yieldToken, finish, expression));
1588    }
1589
1590    /**
1591     * WithStatement :
1592     *      with ( Expression ) Statement
1593     *
1594     * See 12.10
1595     *
1596     * Parse WITH statement.
1597     */
1598    private void withStatement() {
1599        // Capture WITH token.
1600        final int  withLine  = line;
1601        final long withToken = token;
1602        // WITH tested in caller.
1603        next();
1604
1605        // ECMA 12.10.1 strict mode restrictions
1606        if (isStrictMode) {
1607            throw error(AbstractParser.message("strict.no.with"), withToken);
1608        }
1609
1610        Expression expression = null;
1611        Block body = null;
1612        try {
1613            expect(LPAREN);
1614            expression = expression();
1615            expect(RPAREN);
1616            body = getStatement();
1617        } finally {
1618            appendStatement(new WithNode(withLine, withToken, finish, expression, body));
1619        }
1620
1621    }
1622
1623    /**
1624     * SwitchStatement :
1625     *      switch ( Expression ) CaseBlock
1626     *
1627     * CaseBlock :
1628     *      { CaseClauses? }
1629     *      { CaseClauses? DefaultClause CaseClauses }
1630     *
1631     * CaseClauses :
1632     *      CaseClause
1633     *      CaseClauses CaseClause
1634     *
1635     * CaseClause :
1636     *      case Expression : StatementList?
1637     *
1638     * DefaultClause :
1639     *      default : StatementList?
1640     *
1641     * See 12.11
1642     *
1643     * Parse SWITCH statement.
1644     */
1645    private void switchStatement() {
1646        final int  switchLine  = line;
1647        final long switchToken = token;
1648        // SWITCH tested in caller.
1649        next();
1650
1651        // Create and add switch statement.
1652        final ParserContextSwitchNode switchNode= new ParserContextSwitchNode();
1653        lc.push(switchNode);
1654
1655        CaseNode defaultCase = null;
1656        // Prepare to accumulate cases.
1657        final List<CaseNode> cases = new ArrayList<>();
1658
1659        Expression expression = null;
1660
1661        try {
1662            expect(LPAREN);
1663            expression = expression();
1664            expect(RPAREN);
1665
1666            expect(LBRACE);
1667
1668
1669            while (type != RBRACE) {
1670                // Prepare for next case.
1671                Expression caseExpression = null;
1672                final long caseToken = token;
1673
1674                switch (type) {
1675                case CASE:
1676                    next();
1677                    caseExpression = expression();
1678                    break;
1679
1680                case DEFAULT:
1681                    if (defaultCase != null) {
1682                        throw error(AbstractParser.message("duplicate.default.in.switch"));
1683                    }
1684                    next();
1685                    break;
1686
1687                default:
1688                    // Force an error.
1689                    expect(CASE);
1690                    break;
1691                }
1692
1693                expect(COLON);
1694
1695                // Get CASE body.
1696                final Block statements = getBlock(false);
1697                final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
1698
1699                if (caseExpression == null) {
1700                    defaultCase = caseNode;
1701                }
1702
1703                cases.add(caseNode);
1704            }
1705
1706            next();
1707        } finally {
1708            lc.pop(switchNode);
1709            appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase));
1710        }
1711    }
1712
1713    /**
1714     * LabelledStatement :
1715     *      Identifier : Statement
1716     *
1717     * See 12.12
1718     *
1719     * Parse label statement.
1720     */
1721    private void labelStatement() {
1722        // Capture label token.
1723        final long labelToken = token;
1724        // Get label ident.
1725        final IdentNode ident = getIdent();
1726
1727        expect(COLON);
1728
1729        if (lc.findLabel(ident.getName()) != null) {
1730            throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
1731        }
1732
1733        final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName());
1734        Block body = null;
1735        try {
1736            lc.push(labelNode);
1737            body = getStatement();
1738        } finally {
1739            assert lc.peek() instanceof ParserContextLabelNode;
1740            lc.pop(labelNode);
1741            if (ident != null){
1742              appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body));
1743            }
1744        }
1745    }
1746
1747    /**
1748     * ThrowStatement :
1749     *      throw Expression ; // [no LineTerminator here]
1750     *
1751     * See 12.13
1752     *
1753     * Parse throw statement.
1754     */
1755    private void throwStatement() {
1756        // Capture THROW token.
1757        final int  throwLine  = line;
1758        final long throwToken = token;
1759        // THROW tested in caller.
1760        nextOrEOL();
1761
1762        Expression expression = null;
1763
1764        // SEMICOLON or expression.
1765        switch (type) {
1766        case RBRACE:
1767        case SEMICOLON:
1768        case EOL:
1769            break;
1770
1771        default:
1772            expression = expression();
1773            break;
1774        }
1775
1776        if (expression == null) {
1777            throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
1778        }
1779
1780        endOfLine();
1781
1782        appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
1783    }
1784
1785    /**
1786     * TryStatement :
1787     *      try Block Catch
1788     *      try Block Finally
1789     *      try Block Catch Finally
1790     *
1791     * Catch :
1792     *      catch( Identifier if Expression ) Block
1793     *      catch( Identifier ) Block
1794     *
1795     * Finally :
1796     *      finally Block
1797     *
1798     * See 12.14
1799     *
1800     * Parse TRY statement.
1801     */
1802    private void tryStatement() {
1803        // Capture TRY token.
1804        final int  tryLine  = line;
1805        final long tryToken = token;
1806        // TRY tested in caller.
1807        next();
1808
1809        // Container block needed to act as target for labeled break statements
1810        final int startLine = line;
1811        final ParserContextBlockNode outer = newBlock();
1812        // Create try.
1813
1814        try {
1815            final Block       tryBody     = getBlock(true);
1816            final List<Block> catchBlocks = new ArrayList<>();
1817
1818            while (type == CATCH) {
1819                final int  catchLine  = line;
1820                final long catchToken = token;
1821                next();
1822                expect(LPAREN);
1823                final IdentNode exception = getIdent();
1824
1825                // ECMA 12.4.1 strict mode restrictions
1826                verifyStrictIdent(exception, "catch argument");
1827
1828                // Nashorn extension: catch clause can have optional
1829                // condition. So, a single try can have more than one
1830                // catch clause each with it's own condition.
1831                final Expression ifExpression;
1832                if (!env._no_syntax_extensions && type == IF) {
1833                    next();
1834                    // Get the exception condition.
1835                    ifExpression = expression();
1836                } else {
1837                    ifExpression = null;
1838                }
1839
1840                expect(RPAREN);
1841
1842                final ParserContextBlockNode catchBlock = newBlock();
1843                try {
1844                    // Get CATCH body.
1845                    final Block catchBody = getBlock(true);
1846                    final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
1847                    appendStatement(catchNode);
1848                } finally {
1849                    restoreBlock(catchBlock);
1850                    catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags(), catchBlock.getStatements()));
1851                }
1852
1853                // If unconditional catch then should to be the end.
1854                if (ifExpression == null) {
1855                    break;
1856                }
1857            }
1858
1859            // Prepare to capture finally statement.
1860            Block finallyStatements = null;
1861
1862            if (type == FINALLY) {
1863                next();
1864                finallyStatements = getBlock(true);
1865            }
1866
1867            // Need at least one catch or a finally.
1868            if (catchBlocks.isEmpty() && finallyStatements == null) {
1869                throw error(AbstractParser.message("missing.catch.or.finally"), tryToken);
1870            }
1871
1872            final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements);
1873            // Add try.
1874            assert lc.peek() == outer;
1875            appendStatement(tryNode);
1876        } finally {
1877            restoreBlock(outer);
1878        }
1879
1880        appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags(), outer.getStatements())));
1881    }
1882
1883    /**
1884     * DebuggerStatement :
1885     *      debugger ;
1886     *
1887     * See 12.15
1888     *
1889     * Parse debugger statement.
1890     */
1891    private void  debuggerStatement() {
1892        // Capture DEBUGGER token.
1893        final int  debuggerLine  = line;
1894        final long debuggerToken = token;
1895        // DEBUGGER tested in caller.
1896        next();
1897        endOfLine();
1898        appendStatement(new ExpressionStatement(debuggerLine, debuggerToken, finish, new RuntimeNode(debuggerToken, finish, RuntimeNode.Request.DEBUGGER, Collections.<Expression>emptyList())));
1899    }
1900
1901    /**
1902     * PrimaryExpression :
1903     *      this
1904     *      Identifier
1905     *      Literal
1906     *      ArrayLiteral
1907     *      ObjectLiteral
1908     *      ( Expression )
1909     *
1910     *  See 11.1
1911     *
1912     * Parse primary expression.
1913     * @return Expression node.
1914     */
1915    @SuppressWarnings("fallthrough")
1916    private Expression primaryExpression() {
1917        // Capture first token.
1918        final int  primaryLine  = line;
1919        final long primaryToken = token;
1920
1921        switch (type) {
1922        case THIS:
1923            final String name = type.getName();
1924            next();
1925            lc.getCurrentFunction().setFlag(FunctionNode.USES_THIS);
1926            return new IdentNode(primaryToken, finish, name);
1927        case IDENT:
1928            final IdentNode ident = getIdent();
1929            if (ident == null) {
1930                break;
1931            }
1932            detectSpecialProperty(ident);
1933            return ident;
1934        case OCTAL:
1935            if (isStrictMode) {
1936               throw error(AbstractParser.message("strict.no.octal"), token);
1937            }
1938        case STRING:
1939        case ESCSTRING:
1940        case DECIMAL:
1941        case HEXADECIMAL:
1942        case FLOATING:
1943        case REGEX:
1944        case XML:
1945            return getLiteral();
1946        case EXECSTRING:
1947            return execString(primaryLine, primaryToken);
1948        case FALSE:
1949            next();
1950            return LiteralNode.newInstance(primaryToken, finish, false);
1951        case TRUE:
1952            next();
1953            return LiteralNode.newInstance(primaryToken, finish, true);
1954        case NULL:
1955            next();
1956            return LiteralNode.newInstance(primaryToken, finish);
1957        case LBRACKET:
1958            return arrayLiteral();
1959        case LBRACE:
1960            return objectLiteral();
1961        case LPAREN:
1962            next();
1963
1964            final Expression expression = expression();
1965
1966            expect(RPAREN);
1967
1968            return expression;
1969
1970        default:
1971            // In this context some operator tokens mark the start of a literal.
1972            if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
1973                next();
1974                return getLiteral();
1975            }
1976            if (isNonStrictModeIdent()) {
1977                return getIdent();
1978            }
1979            break;
1980        }
1981
1982        return null;
1983    }
1984
1985    /**
1986     * Convert execString to a call to $EXEC.
1987     *
1988     * @param primaryToken Original string token.
1989     * @return callNode to $EXEC.
1990     */
1991    CallNode execString(final int primaryLine, final long primaryToken) {
1992        // Synthesize an ident to call $EXEC.
1993        final IdentNode execIdent = new IdentNode(primaryToken, finish, ScriptingFunctions.EXEC_NAME);
1994        // Skip over EXECSTRING.
1995        next();
1996        // Set up argument list for call.
1997        // Skip beginning of edit string expression.
1998        expect(LBRACE);
1999        // Add the following expression to arguments.
2000        final List<Expression> arguments = Collections.singletonList(expression());
2001        // Skip ending of edit string expression.
2002        expect(RBRACE);
2003
2004        return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
2005    }
2006
2007    /**
2008     * ArrayLiteral :
2009     *      [ Elision? ]
2010     *      [ ElementList ]
2011     *      [ ElementList , Elision? ]
2012     *      [ expression for (LeftHandExpression in expression) ( (if ( Expression ) )? ]
2013     *
2014     * ElementList : Elision? AssignmentExpression
2015     *      ElementList , Elision? AssignmentExpression
2016     *
2017     * Elision :
2018     *      ,
2019     *      Elision ,
2020     *
2021     * See 12.1.4
2022     * JavaScript 1.8
2023     *
2024     * Parse array literal.
2025     * @return Expression node.
2026     */
2027    private LiteralNode<Expression[]> arrayLiteral() {
2028        // Capture LBRACKET token.
2029        final long arrayToken = token;
2030        // LBRACKET tested in caller.
2031        next();
2032
2033        // Prepare to accummulating elements.
2034        final List<Expression> elements = new ArrayList<>();
2035        // Track elisions.
2036        boolean elision = true;
2037loop:
2038        while (true) {
2039             switch (type) {
2040            case RBRACKET:
2041                next();
2042
2043                break loop;
2044
2045            case COMMARIGHT:
2046                next();
2047
2048                // If no prior expression
2049                if (elision) {
2050                    elements.add(null);
2051                }
2052
2053                elision = true;
2054
2055                break;
2056
2057            default:
2058                if (!elision) {
2059                    throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2060                }
2061                // Add expression element.
2062                final Expression expression = assignmentExpression(false);
2063
2064                if (expression != null) {
2065                    elements.add(expression);
2066                } else {
2067                    expect(RBRACKET);
2068                }
2069
2070                elision = false;
2071                break;
2072            }
2073        }
2074
2075        return LiteralNode.newInstance(arrayToken, finish, elements);
2076    }
2077
2078    /**
2079     * ObjectLiteral :
2080     *      { }
2081     *      { PropertyNameAndValueList } { PropertyNameAndValueList , }
2082     *
2083     * PropertyNameAndValueList :
2084     *      PropertyAssignment
2085     *      PropertyNameAndValueList , PropertyAssignment
2086     *
2087     * See 11.1.5
2088     *
2089     * Parse an object literal.
2090     * @return Expression node.
2091     */
2092    private ObjectNode objectLiteral() {
2093        // Capture LBRACE token.
2094        final long objectToken = token;
2095        // LBRACE tested in caller.
2096        next();
2097
2098        // Object context.
2099        // Prepare to accumulate elements.
2100        final List<PropertyNode> elements = new ArrayList<>();
2101        final Map<String, Integer> map = new HashMap<>();
2102
2103        // Create a block for the object literal.
2104        boolean commaSeen = true;
2105loop:
2106        while (true) {
2107            switch (type) {
2108                case RBRACE:
2109                    next();
2110                    break loop;
2111
2112                case COMMARIGHT:
2113                    if (commaSeen) {
2114                        throw error(AbstractParser.message("expected.property.id", type.getNameOrType()));
2115                    }
2116                    next();
2117                    commaSeen = true;
2118                    break;
2119
2120                default:
2121                    if (!commaSeen) {
2122                        throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
2123                    }
2124
2125                    commaSeen = false;
2126                    // Get and add the next property.
2127                    final PropertyNode property = propertyAssignment();
2128                    final String key = property.getKeyName();
2129                    final Integer existing = map.get(key);
2130
2131                    if (existing == null) {
2132                        map.put(key, elements.size());
2133                        elements.add(property);
2134                        break;
2135                    }
2136
2137                    final PropertyNode existingProperty = elements.get(existing);
2138
2139                    // ECMA section 11.1.5 Object Initialiser
2140                    // point # 4 on property assignment production
2141                    final Expression   value  = property.getValue();
2142                    final FunctionNode getter = property.getGetter();
2143                    final FunctionNode setter = property.getSetter();
2144
2145                    final Expression   prevValue  = existingProperty.getValue();
2146                    final FunctionNode prevGetter = existingProperty.getGetter();
2147                    final FunctionNode prevSetter = existingProperty.getSetter();
2148
2149                    // ECMA 11.1.5 strict mode restrictions
2150                    if (isStrictMode && value != null && prevValue != null) {
2151                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2152                    }
2153
2154                    final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
2155                    final boolean isAccessor     = getter != null     || setter != null;
2156
2157                    // data property redefined as accessor property
2158                    if (prevValue != null && isAccessor) {
2159                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2160                    }
2161
2162                    // accessor property redefined as data
2163                    if (isPrevAccessor && value != null) {
2164                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2165                    }
2166
2167                    if (isAccessor && isPrevAccessor) {
2168                        if (getter != null && prevGetter != null ||
2169                                setter != null && prevSetter != null) {
2170                            throw error(AbstractParser.message("property.redefinition", key), property.getToken());
2171                        }
2172                    }
2173
2174                    if (value != null) {
2175                        elements.add(property);
2176                    } else if (getter != null) {
2177                        elements.set(existing, existingProperty.setGetter(getter));
2178                    } else if (setter != null) {
2179                        elements.set(existing, existingProperty.setSetter(setter));
2180                    }
2181                    break;
2182            }
2183        }
2184
2185        return new ObjectNode(objectToken, finish, elements);
2186    }
2187
2188    /**
2189     * PropertyName :
2190     *      IdentifierName
2191     *      StringLiteral
2192     *      NumericLiteral
2193     *
2194     * See 11.1.5
2195     *
2196     * @return PropertyName node
2197     */
2198    @SuppressWarnings("fallthrough")
2199    private PropertyKey propertyName() {
2200        switch (type) {
2201        case IDENT:
2202            return getIdent().setIsPropertyName();
2203        case OCTAL:
2204            if (isStrictMode) {
2205                throw error(AbstractParser.message("strict.no.octal"), token);
2206            }
2207        case STRING:
2208        case ESCSTRING:
2209        case DECIMAL:
2210        case HEXADECIMAL:
2211        case FLOATING:
2212            return getLiteral();
2213        default:
2214            return getIdentifierName().setIsPropertyName();
2215        }
2216    }
2217
2218    /**
2219     * PropertyAssignment :
2220     *      PropertyName : AssignmentExpression
2221     *      get PropertyName ( ) { FunctionBody }
2222     *      set PropertyName ( PropertySetParameterList ) { FunctionBody }
2223     *
2224     * PropertySetParameterList :
2225     *      Identifier
2226     *
2227     * PropertyName :
2228     *      IdentifierName
2229     *      StringLiteral
2230     *      NumericLiteral
2231     *
2232     * See 11.1.5
2233     *
2234     * Parse an object literal property.
2235     * @return Property or reference node.
2236     */
2237    private PropertyNode propertyAssignment() {
2238        // Capture firstToken.
2239        final long propertyToken = token;
2240        final int  functionLine  = line;
2241
2242        PropertyKey propertyName;
2243
2244        if (type == IDENT) {
2245            // Get IDENT.
2246            final String ident = (String)expectValue(IDENT);
2247
2248            if (type != COLON) {
2249                final long getSetToken = propertyToken;
2250
2251                switch (ident) {
2252                case "get":
2253                    final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
2254                    return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null);
2255
2256                case "set":
2257                    final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
2258                    return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode);
2259                default:
2260                    break;
2261                }
2262            }
2263
2264            propertyName =  createIdentNode(propertyToken, finish, ident).setIsPropertyName();
2265        } else {
2266            propertyName = propertyName();
2267        }
2268
2269        expect(COLON);
2270
2271        defaultNames.push(propertyName);
2272        try {
2273            return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
2274        } finally {
2275            defaultNames.pop();
2276        }
2277    }
2278
2279    private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
2280        final PropertyKey getIdent = propertyName();
2281        final String getterName = getIdent.getPropertyName();
2282        final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
2283        expect(LPAREN);
2284        expect(RPAREN);
2285
2286        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
2287        lc.push(functionNode);
2288
2289        final Block functionBody = functionBody(functionNode);
2290
2291        lc.pop(functionNode);
2292
2293        final FunctionNode  function = createFunctionNode(
2294                functionNode,
2295                getSetToken,
2296                getNameNode,
2297                Collections.<IdentNode>emptyList(),
2298                FunctionNode.Kind.GETTER,
2299                functionLine,
2300                functionBody);
2301
2302        return new PropertyFunction(getIdent, function);
2303    }
2304
2305    private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
2306        final PropertyKey setIdent = propertyName();
2307        final String setterName = setIdent.getPropertyName();
2308        final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
2309        expect(LPAREN);
2310        // be sloppy and allow missing setter parameter even though
2311        // spec does not permit it!
2312        final IdentNode argIdent;
2313        if (type == IDENT || isNonStrictModeIdent()) {
2314            argIdent = getIdent();
2315            verifyStrictIdent(argIdent, "setter argument");
2316        } else {
2317            argIdent = null;
2318        }
2319        expect(RPAREN);
2320        final List<IdentNode> parameters = new ArrayList<>();
2321        if (argIdent != null) {
2322            parameters.add(argIdent);
2323        }
2324
2325
2326        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
2327        lc.push(functionNode);
2328
2329        final Block functionBody = functionBody(functionNode);
2330
2331        lc.pop(functionNode);
2332
2333        final FunctionNode  function = createFunctionNode(
2334                functionNode,
2335                getSetToken,
2336                setNameNode,
2337                parameters,
2338                FunctionNode.Kind.SETTER,
2339                functionLine,
2340                functionBody);
2341
2342        return new PropertyFunction(setIdent, function);
2343    }
2344
2345    private static class PropertyFunction {
2346        final PropertyKey ident;
2347        final FunctionNode functionNode;
2348
2349        PropertyFunction(final PropertyKey ident, final FunctionNode function) {
2350            this.ident = ident;
2351            this.functionNode = function;
2352        }
2353    }
2354
2355    /**
2356     * LeftHandSideExpression :
2357     *      NewExpression
2358     *      CallExpression
2359     *
2360     * CallExpression :
2361     *      MemberExpression Arguments
2362     *      CallExpression Arguments
2363     *      CallExpression [ Expression ]
2364     *      CallExpression . IdentifierName
2365     *
2366     * See 11.2
2367     *
2368     * Parse left hand side expression.
2369     * @return Expression node.
2370     */
2371    private Expression leftHandSideExpression() {
2372        int  callLine  = line;
2373        long callToken = token;
2374
2375        Expression lhs = memberExpression();
2376
2377        if (type == LPAREN) {
2378            final List<Expression> arguments = optimizeList(argumentList());
2379
2380            // Catch special functions.
2381            if (lhs instanceof IdentNode) {
2382                detectSpecialFunction((IdentNode)lhs);
2383            }
2384
2385            lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2386        }
2387
2388loop:
2389        while (true) {
2390            // Capture token.
2391            callLine  = line;
2392            callToken = token;
2393
2394            switch (type) {
2395            case LPAREN:
2396                // Get NEW or FUNCTION arguments.
2397                final List<Expression> arguments = optimizeList(argumentList());
2398
2399                // Create call node.
2400                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
2401
2402                break;
2403
2404            case LBRACKET:
2405                next();
2406
2407                // Get array index.
2408                final Expression rhs = expression();
2409
2410                expect(RBRACKET);
2411
2412                // Create indexing node.
2413                lhs = new IndexNode(callToken, finish, lhs, rhs);
2414
2415                break;
2416
2417            case PERIOD:
2418                next();
2419
2420                final IdentNode property = getIdentifierName();
2421
2422                // Create property access node.
2423                lhs = new AccessNode(callToken, finish, lhs, property.getName());
2424
2425                break;
2426
2427            default:
2428                break loop;
2429            }
2430        }
2431
2432        return lhs;
2433    }
2434
2435    /**
2436     * NewExpression :
2437     *      MemberExpression
2438     *      new NewExpression
2439     *
2440     * See 11.2
2441     *
2442     * Parse new expression.
2443     * @return Expression node.
2444     */
2445    private Expression newExpression() {
2446        final long newToken = token;
2447        // NEW is tested in caller.
2448        next();
2449
2450        // Get function base.
2451        final int  callLine    = line;
2452        final Expression constructor = memberExpression();
2453        if (constructor == null) {
2454            return null;
2455        }
2456        // Get arguments.
2457        ArrayList<Expression> arguments;
2458
2459        // Allow for missing arguments.
2460        if (type == LPAREN) {
2461            arguments = argumentList();
2462        } else {
2463            arguments = new ArrayList<>();
2464        }
2465
2466        // Nashorn extension: This is to support the following interface implementation
2467        // syntax:
2468        //
2469        //     var r = new java.lang.Runnable() {
2470        //         run: function() { println("run"); }
2471        //     };
2472        //
2473        // The object literal following the "new Constructor()" expresssion
2474        // is passed as an additional (last) argument to the constructor.
2475        if (!env._no_syntax_extensions && type == LBRACE) {
2476            arguments.add(objectLiteral());
2477        }
2478
2479        final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
2480
2481        return new UnaryNode(newToken, callNode);
2482    }
2483
2484    /**
2485     * MemberExpression :
2486     *      PrimaryExpression
2487     *      FunctionExpression
2488     *      MemberExpression [ Expression ]
2489     *      MemberExpression . IdentifierName
2490     *      new MemberExpression Arguments
2491     *
2492     * See 11.2
2493     *
2494     * Parse member expression.
2495     * @return Expression node.
2496     */
2497    private Expression memberExpression() {
2498        // Prepare to build operation.
2499        Expression lhs;
2500
2501        switch (type) {
2502        case NEW:
2503            // Get new expression.
2504            lhs = newExpression();
2505            break;
2506
2507        case FUNCTION:
2508            // Get function expression.
2509            lhs = functionExpression(false, false);
2510            break;
2511
2512        default:
2513            // Get primary expression.
2514            lhs = primaryExpression();
2515            break;
2516        }
2517
2518loop:
2519        while (true) {
2520            // Capture token.
2521            final long callToken = token;
2522
2523            switch (type) {
2524            case LBRACKET:
2525                next();
2526
2527                // Get array index.
2528                final Expression index = expression();
2529
2530                expect(RBRACKET);
2531
2532                // Create indexing node.
2533                lhs = new IndexNode(callToken, finish, lhs, index);
2534
2535                break;
2536
2537            case PERIOD:
2538                if (lhs == null) {
2539                    throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
2540                }
2541
2542                next();
2543
2544                final IdentNode property = getIdentifierName();
2545
2546                // Create property access node.
2547                lhs = new AccessNode(callToken, finish, lhs, property.getName());
2548
2549                break;
2550
2551            default:
2552                break loop;
2553            }
2554        }
2555
2556        return lhs;
2557    }
2558
2559    /**
2560     * Arguments :
2561     *      ( )
2562     *      ( ArgumentList )
2563     *
2564     * ArgumentList :
2565     *      AssignmentExpression
2566     *      ArgumentList , AssignmentExpression
2567     *
2568     * See 11.2
2569     *
2570     * Parse function call arguments.
2571     * @return Argument list.
2572     */
2573    private ArrayList<Expression> argumentList() {
2574        // Prepare to accumulate list of arguments.
2575        final ArrayList<Expression> nodeList = new ArrayList<>();
2576        // LPAREN tested in caller.
2577        next();
2578
2579        // Track commas.
2580        boolean first = true;
2581
2582        while (type != RPAREN) {
2583            // Comma prior to every argument except the first.
2584            if (!first) {
2585                expect(COMMARIGHT);
2586            } else {
2587                first = false;
2588            }
2589
2590            // Get argument expression.
2591            nodeList.add(assignmentExpression(false));
2592        }
2593
2594        expect(RPAREN);
2595        return nodeList;
2596    }
2597
2598    private static <T> List<T> optimizeList(final ArrayList<T> list) {
2599        switch(list.size()) {
2600            case 0: {
2601                return Collections.emptyList();
2602            }
2603            case 1: {
2604                return Collections.singletonList(list.get(0));
2605            }
2606            default: {
2607                list.trimToSize();
2608                return list;
2609            }
2610        }
2611    }
2612
2613    /**
2614     * FunctionDeclaration :
2615     *      function Identifier ( FormalParameterList? ) { FunctionBody }
2616     *
2617     * FunctionExpression :
2618     *      function Identifier? ( FormalParameterList? ) { FunctionBody }
2619     *
2620     * See 13
2621     *
2622     * Parse function declaration.
2623     * @param isStatement True if for is a statement.
2624     *
2625     * @return Expression node.
2626     */
2627    private Expression functionExpression(final boolean isStatement, final boolean topLevel) {
2628        final long functionToken = token;
2629        final int  functionLine  = line;
2630        // FUNCTION is tested in caller.
2631        next();
2632
2633        IdentNode name = null;
2634
2635        if (type == IDENT || isNonStrictModeIdent()) {
2636            name = getIdent();
2637            verifyStrictIdent(name, "function name");
2638        } else if (isStatement) {
2639            // Nashorn extension: anonymous function statements
2640            if (env._no_syntax_extensions) {
2641                expect(IDENT);
2642            }
2643        }
2644
2645        // name is null, generate anonymous name
2646        boolean isAnonymous = false;
2647        if (name == null) {
2648            final String tmpName = getDefaultValidFunctionName(functionLine);
2649            name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
2650            isAnonymous = true;
2651        }
2652
2653        expect(LPAREN);
2654        final List<IdentNode> parameters = formalParameterList();
2655        expect(RPAREN);
2656
2657        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters);
2658        lc.push(functionNode);
2659        Block functionBody = null;
2660        try{
2661            functionBody = functionBody(functionNode);
2662        } finally {
2663            lc.pop(functionNode);
2664        }
2665
2666        if (isStatement) {
2667            if (topLevel || useBlockScope()) {
2668                functionNode.setFlag(FunctionNode.IS_DECLARED);
2669            } else if (isStrictMode) {
2670                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
2671            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) {
2672                throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here"), functionToken);
2673            } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) {
2674                warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken);
2675            }
2676            if (isArguments(name)) {
2677               lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS);
2678            }
2679        }
2680
2681        if (isAnonymous) {
2682            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
2683        }
2684
2685        final int arity = parameters.size();
2686
2687        final boolean strict = functionNode.isStrict();
2688        if (arity > 1) {
2689            final HashSet<String> parametersSet = new HashSet<>(arity);
2690
2691            for (int i = arity - 1; i >= 0; i--) {
2692                final IdentNode parameter = parameters.get(i);
2693                String parameterName = parameter.getName();
2694
2695                if (isArguments(parameterName)) {
2696                    functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2697                }
2698
2699                if (parametersSet.contains(parameterName)) {
2700                    // redefinition of parameter name
2701                    if (strict) {
2702                        throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
2703                    }
2704                    // rename in non-strict mode
2705                    parameterName = functionNode.uniqueName(parameterName);
2706                    final long parameterToken = parameter.getToken();
2707                    parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
2708                }
2709
2710                parametersSet.add(parameterName);
2711            }
2712        } else if (arity == 1) {
2713            if (isArguments(parameters.get(0))) {
2714                functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
2715            }
2716        }
2717
2718        final FunctionNode function = createFunctionNode(
2719                functionNode,
2720                functionToken,
2721                name,
2722                parameters,
2723                FunctionNode.Kind.NORMAL,
2724                functionLine,
2725                functionBody);
2726
2727        if (isStatement) {
2728            int varFlags = VarNode.IS_STATEMENT;
2729            if (!topLevel && useBlockScope()) {
2730                // mark ES6 block functions as lexically scoped
2731                varFlags |= VarNode.IS_LET;
2732            }
2733            final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, function, varFlags);
2734            if (topLevel) {
2735                functionDeclarations.add(varNode);
2736            } else if (useBlockScope()) {
2737                prependStatement(varNode); // Hoist to beginning of current block
2738            } else {
2739                appendStatement(varNode);
2740            }
2741        }
2742
2743        return function;
2744    }
2745
2746    private String getDefaultValidFunctionName(final int functionLine) {
2747        final String defaultFunctionName = getDefaultFunctionName();
2748        return isValidIdentifier(defaultFunctionName) ? defaultFunctionName : ANON_FUNCTION_PREFIX.symbolName() + functionLine;
2749    }
2750
2751    private static boolean isValidIdentifier(final String name) {
2752        if(name == null || name.isEmpty()) {
2753            return false;
2754        }
2755        if(!Character.isJavaIdentifierStart(name.charAt(0))) {
2756            return false;
2757        }
2758        for(int i = 1; i < name.length(); ++i) {
2759            if(!Character.isJavaIdentifierPart(name.charAt(i))) {
2760                return false;
2761            }
2762        }
2763        return true;
2764    }
2765
2766    private String getDefaultFunctionName() {
2767        if(!defaultNames.isEmpty()) {
2768            final Object nameExpr = defaultNames.peek();
2769            if(nameExpr instanceof PropertyKey) {
2770                markDefaultNameUsed();
2771                return ((PropertyKey)nameExpr).getPropertyName();
2772            } else if(nameExpr instanceof AccessNode) {
2773                markDefaultNameUsed();
2774                return ((AccessNode)nameExpr).getProperty();
2775            }
2776        }
2777        return null;
2778    }
2779
2780    private void markDefaultNameUsed() {
2781        defaultNames.pop();
2782        // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
2783        // from. Can't be null
2784        defaultNames.push("");
2785    }
2786
2787    /**
2788     * FormalParameterList :
2789     *      Identifier
2790     *      FormalParameterList , Identifier
2791     *
2792     * See 13
2793     *
2794     * Parse function parameter list.
2795     * @return List of parameter nodes.
2796     */
2797    private List<IdentNode> formalParameterList() {
2798        return formalParameterList(RPAREN);
2799    }
2800
2801    /**
2802     * Same as the other method of the same name - except that the end
2803     * token type expected is passed as argument to this method.
2804     *
2805     * FormalParameterList :
2806     *      Identifier
2807     *      FormalParameterList , Identifier
2808     *
2809     * See 13
2810     *
2811     * Parse function parameter list.
2812     * @return List of parameter nodes.
2813     */
2814    private List<IdentNode> formalParameterList(final TokenType endType) {
2815        // Prepare to gather parameters.
2816        final ArrayList<IdentNode> parameters = new ArrayList<>();
2817        // Track commas.
2818        boolean first = true;
2819
2820        while (type != endType) {
2821            // Comma prior to every argument except the first.
2822            if (!first) {
2823                expect(COMMARIGHT);
2824            } else {
2825                first = false;
2826            }
2827
2828            // Get and add parameter.
2829            final IdentNode ident = getIdent();
2830
2831            // ECMA 13.1 strict mode restrictions
2832            verifyStrictIdent(ident, "function parameter");
2833
2834            parameters.add(ident);
2835        }
2836
2837        parameters.trimToSize();
2838        return parameters;
2839    }
2840
2841    /**
2842     * FunctionBody :
2843     *      SourceElements?
2844     *
2845     * See 13
2846     *
2847     * Parse function body.
2848     * @return function node (body.)
2849     */
2850    private Block functionBody(final ParserContextFunctionNode functionNode) {
2851        long lastToken = 0L;
2852        ParserContextBlockNode body = null;
2853        final long bodyToken = token;
2854        Block functionBody;
2855        int bodyFinish = 0;
2856
2857
2858        final boolean parseBody;
2859        Object endParserState = null;
2860        try {
2861            // Create a new function block.
2862            body = newBlock();
2863            assert functionNode != null;
2864            final int functionId = functionNode.getId();
2865            parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
2866            // Nashorn extension: expression closures
2867            if (!env._no_syntax_extensions && type != LBRACE) {
2868                /*
2869                 * Example:
2870                 *
2871                 * function square(x) x * x;
2872                 * print(square(3));
2873                 */
2874
2875                // just expression as function body
2876                final Expression expr = assignmentExpression(true);
2877                lastToken = previousToken;
2878                functionNode.setLastToken(previousToken);
2879                assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
2880                // EOL uses length field to store the line number
2881                final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
2882                // Only create the return node if we aren't skipping nested functions. Note that we aren't
2883                // skipping parsing of these extended functions; they're considered to be small anyway. Also,
2884                // they don't end with a single well known token, so it'd be very hard to get correctly (see
2885                // the note below for reasoning on skipping happening before instead of after RBRACE for
2886                // details).
2887                if (parseBody) {
2888                    final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
2889                    appendStatement(returnNode);
2890                }
2891            } else {
2892                expectDontAdvance(LBRACE);
2893                if (parseBody || !skipFunctionBody(functionNode)) {
2894                    next();
2895                    // Gather the function elements.
2896                    final List<Statement> prevFunctionDecls = functionDeclarations;
2897                    functionDeclarations = new ArrayList<>();
2898                    try {
2899                        sourceElements(false);
2900                        addFunctionDeclarations(functionNode);
2901                    } finally {
2902                        functionDeclarations = prevFunctionDecls;
2903                    }
2904
2905                    lastToken = token;
2906                    if (parseBody) {
2907                        // Since the lexer can read ahead and lexify some number of tokens in advance and have
2908                        // them buffered in the TokenStream, we need to produce a lexer state as it was just
2909                        // before it lexified RBRACE, and not whatever is its current (quite possibly well read
2910                        // ahead) state.
2911                        endParserState = new ParserState(Token.descPosition(token), line, linePosition);
2912
2913                        // NOTE: you might wonder why do we capture/restore parser state before RBRACE instead of
2914                        // after RBRACE; after all, we could skip the below "expect(RBRACE);" if we captured the
2915                        // state after it. The reason is that RBRACE is a well-known token that we can expect and
2916                        // will never involve us getting into a weird lexer state, and as such is a great reparse
2917                        // point. Typical example of a weird lexer state after RBRACE would be:
2918                        //     function this_is_skipped() { ... } "use strict";
2919                        // because lexer is doing weird off-by-one maneuvers around string literal quotes. Instead
2920                        // of compensating for the possibility of a string literal (or similar) after RBRACE,
2921                        // we'll rather just restart parsing from this well-known, friendly token instead.
2922                    }
2923                }
2924                bodyFinish = finish;
2925                functionNode.setLastToken(token);
2926                expect(RBRACE);
2927            }
2928        } finally {
2929            restoreBlock(body);
2930        }
2931
2932        // NOTE: we can only do alterations to the function node after restoreFunctionNode.
2933
2934        if (parseBody) {
2935            functionNode.setEndParserState(endParserState);
2936        } else if (!body.getStatements().isEmpty()){
2937            // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see
2938            // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to
2939            // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as
2940            // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away
2941            // nested bodies early if we were supposed to skip 'em.
2942            body.setStatements(Collections.<Statement>emptyList());
2943        }
2944
2945        if (reparsedFunction != null) {
2946            // We restore the flags stored in the function's ScriptFunctionData that we got when we first
2947            // eagerly parsed the code. We're doing it because some flags would be set based on the
2948            // content of the function, or even content of its nested functions, most of which are normally
2949            // skipped during an on-demand compilation.
2950            final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
2951            if (data != null) {
2952                // Data can be null if when we originally parsed the file, we removed the function declaration
2953                // as it was dead code.
2954                functionNode.setFlag(data.getFunctionFlags());
2955                // This compensates for missing markEval() in case the function contains an inner function
2956                // that contains eval(), that now we didn't discover since we skipped the inner function.
2957                if (functionNode.hasNestedEval()) {
2958                    assert functionNode.hasScopeBlock();
2959                    body.setFlag(Block.NEEDS_SCOPE);
2960                }
2961            }
2962        }
2963        functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements());
2964        return functionBody;
2965    }
2966
2967    private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) {
2968        if (reparsedFunction == null) {
2969            // Not reparsing, so don't skip any function body.
2970            return false;
2971        }
2972        // Skip to the RBRACE of this function, and continue parsing from there.
2973        final RecompilableScriptFunctionData data = reparsedFunction.getScriptFunctionData(functionNode.getId());
2974        if (data == null) {
2975            // Nested function is not known to the reparsed function. This can happen if the FunctionNode was
2976            // in dead code that was removed. Both FoldConstants and Lower prune dead code. In that case, the
2977            // FunctionNode was dropped before a RecompilableScriptFunctionData could've been created for it.
2978            return false;
2979        }
2980        final ParserState parserState = (ParserState)data.getEndParserState();
2981        assert parserState != null;
2982
2983        stream.reset();
2984        lexer = parserState.createLexer(source, lexer, stream, scripting && !env._no_syntax_extensions);
2985        line = parserState.line;
2986        linePosition = parserState.linePosition;
2987        // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
2988        // the RBRACE.
2989        type = SEMICOLON;
2990        k = -1;
2991        next();
2992
2993        return true;
2994    }
2995
2996    /**
2997     * Encapsulates part of the state of the parser, enough to reconstruct the state of both parser and lexer
2998     * for resuming parsing after skipping a function body.
2999     */
3000    private static class ParserState implements Serializable {
3001        private final int position;
3002        private final int line;
3003        private final int linePosition;
3004
3005        private static final long serialVersionUID = -2382565130754093694L;
3006
3007        ParserState(final int position, final int line, final int linePosition) {
3008            this.position = position;
3009            this.line = line;
3010            this.linePosition = linePosition;
3011        }
3012
3013        Lexer createLexer(final Source source, final Lexer lexer, final TokenStream stream, final boolean scripting) {
3014            final Lexer newLexer = new Lexer(source, position, lexer.limit - position, stream, scripting, true);
3015            newLexer.restoreState(new Lexer.State(position, Integer.MAX_VALUE, line, -1, linePosition, SEMICOLON));
3016            return newLexer;
3017        }
3018    }
3019
3020    private void printAST(final FunctionNode functionNode) {
3021        if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
3022            env.getErr().println(new ASTWriter(functionNode));
3023        }
3024
3025        if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
3026            env.getErr().println(new PrintVisitor(functionNode, true, false));
3027        }
3028    }
3029
3030    private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) {
3031        VarNode lastDecl = null;
3032        for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
3033            Statement decl = functionDeclarations.get(i);
3034            if (lastDecl == null && decl instanceof VarNode) {
3035                decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
3036                functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS);
3037            }
3038            prependStatement(decl);
3039        }
3040    }
3041
3042    private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
3043        if (earlyError) {
3044            throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
3045        }
3046        final ArrayList<Expression> args = new ArrayList<>();
3047        args.add(lhs);
3048        if (rhs == null) {
3049            args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish()));
3050        } else {
3051            args.add(rhs);
3052        }
3053        args.add(LiteralNode.newInstance(lhs.getToken(), lhs.getFinish(), lhs.toString()));
3054        return new RuntimeNode(lhs.getToken(), lhs.getFinish(), RuntimeNode.Request.REFERENCE_ERROR, args);
3055    }
3056
3057    /*
3058     * parse LHS [a, b, ..., c].
3059     *
3060     * JavaScript 1.8.
3061     */
3062    //private Node destructureExpression() {
3063    //    return null;
3064    //}
3065
3066    /**
3067     * PostfixExpression :
3068     *      LeftHandSideExpression
3069     *      LeftHandSideExpression ++ // [no LineTerminator here]
3070     *      LeftHandSideExpression -- // [no LineTerminator here]
3071     *
3072     * See 11.3
3073     *
3074     * UnaryExpression :
3075     *      PostfixExpression
3076     *      delete UnaryExpression
3077     *      Node UnaryExpression
3078     *      typeof UnaryExpression
3079     *      ++ UnaryExpression
3080     *      -- UnaryExpression
3081     *      + UnaryExpression
3082     *      - UnaryExpression
3083     *      ~ UnaryExpression
3084     *      ! UnaryExpression
3085     *
3086     * See 11.4
3087     *
3088     * Parse unary expression.
3089     * @return Expression node.
3090     */
3091    private Expression unaryExpression() {
3092        final int  unaryLine  = line;
3093        final long unaryToken = token;
3094
3095        switch (type) {
3096        case DELETE: {
3097            next();
3098            final Expression expr = unaryExpression();
3099            if (expr instanceof BaseNode || expr instanceof IdentNode) {
3100                return new UnaryNode(unaryToken, expr);
3101            }
3102            appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
3103            return LiteralNode.newInstance(unaryToken, finish, true);
3104        }
3105        case VOID:
3106        case TYPEOF:
3107        case ADD:
3108        case SUB:
3109        case BIT_NOT:
3110        case NOT:
3111            next();
3112            final Expression expr = unaryExpression();
3113            return new UnaryNode(unaryToken, expr);
3114
3115        case INCPREFIX:
3116        case DECPREFIX:
3117            final TokenType opType = type;
3118            next();
3119
3120            final Expression lhs = leftHandSideExpression();
3121            // ++, -- without operand..
3122            if (lhs == null) {
3123                throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3124            }
3125
3126            if (!(lhs instanceof AccessNode ||
3127                  lhs instanceof IndexNode ||
3128                  lhs instanceof IdentNode)) {
3129                return referenceError(lhs, null, env._early_lvalue_error);
3130            }
3131
3132            if (lhs instanceof IdentNode) {
3133                if (!checkIdentLValue((IdentNode)lhs)) {
3134                    return referenceError(lhs, null, false);
3135                }
3136                verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3137            }
3138
3139            return incDecExpression(unaryToken, opType, lhs, false);
3140
3141        default:
3142            break;
3143        }
3144
3145        Expression expression = leftHandSideExpression();
3146
3147        if (last != EOL) {
3148            switch (type) {
3149            case INCPREFIX:
3150            case DECPREFIX:
3151                final TokenType opType = type;
3152                final Expression lhs = expression;
3153                // ++, -- without operand..
3154                if (lhs == null) {
3155                    throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
3156                }
3157
3158                if (!(lhs instanceof AccessNode ||
3159                   lhs instanceof IndexNode ||
3160                   lhs instanceof IdentNode)) {
3161                    next();
3162                    return referenceError(lhs, null, env._early_lvalue_error);
3163                }
3164                if (lhs instanceof IdentNode) {
3165                    if (!checkIdentLValue((IdentNode)lhs)) {
3166                        next();
3167                        return referenceError(lhs, null, false);
3168                    }
3169                    verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
3170                }
3171                expression = incDecExpression(token, type, expression, true);
3172                next();
3173                break;
3174            default:
3175                break;
3176            }
3177        }
3178
3179        if (expression == null) {
3180            throw error(AbstractParser.message("expected.operand", type.getNameOrType()));
3181        }
3182
3183        return expression;
3184    }
3185
3186    /**
3187     * MultiplicativeExpression :
3188     *      UnaryExpression
3189     *      MultiplicativeExpression * UnaryExpression
3190     *      MultiplicativeExpression / UnaryExpression
3191     *      MultiplicativeExpression % UnaryExpression
3192     *
3193     * See 11.5
3194     *
3195     * AdditiveExpression :
3196     *      MultiplicativeExpression
3197     *      AdditiveExpression + MultiplicativeExpression
3198     *      AdditiveExpression - MultiplicativeExpression
3199     *
3200     * See 11.6
3201     *
3202     * ShiftExpression :
3203     *      AdditiveExpression
3204     *      ShiftExpression << AdditiveExpression
3205     *      ShiftExpression >> AdditiveExpression
3206     *      ShiftExpression >>> AdditiveExpression
3207     *
3208     * See 11.7
3209     *
3210     * RelationalExpression :
3211     *      ShiftExpression
3212     *      RelationalExpression < ShiftExpression
3213     *      RelationalExpression > ShiftExpression
3214     *      RelationalExpression <= ShiftExpression
3215     *      RelationalExpression >= ShiftExpression
3216     *      RelationalExpression instanceof ShiftExpression
3217     *      RelationalExpression in ShiftExpression // if !noIf
3218     *
3219     * See 11.8
3220     *
3221     *      RelationalExpression
3222     *      EqualityExpression == RelationalExpression
3223     *      EqualityExpression != RelationalExpression
3224     *      EqualityExpression === RelationalExpression
3225     *      EqualityExpression !== RelationalExpression
3226     *
3227     * See 11.9
3228     *
3229     * BitwiseANDExpression :
3230     *      EqualityExpression
3231     *      BitwiseANDExpression & EqualityExpression
3232     *
3233     * BitwiseXORExpression :
3234     *      BitwiseANDExpression
3235     *      BitwiseXORExpression ^ BitwiseANDExpression
3236     *
3237     * BitwiseORExpression :
3238     *      BitwiseXORExpression
3239     *      BitwiseORExpression | BitwiseXORExpression
3240     *
3241     * See 11.10
3242     *
3243     * LogicalANDExpression :
3244     *      BitwiseORExpression
3245     *      LogicalANDExpression && BitwiseORExpression
3246     *
3247     * LogicalORExpression :
3248     *      LogicalANDExpression
3249     *      LogicalORExpression || LogicalANDExpression
3250     *
3251     * See 11.11
3252     *
3253     * ConditionalExpression :
3254     *      LogicalORExpression
3255     *      LogicalORExpression ? AssignmentExpression : AssignmentExpression
3256     *
3257     * See 11.12
3258     *
3259     * AssignmentExpression :
3260     *      ConditionalExpression
3261     *      LeftHandSideExpression AssignmentOperator AssignmentExpression
3262     *
3263     * AssignmentOperator :
3264     *      = *= /= %= += -= <<= >>= >>>= &= ^= |=
3265     *
3266     * See 11.13
3267     *
3268     * Expression :
3269     *      AssignmentExpression
3270     *      Expression , AssignmentExpression
3271     *
3272     * See 11.14
3273     *
3274     * Parse expression.
3275     * @return Expression node.
3276     */
3277    private Expression expression() {
3278        // TODO - Destructuring array.
3279        // Include commas in expression parsing.
3280        return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
3281    }
3282
3283    private JoinPredecessorExpression joinPredecessorExpression() {
3284        return new JoinPredecessorExpression(expression());
3285    }
3286
3287    private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
3288        // Get the precedence of the next operator.
3289        int precedence = type.getPrecedence();
3290        Expression lhs = exprLhs;
3291
3292        // While greater precedence.
3293        while (type.isOperator(noIn) && precedence >= minPrecedence) {
3294            // Capture the operator token.
3295            final long op = token;
3296
3297            if (type == TERNARY) {
3298                // Skip operator.
3299                next();
3300
3301                // Pass expression. Middle expression of a conditional expression can be a "in"
3302                // expression - even in the contexts where "in" is not permitted.
3303                final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
3304
3305                expect(COLON);
3306
3307                // Fail expression.
3308                final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3309
3310                // Build up node.
3311                lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
3312            } else {
3313                // Skip operator.
3314                next();
3315
3316                 // Get the next primary expression.
3317                Expression rhs;
3318                final boolean isAssign = Token.descType(op) == ASSIGN;
3319                if(isAssign) {
3320                    defaultNames.push(lhs);
3321                }
3322                try {
3323                    rhs = unaryExpression();
3324                    // Get precedence of next operator.
3325                    int nextPrecedence = type.getPrecedence();
3326
3327                    // Subtask greater precedence.
3328                    while (type.isOperator(noIn) &&
3329                           (nextPrecedence > precedence ||
3330                           nextPrecedence == precedence && !type.isLeftAssociative())) {
3331                        rhs = expression(rhs, nextPrecedence, noIn);
3332                        nextPrecedence = type.getPrecedence();
3333                    }
3334                } finally {
3335                    if(isAssign) {
3336                        defaultNames.pop();
3337                    }
3338                }
3339                lhs = verifyAssignment(op, lhs, rhs);
3340            }
3341
3342            precedence = type.getPrecedence();
3343        }
3344
3345        return lhs;
3346    }
3347
3348    private Expression assignmentExpression(final boolean noIn) {
3349        // TODO - Handle decompose.
3350        // Exclude commas in expression parsing.
3351        return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
3352    }
3353
3354    /**
3355     * Parse an end of line.
3356     */
3357    private void endOfLine() {
3358        switch (type) {
3359        case SEMICOLON:
3360        case EOL:
3361            next();
3362            break;
3363        case RPAREN:
3364        case RBRACKET:
3365        case RBRACE:
3366        case EOF:
3367            break;
3368        default:
3369            if (last != EOL) {
3370                expect(SEMICOLON);
3371            }
3372            break;
3373        }
3374    }
3375
3376    @Override
3377    public String toString() {
3378        return "'JavaScript Parsing'";
3379    }
3380
3381    private static void markEval(final ParserContext lc) {
3382        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
3383        boolean flaggedCurrentFn = false;
3384        while (iter.hasNext()) {
3385            final ParserContextFunctionNode fn = iter.next();
3386            if (!flaggedCurrentFn) {
3387                fn.setFlag(FunctionNode.HAS_EVAL);
3388                flaggedCurrentFn = true;
3389            } else {
3390                fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
3391            }
3392            final ParserContextBlockNode body = lc.getFunctionBody(fn);
3393            // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip
3394            // parsing a nested function. functionBody() contains code to compensate for the lack of invoking
3395            // this method when the parser skips a nested function.
3396            body.setFlag(Block.NEEDS_SCOPE);
3397            fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK);
3398        }
3399    }
3400
3401    private void prependStatement(final Statement statement) {
3402        lc.prependStatementToCurrentNode(statement);
3403    }
3404
3405    private void appendStatement(final Statement statement) {
3406        lc.appendStatementToCurrentNode(statement);
3407    }
3408}
3409