ANTLR4 中的规则变量 [英] Rule variables in ANTLR4
问题描述
我正在尝试将我的语法从 v3 转换为 v4,但遇到了一些问题.
I'm trying to convert my grammar from v3 to v4 and having some trouble.
在 v3 中我有这样的规则:
In v3 I have rules like this:
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 方法是什么?
However, with rules in v4 returning these custom context objects instead of what I explicitly told them to return, things are all messed up. What's the v4 way to do this?
推荐答案
这里有多个案例:
- 访问传入的变量(
layout
) - 访问当前规则的返回值(
extractor
) - 访问局部变量(
first
,next
)
当访问传入的变量或当前规则的返回值时,您只需在规则定义中给定的名称前加上 $
.
When accessing passed-in variables or the return value of the current rule you simply need to prefix the name given in the rule definition with $
.
layout
变成$layout
extractor
变成$extractor
layout
becomes$layout
extractor
becomes$extractor
显然需要做的是引用根据返回值规则的returns
子句命名的变量成员.
Evidently what needs to be done is to reference the variables' member which is named according to the returns
clause of the rule which returned the value.
例如,first
是从 expr
规则中捕获结果,expr
将其返回值命名为 ext
,意思是:
For example, first
is capturing the result from the expr
rule, and expr
names its return value ext
, meaning that:
first
变成$first.ext
next
变成$next.ext
first
becomes$first.ext
next
becomes$next.ext
与在 v3 中可以将某些变量作为常规 java 字段引用不同,在 所有 情况下(包括在操作中)使用 $
形式是必要的,在 @init
和 @after
阻塞,以及将变量传递给其他规则时.
Unlike in v3 where you could reference certain variables as regular java fields, using the $
form is necessary in all cases, including in actions, in the @init
and @after
blocks, and when passing variables to other rules.
如果您在局部变量中捕获可选标记,那么您可能会遇到空指针异常,因为您正在引用该变量的属性.
If you're capturing optional tokens in a local variable, you may run into null pointer exceptions now that you're referencing an attribute of that variable.
single_lname returns [String s]
: p=LNAME_PREFIX? r=NAME { $p.text + toNameCase($r.text); }
;
您需要检查 $p
是否为空,但大多数情况下这会导致缺少属性访问"错误.ANTLR4 做了一个特殊的例外,以便您可以检查它,仅适用于在 if
条件中使用时(例如,重构它以使用三元运算符,仍然会导致在错误中).
You'll need to check whether $p
is null, but most of the time this would result in a "missing attribute access" error. ANTLR4 makes a special exception so that you can check this, which only applies when used in an if
condition (refactoring this to use the ternary operator, for example, will still result in the error).
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); })*
;
这篇关于ANTLR4 中的规则变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!