ANTLR4中的规则变量

Bra*_*ace 5 java migration variables 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]
    ...
Run Code Online (Sandbox Code Playgroud)

但是,使用v4中的规则返回这些自定义上下文对象而不是我明确告诉他们返回的内容,事情都搞砸了.什么是v4方式这样做?

Bra*_*ace 4

这里有多种情况:

  • 访问传入的变量 ( layout)
  • 访问当前规则的返回值 ( extractor)
  • 访问局部变量 ( first, next)

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

当访问传入的变量或当前规则的返回值时,您只需在规则定义中给定的名称前面加上$.

  • 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); }
;
Run Code Online (Sandbox Code Playgroud)

您需要检查是否$p为 null,但大多数情况下这会导致“缺少属性访问”错误。ANTLR4 做了一个特殊的例外,以便您可以检查它,它if条件中使用时适用(例如,重构它以使用三元运算符,仍然会导致错误)。

single_lname returns [String s]
    : p=LNAME_PREFIX? r=NAME { 
        if ($p == null) {
            $s = toNameCase($r.text);
        } else {
            $s = $p.text + toNameCase($r.text);
        }
    }
;
Run Code Online (Sandbox Code Playgroud)

更新后的规则

把它们放在一起,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); })* 
    ;
Run Code Online (Sandbox Code Playgroud)