ここには複数のケースがあります:
- 渡された変数へのアクセス (
layout
)
- 現在のルールの戻り値にアクセスする (
extractor
)
- ローカル変数へのアクセス (
first
、next
)
渡された変数と現在のルールの戻り値
渡された変数または現在のルールの戻り値にアクセスするときは、ルール定義で指定された名前の前に$
.
layout
になる$layout
extractor
になる$extractor
ローカル変数
returns
明らかに、値を返すルールの句に従って名前が付けられた変数のメンバーを参照する必要があります。
たとえば、はルールfirst
から結果を取得し、その戻り値に名前を付けます。つまり、次のことを意味します。expr
expr
ext
first
になる$first.ext
next
になる$next.ext
$
フォームを使用する場合
特定の変数を通常の Java フィールドとして参照できた v3 とは異なり、アクション内、ブロック内、変数を他のルールに渡すときなど、すべての場合でフォームを使用$
する必要があります。@init
@after
その他のトラップ
ローカル変数でオプションのトークンをキャプチャしている場合、その変数の属性を参照しているため、null ポインター例外が発生する可能性があります。
single_lname returns [String s]
: p=LNAME_PREFIX? r=NAME { $p.text + toNameCase($r.text); }
;
が nullかどうかを確認する必要があり$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); })*
;