示例#1
0
文件: CodeBlock.cs 项目: blyry/MiniME
        public void AddStatement(Statement stmt)
        {
            // Ignore if null (typically from extra semicolon in source)
            if (stmt == null)
                return;

            Content.Add(stmt);
        }
示例#2
0
        public void CheckControlCondition(ast.Statement statement, ast.Expression expr)
        {
            if (expr == null)
            {
                return;
            }

            if ((expr.RootNode as ast.ExprNodeAssignment) != null)
            {
                currentScope.Compiler.RecordWarning(expr.Bookmark, "assignment as condition of flow control statement (use parens to disable this warning)");
            }
        }
示例#3
0
 public static CodeBlock GetTrailingCodeBlock(Statement s)
 {
     var cbf=new CodeBlockFinder();
     s.OnVisitChildNodes(cbf);
     return cbf.TrailingCodeBlock;
 }
示例#4
0
        // Parse a single statement
        ast.Statement ParseSingleStatement()
        {
            var bmk = t.GetBookmark();

            // Special handling for labels
            if (t.token == Token.identifier)
            {
                string label = t.identifier;
                t.Next();
                if (t.SkipOptional(Token.colon))
                {
                    return(new ast.StatementLabel(bmk, label));
                }

                t.Rewind(bmk);
            }

            switch (t.token)
            {
            case Token.semicolon:
            {
                t.Compiler.RecordWarning(t.GetBookmark(), "unnecessary semicolon");
                t.Next();
                return(null);
            }

            case Token.openBrace:
            {
                t.Next();
                var stmt = new ast.StatementBlock(t.GetBookmark());
                while (!t.SkipOptional(Token.closeBrace))
                {
                    stmt.AddStatement(ParseSingleStatement());
                }
                return(stmt);
            }

            case Token.kw_debugger:
            {
                t.Next();
                t.SkipRequired(Token.semicolon);

                return(new ast.StatementDebugger(bmk, Token.kw_debugger));
            }

            case Token.kw_return:
            {
                t.Next();

                if (t.SkipOptional(Token.semicolon))
                {
                    return(new ast.StatementReturnThrow(bmk, Token.kw_return));
                }
                else
                {
                    var temp = new ast.StatementReturnThrow(bmk, Token.kw_return, ParseCompositeExpression(0));
                    t.SkipRequired(Token.semicolon);
                    return(temp);
                }
            }

            case Token.kw_throw:
            {
                t.Next();
                var temp = new ast.StatementReturnThrow(bmk, Token.kw_throw, ParseCompositeExpression(0));
                t.SkipRequired(Token.semicolon);
                return(temp);
            }

            case Token.kw_fallthrough:
            {
                // Fake statement - comment // fall through
                Token op = t.token;
                t.Next();
                return(new ast.StatementBreakContinue(bmk, op, null));
            }

            case Token.kw_break:
            case Token.kw_continue:
            {
                // Statement
                Token op = t.token;
                t.Next();

                // Optional label
                if (!t.SkipOptional(Token.semicolon))
                {
                    t.Require(Token.identifier);

                    var temp = new ast.StatementBreakContinue(bmk, op, t.identifier);
                    t.Next();

                    t.Require(Token.semicolon);

                    return(temp);
                }

                // No label
                return(new ast.StatementBreakContinue(bmk, op, null));
            }

            case Token.kw_if:
            {
                t.Next();

                // Condition
                t.SkipRequired(Token.openRound);
                var stmt = new ast.StatementIfElse(bmk, ParseCompositeExpression(0));
                t.SkipRequired(Token.closeRound);

                // True code block
                stmt.TrueStatement = ParseStatement();

                // Optional else block
                if (t.SkipOptional(Token.kw_else))
                {
                    stmt.FalseStatement = ParseStatement();
                }

                return(stmt);
            }

            case Token.kw_switch:
            {
                t.Next();

                // Value
                t.SkipRequired(Token.openRound);
                var stmt = new ast.StatementSwitch(bmk, ParseCompositeExpression(0));
                t.SkipRequired(Token.closeRound);

                // Opening brace
                t.SkipRequired(Token.openBrace);

                // Parse all cases
                ast.StatementSwitch.Case currentCase = null;
                while (t.token != Token.closeBrace)
                {
                    // new case?
                    if (t.SkipOptional(Token.kw_case))
                    {
                        currentCase = stmt.AddCase(ParseCompositeExpression(0));
                        t.SkipRequired(Token.colon);
                        continue;
                    }

                    // default case?
                    if (t.SkipOptional(Token.kw_default))
                    {
                        currentCase = stmt.AddCase(null);
                        t.SkipRequired(Token.colon);
                        continue;
                    }

                    // Must have a case
                    if (currentCase == null)
                    {
                        throw new CompileError("Unexpected code in switch statement before 'case' or 'default'", t);
                    }

                    currentCase.AddCode(ParseSingleStatement());
                }

                // Done
                t.SkipRequired(Token.closeBrace);
                return(stmt);
            }

            case Token.kw_for:
            {
                // Statement
                t.Next();
                t.SkipRequired(Token.openRound);

                ast.Statement init = null;

                if (t.token != Token.semicolon)
                {
                    // Initializers
                    init = ParseVarDeclStatement(ParseContext.DisableInOperator | ParseContext.AllowCompositeExpressions);

                    // Foreach iterator
                    if (t.SkipOptional(Token.kw_in))
                    {
                        var stmtForEach = new ast.StatementForIn(bmk);

                        var decl = init as ast.StatementVariableDeclaration;

                        if (decl != null)
                        {
                            if (decl.HasInitialValue())
                            {
                                throw new CompileError("Syntax error - unexpected initializer in for-in statement", t);
                            }
                            if (decl.Variables.Count > 1)
                            {
                                throw new CompileError("Syntax error - unexpected multiple iterator variables in for-in statement", t);
                            }
                            stmtForEach.VariableDeclaration = init;
                        }
                        else
                        {
                            var exprstmtForEach = init as ast.StatementExpression;
                            if (exprstmtForEach == null)
                            {
                                throw new CompileError("Syntax error - invalid iterator variable declarations in for loop", t);
                            }
                            if ((exprstmtForEach.Expression.RootNode as ast.ExprNodeIdentifier) == null &&
                                (exprstmtForEach.Expression.RootNode as ast.ExprNodeIndexer) == null)
                            {
                                throw new CompileError("Syntax error - invalid iterator variable declarations in for loop", t);
                            }
                            stmtForEach.Iterator = exprstmtForEach.Expression;
                        }


                        // Collection
                        stmtForEach.Collection = ParseCompositeExpression(0);
                        t.SkipRequired(Token.closeRound);

                        // Parse content
                        stmtForEach.Code = ParseStatement();
                        return(stmtForEach);
                    }
                }

                // Create the statement, store the initialization expression(s)
                var stmt = new ast.StatementFor(bmk);
                stmt.Initialize = init;
                t.SkipRequired(Token.semicolon);

                // Condition
                if (t.token != Token.semicolon)
                {
                    stmt.Condition = ParseCompositeExpression(0);
                }
                t.SkipRequired(Token.semicolon);

                // Iterator
                if (t.token != Token.closeRound)
                {
                    stmt.Increment = ParseCompositeExpression(ParseContext.AllowCompositeExpressions);
                }
                t.SkipRequired(Token.closeRound);

                // Parse code block
                stmt.Code = ParseStatement();
                return(stmt);
            }

            case Token.kw_do:
            {
                var stmt = new ast.StatementDoWhile(bmk);
                t.Next();
                stmt.Code = ParseStatement();
                t.SkipRequired(Token.kw_while);
                t.SkipRequired(Token.openRound);
                stmt.Condition = ParseCompositeExpression(ParseContext.AllowCompositeExpressions);
                t.SkipRequired(Token.closeRound);
                t.SkipRequired(Token.semicolon);
                return(stmt);
            }

            case Token.kw_while:
            {
                var stmt = new ast.StatementWhile(bmk);
                t.Next();
                t.SkipRequired(Token.openRound);
                stmt.Condition = ParseCompositeExpression(ParseContext.AllowCompositeExpressions);
                t.SkipRequired(Token.closeRound);
                stmt.Code = ParseStatement();
                return(stmt);
            }

            case Token.kw_with:
            {
                var stmt = new ast.StatementWith(bmk);
                t.Next();
                t.SkipRequired(Token.openRound);
                stmt.Expression = ParseCompositeExpression(0);
                t.SkipRequired(Token.closeRound);
                stmt.Code = ParseStatement();
                return(stmt);
            }

            case Token.kw_try:
            {
                t.Next();

                // Create the statement
                var stmt = new ast.StatementTryCatchFinally(bmk);

                // The code
                t.Require(Token.openBrace);
                stmt.Code = ParseStatementBlock(TriState.Yes);

                // Catch clauses
                bmk = t.GetBookmark();
                while (t.SkipOptional(Token.kw_catch))
                {
                    var cc = new ast.CatchClause(bmk);

                    // Catch expression
                    t.SkipRequired(Token.openRound);

                    // Exception variable name
                    t.Require(Token.identifier);
                    cc.ExceptionVariable = t.identifier;
                    t.Next();

                    // Optional 'if <condition>'   (firefox extension)
                    if (t.token == Token.kw_if)
                    {
                        t.Next();
                        cc.Condition = ParseCompositeExpression(0);
                    }

                    // End of expression
                    t.SkipRequired(Token.closeRound);

                    // Code block
                    t.Require(Token.openBrace);
                    cc.Code = ParseStatementBlock(TriState.Yes);

                    stmt.CatchClauses.Add(cc);

                    bmk = t.GetBookmark();
                }

                // Finally
                if (t.SkipOptional(Token.kw_finally))
                {
                    t.Require(Token.openBrace);
                    stmt.FinallyClause = ParseStatementBlock(TriState.Yes);
                }

                return(stmt);
            }

            case Token.kw_function:
            {
                // Function declaration
                t.Next();
                t.Require(Token.identifier);
                var stmt = new ast.StatementExpression(bmk, new ast.Expression(ParseFunction()));
                t.SkipOptional(Token.semicolon);
                return(stmt);
            }

            case Token.directive_comment:
            {
                var stmt = new ast.StatementComment(bmk, t.RawToken.Substring(0, 2) + t.RawToken.Substring(3));
                t.Next();
                return(stmt);
            }

            case Token.directive_private:
            case Token.directive_public:
            {
                var stmt = new ast.StatementAccessibility(bmk);
                foreach (var symbol in t.identifier.Split(','))
                {
                    var spec = new AccessibilitySpec();
                    if (!spec.Parse(t.token == Token.directive_private ? Accessibility.Private : Accessibility.Public,
                                    symbol))
                    {
                        throw new CompileError(string.Format("Invalid private member declaration - `{0}`", symbol), t);
                    }
                    stmt.Specs.Add(spec);
                }

                t.Next();
                return(stmt);
            }

            default:
            {
                // Must be a variable declaration or an expression
                var stmt = ParseVarDeclStatement(0);
                t.SkipRequired(Token.semicolon);
                return(stmt);
            }
            }
        }