我已经阅读了一些关于ANTLR循环的内容,但我仍然没有得到如何为循环实际构建一个treewalker。所以我想做的是解析和执行这样的语句:
int a = 1
while(a < 3) {
int c = 1
a = a + 1
}
当我把它放在我的解析器中时,生成的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; }
;