关于使用ANTLR treewalker执行循环的问题

时间:2011-08-07 16:47:26

标签: c# loops antlr

我已经阅读了一些关于ANTLR循环的内容,但我仍然没有得到如何为循环实际构建一个treewalker。所以我想做的是解析和执行这样的语句:

int a = 1
while(a < 3) {
    int c = 1
    a = a + 1
}

当我把它放在我的解析器中时,生成的AST看起来像这样: AST

现在我想创建一个树形行管,它首先检查while条件是否为真,然后执行语句,或者如果语句不为真,则跳转到while之后的语句。因此,我想我必须知道如何获取EOF的索引才能跳过它,但我不知道该怎么做。

我尝试的是this page上的代码示例,但似乎它不再起作用(您可以在下面的评论中看到这一点),还有什么困扰我,这是事实上,在执行while循环之前执行VARDEF和ASSIGN,我不知道如何更改它。

所以我想知道的是,我在这里有正确的方法,还是有更好的方法呢?你能为我的while循环给我一个示例树木行者,我认为这会非常有帮助。

这是我目前对树行者的尝试:

tree grammar SGLTreeWalker;

options {
    tokenVocab = SGL;
    language = 'CSharp2';
    ASTLabelType=CommonTree;
}

@namespace { SGL }

@header {
    using System.Collections.Generic;
}

@members{
    SGLActions action = new SGLActions();
}

compilationUnit
    :   mainStatement+ EOF
    ;

mainStatement
    :   statement
    ;   

statement
    :   variableDeclarationList // int a = 1, b = 2, c
    |   ^(ASSIGN variableAssignment) // a = 4
    |   whileLoop
    ;

/* Statements */

whileLoop
    :   ^('while' expression statement*)
    {
        int next = input.Index(); // index of node following WHILE
        input.Seek($expression.start.startIndex);
        Object condition = expression();
        while((Boolean) condition) {
            input.Seek($statement.start.startIndex);
            statement();
            input.Seek($expression.start.startIndex);
                condition = expression();
        }
        input.Seek(next);
    }
    ;

variableDeclarationList
    :   ^(VARDEF variableType variableName expression) {    
        action.NewLocalVariable($variableType.txt,$variableName.txt,$expression.txt); 
    }
    ;

// Only used for the first time declaration of a new variable
variableAssignment
    :   variableName expression? {
        action.AssignVariable($variableName.txt,$expression.txt);
    }
    ;

variableName returns [string txt]
    :   Identifier {$txt = $Identifier.text;}
    ;   

variableType returns [string txt]
    :   IntType {$txt = $IntType.text;}
    |   BooleanType {$txt = $BooleanType.text;}
    |   StringType {$txt = $StringType.text;}
    |   FloatType {$txt = $FloatType.text;}
    ;     

/* Expressions */

// start rule for all sorts of expressions
expression returns [string txt]
    :   ^('+' a=expression b=expression) { $txt = action.Add($a.txt,$b.txt); }
    |   ^('-' a=expression b=expression) { $txt = action.Sub($a.txt,$b.txt); }
    |   ^('*' a=expression b=expression) { $txt = action.Mult($a.txt,$b.txt); }
    |   ^('/' a=expression b=expression) { $txt = action.Div($a.txt,$b.txt); }
    |   ^('%' a=expression b=expression) { $txt = action.Remainder($a.txt,$b.txt); } 
    |   ^(NEGATE a=expression) { $txt = action.Mult($a.txt,"-1"); }
    |   ^('<' a=expression b=expression) { $txt = action.ConditionLess($a.txt,$b.txt); }
    |   ^('<=' a=expression b=expression) { $txt = action.ConditionLessOrEqual($a.txt,$b.txt); }
    |   ^('>' a=expression b=expression) { $txt = action.ConditionGreater($a.txt,$b.txt); }
    |   ^('>=' a=expression b=expression) { $txt = action.ConditionGreaterOrEqual($a.txt,$b.txt); }
    |   ^('!=' a=expression b=expression) { $txt = action.ConditionNotEqual($a.txt,$b.txt); }
    |   ^('==' a=expression b=expression) { $txt = action.ConditionEqual($a.txt,$b.txt); }
    |   ^('&&' a=expression b=expression) { $txt = action.ConnectiveAnd($a.txt,$b.txt); }
    |   ^('||' a=expression b=expression) { $txt = action.ConnectiveOr($a.txt,$b.txt); }
    |   ^('?' a=expression b=expression c=expression) { $txt = action.ConditionBranch($a.txt,$b.txt,$c.txt); }
    |   Identifier { $txt = action.GetVariable($Identifier.text); }
    |   IntegerAtom { $txt = $IntegerAtom.text; }
    |   BooleanAtom { $txt = $BooleanAtom.text; }
    ;

0 个答案:

没有答案