ANTLR4中的规则变量

时间:2013-08-07 17:34:46

标签: java variables migration rules antlr4

我正在尝试将我的语法从v3转换为v4并遇到一些麻烦。

在第3版我有这样的规则:

dataspec[DataLayout layout] returns [DataExtractor extractor]
    @init {
        DataExtractorBuilder builder = new DataExtractorBuilder(layout);
    }
    @after {
        extractor = builder.create();
    }
    : first=expr { builder.addAll(first); } (COMMA next=expr { builder.addAll(next); })* 
    ;

expr returns [List<ValueExtractor> ext]
    ...

然而,由于v4中的规则返回这些自定义上下文对象而不是我明确告诉他们返回的内容,所以事情都搞砸了。 v4的方法是什么?

1 个答案:

答案 0 :(得分:4)

这里有多种情况:

  • 访问传入的变量(layout
  • 访问当前规则的返回值(extractor
  • 访问本地变量(firstnext

传入变量和当前规则的返回值

访问传入变量或当前规则的返回值时,您只需要在规则定义中为$添加前缀。

  • layout变为$layout
  • extractor变为$extractor

本地变量

显然需要做的是引用变量的成员,该成员是根据返回值的规则的returns子句命名的。

例如,first正在从expr规则中捕获结果,expr将其返回值命名为ext,这意味着:

  • first变为$first.ext
  • next变为$next.ext

何时使用$表格

与在v3中您可以将某些变量引用为常规Java字段的情况不同,在所有情况下,包括在操作中,$@init中都需要使用@after表单single_lname returns [String s] : p=LNAME_PREFIX? r=NAME { $p.text + toNameCase($r.text); } ; 阻止,以及将变量传递给其他规则时。

其他陷阱

如果您在局部变量中捕获可选标记,则可能会遇到空指针异常,因为您正在引用该变量的属性。

$p

您需要检查if是否为空,但大多数时候这会导致“缺少属性访问”错误。 ANTLR4发出一个特殊异常,以便您可以在single_lname returns [String s] : p=LNAME_PREFIX? r=NAME { if ($p == null) { $s = toNameCase($r.text); } else { $s = $p.text + toNameCase($r.text); } } ; 条件下使用时检查适用<例如,重构此操作以使用三元运算符,仍然会导致错误)。

dataspec

更新后的规则

将所有内容放在一起,dataspec[DataLayout layout] returns [DataExtractor extractor] @init { DataExtractorBuilder builder = new DataExtractorBuilder($layout); } @after { $extractor = builder.create(); } : first=expr { builder.addAll($first.ext); } (COMMA next=expr { builder.addAll($next.ext); })* ; 规则变为:

{{1}}