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方式这样做?
这里有多种情况:
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)