예제 #1
0
        public Node parseForStatement(Node node)
        {
            Node init;
            bool forIn;
            List<Node> initSeq;
            Token initStartToken;
            Node test;
            Node update;
            Node left = null, right = null;
            string kind;
            List<Node> declarations;
            List<Node> body;
            bool oldInIteration;
            bool previousAllowIn = state.allowIn;

            init = test = update = null;
            forIn = true;

            expectKeyword("for");

            expect("(");

            if (match(";"))
            {
                lex();
            }
            else
            {
                if (matchKeyword("var"))
                {
                    init = new Node();
                    lex();

                    state.allowIn = false;
                    declarations = parseVariableDeclarationList(new Options() { inFor = true });
                    state.allowIn = previousAllowIn;

                    if (declarations.Count == 1 && matchKeyword("in"))
                    {
                        init = init.finishVariableDeclaration(declarations);
                        lex();
                        left = init;
                        right = parseExpression();
                        init = null;
                    }
                    else if (declarations.Count == 1 && declarations[0].init == null && matchContextualKeyword("of"))
                    {
                        init = init.finishVariableDeclaration(declarations);
                        lex();
                        left = init;
                        right = parseAssignmentExpression();
                        init = null;
                        forIn = false;
                    }
                    else
                    {
                        init = init.finishVariableDeclaration(declarations);
                        expect(";");
                    }
                }
                else if (matchKeyword("const") || matchKeyword("let"))
                {
                    init = new Node();
                    kind = lex().value;

                    state.allowIn = false;
                    declarations = parseBindingList(kind, new Options() { inFor = true });
                    state.allowIn = previousAllowIn;

                    if (declarations.Count == 1 && declarations[0].init == null && matchKeyword("in"))
                    {
                        init = init.finishLexicalDeclaration(declarations, kind);
                        lex();
                        left = init;
                        right = parseExpression();
                        init = null;
                    }
                    else if (declarations.Count == 1 && declarations[0].init == null && matchContextualKeyword("of"))
                    {
                        init = init.finishLexicalDeclaration(declarations, kind);
                        lex();
                        left = init;
                        right = parseAssignmentExpression();
                        init = null;
                        forIn = false;
                    }
                    else
                    {
                        consumeSemicolon();
                        init = init.finishLexicalDeclaration(declarations, kind);
                    }
                }
                else
                {
                    initStartToken = lookahead;
                    state.allowIn = false;
                    init = inheritCoverGrammar(parseAssignmentExpression);
                    state.allowIn = previousAllowIn;

                    if (matchKeyword("in"))
                    {
                        if (!isAssignmentTarget)
                        {
                            tolerateError(Messages.InvalidLHSInForIn);
                        }

                        lex();
                        reinterpretExpressionAsPattern(init);
                        left = init;
                        right = parseExpression();
                        init = null;
                    }
                    else if (matchContextualKeyword("of"))
                    {
                        if (!isAssignmentTarget)
                        {
                            tolerateError(Messages.InvalidLHSInForLoop);
                        }

                        lex();
                        reinterpretExpressionAsPattern(init);
                        left = init;
                        right = parseAssignmentExpression();
                        init = null;
                        forIn = false;
                    }
                    else
                    {
                        if (match(","))
                        {
                            initSeq = new List<Node>() { init };
                            while (match(","))
                            {
                                lex();
                                initSeq.Add(isolateCoverGrammar(parseAssignmentExpression));
                            }
                            init = new Node(initStartToken).finishSequenceExpression(initSeq);
                        }
                        expect(";");
                    }
                }
            }

            if (left != null)
            {

                if (!match(";"))
                {
                    test = parseExpression();
                }
                expect(";");

                if (!match(")"))
                {
                    update = parseExpression();
                }
            }

            expect(")");

            oldInIteration = state.inIteration;
            state.inIteration = true;

            body = new List<Node>() { isolateCoverGrammar(parseStatement) };

            state.inIteration = oldInIteration;

            return (left == null)
                ? node.finishForStatement(init, test, update, body)
                : forIn
                    ? node.finishForInStatement(left, right, body)
                    : node.finishForOfStatement(left, right, body);
        }