如何避免使用 ANTLR3 构建中间体和无用的 AST 节点



我写了一个ANTLR3语法,细分为更小的规则以提高可读性。例如:

messageSequenceChart:
  'msc' mscHead bmsc 'endmsc' end
;
# Where mscHead is a shortcut to :
mscHead:
  mscName mscParameterDecl? timeOffset? end
  mscInstInterface? mscGateInterface
;

我知道内置的ANTLR AST构建功能允许用户声明不会在最终AST中的中间AST节点。但是,如果您手动构建 AST 会怎样?

messageSequenceChart returns [msc::MessageSequenceChart* n = 0]:
  'msc' mscHead bmsc'endmsc' end
  {
    $n = new msc::MessageSequenceChart(/* mscHead subrules accessors like $mscHead.mscName.n ? */
                                       $bmsc.n);
  }
;
mscHead:
  mscName mscParameterDecl? timeOffset? end
;

文档没有谈论这样的事情。因此,看起来我必须为每个中间规则创建节点才能访问其子规则结果。

有谁知道更好的解决方案?

谢谢。

您可以通过让子规则返回多个值并仅访问您感兴趣的值来解决此问题。

以下演示演示了如何执行此操作。虽然它不是 C 语言,但我相信您将能够对其进行调整,使其符合您的需求:

grammar Test;
parse
  :  sub EOF {System.out.printf("second=%sn", $sub.second);}
  ;
sub returns [String first, String second, String third]
  :  a=INT b=INT c=INT
     {
       $first = $a.text;
       $second = $b.text;
       $third = $c.text;
     }
  ;
INT
  :  '0'..'9'+
  ;
SPACE
  :  ' ' {$channel=HIDDEN;}
  ;

如果您使用生成的解析器解析输入"12 34 56",则second=34将打印到控制台,如运行后所示:

import org.antlr.runtime.*;
public class Main {
  public static void main(String[] args) throws Exception {
    TestLexer lex = new TestLexer(new ANTLRStringStream("12 34 56"));
    TokenStream tokens = new TokenRewriteStream(lex);
    TestParser parser = new TestParser(tokens);
    parser.parse();
  }
}

因此,parse规则中的快捷方式,例如 $sub.INT ,或者$sub.$a访问三个INT令牌之一,不幸的是,这是不可能的。

最新更新