这里有多种情况:
- 访问传入的变量 (
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); }
;
您需要检查是否$p
为空,但大多数情况下这会导致“缺少属性访问”错误。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);
}
}
;
更新的规则
综上所述,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); })*
;