一次只处理一个子元素的n元ANTLR

一次只处理一个子元素的n元ANTLR,antlr,Antlr,我目前有一个使用AST的编译器,其中代码块的所有子级都位于同一级别(即block.children={stm1、stm2、stm3等…})。我试图对这棵树进行活性分析,这意味着我需要获取stm1处理返回的值,然后将其传递给stm2,然后获取stm2返回的值,然后将其传递给stm3,依此类推。当AST以这种方式构造时,我看不到以这种方式执行子规则的方法 有没有一种方法可以让我将子语法项的执行与给定的AST链接起来,或者我必须经历一个痛苦的过程:重构解析器以生成嵌套结构,并更新编译器的其余部分以使用

我目前有一个使用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
    ;
解析器(或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
解析器(或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

非常感谢你。这正是我需要的。非常感谢。这正是我需要的。