2010-04-20 49 views
1

我目前有一个编译器,它使用一个代码块的所有子代都在同一级别的AST(即,block.children == {stm1,stm2,stm3 ,等...})。我试图在这棵树上做活性分析,这意味着我需要从stm1处理返回的值,然后将其传递给stm2,然后将stm2返回的值传递给stm3,依此类推。当AST以这种方式构建时,我没有看到以这种方式执行子规则的方式。一次处理一个n-ary ANTLR AST一个孩子

有没有办法允许我用给定的AST链接儿童语法项目的执行,还是我将不得不经历重构解析器以生成嵌套结构和更新其余部分的痛苦过程编译器的工作与新的AST?


例ANTLR语法片段:

block 
    : ^(BLOCK statement*) 
    ; 
statement 
    : // stuff 
    ; 

我希望我不用去:

block 
    : ^(BLOCK statementList) 
    ; 
statementList 
    : ^(StmLst statement statement+) 
    | ^(StmLst statement) 
    ; 
statement 
    : // stuff 
    ; 

回答

1

分析器(或词法)规则,可以采取参数值和能返回一个值。所以,在你的话,你可以这样做:

block 
@init {Object o = null; /* initialize the value being passed through */ } 
    : ^(BLOCK (s=statement[o] {$o = $s.returnValue; /*re-assign 'o' */ })*) 
    ; 

statement [Object parameter] returns [Object returnValue] 
    : // do something with 'parameter' and 'returnValue' 
    ; 

这里是一个非常简单的例子,你可以用它来玩弄:

grammar Test; 

@members{ 
    public static void main(String[] args) throws Exception { 
     ANTLRStringStream in = new ANTLRStringStream("1;2;3;4;"); 
     TestLexer lexer = new TestLexer(in); 
     CommonTokenStream tokens = new CommonTokenStream(lexer); 
     TestParser parser = new TestParser(tokens); 
     parser.parse(); 
    } 
} 

parse 
    : block EOF 
    ; 

block 
@init{int temp = 0;} 
    : (i=statement[temp] {temp = $i.ret;} ';')+ 
    ; 

statement [int param] returns [int ret] 
    : Number {$ret = $param + Integer.parseInt($Number.text);} 
    {System.out.printf("param=\%d, Number=\%s, ret=\%d\n", $param, $Number.text, $ret);} 
    ; 

Number 
    : '0'..'9'+ 
    ; 

当你生成一个解析器和词法分析器从它并编译这些类,执行TestParser类,你会看到下面的内容印在你的控制台上:

param=0, Number=1, ret=1 
param=1, Number=2, ret=3 
param=3, Number=3, ret=6 
param=6, Number=4, ret=10 
+0

非常感谢。这正是我需要的。 – 2010-04-21 14:47:13

+0

好听@Chris。别客气。 – 2010-04-21 16:02:39