代码之家  ›  专栏  ›  技术社区  ›  Chris Lieb

一次处理一个n元antlr ast一个子对象

  •  1
  • Chris Lieb  · 技术社区  · 16 年前

    我现在有一个编译器,它使用一个ast,其中一个代码块的所有子级都在同一级别(即block.children=={stm1、stm2、stm3等等…})。我正在尝试对此树进行活性分析,这意味着我需要获取stm1处理返回的值,然后将其传递给stm2,然后获取stm2返回的值并将其传递给stm3,依此类推。当ast是这样构造的时,我看不到以这种方式执行子规则的方法。

    是否有方法允许我将子语法项的执行与给定的ast链接起来,或者我必须经历重构解析器以生成嵌套结构并更新编译器的其余部分以使用新的ast的痛苦过程?


    示例antlr语法片段:

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

    我希望我不必去:

    block
        : ^(BLOCK statementList)
        ;
    statementList
        : ^(StmLst statement statement+) 
        | ^(StmLst statement)
        ;
    statement
        : // stuff
        ;
    
    1 回复  |  直到 16 年前
        1
  •  1
  •   Bart Kiers    16 年前

    解析器(或lexer)规则可以接受参数值并返回值。所以,在你的情况下,你可以这样做:

    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'+
      ;
    

    从中生成解析器和lexer并编译这些类后,执行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
    
    推荐文章