パーサーが何をすべきかわからない場合のデフォルトの動作は、次のようなメッセージを端末に出力することです。
1:23 行目の '}' に DECIMAL がありません
これは良いメッセージですが、場所が間違っています。これは例外として受け取りたいと思います。
を使用してみましたBailErrorStrategy
が、これはメッセージなしで a をスローしParseCancellationException
ます ( a が原因で、InputMismatchException
メッセージもありません)。
メッセージに有用な情報を保持しながら、例外を介してエラーを報告する方法はありますか?
私が実際に求めているのは次のとおりです。通常、ルールでアクションを使用してオブジェクトを構築します。
dataspec returns [DataExtractor extractor]
@init {
DataExtractorBuilder builder = new DataExtractorBuilder(layout);
}
@after {
$extractor = builder.create();
}
: first=expr { builder.addAll($first.values); } (COMMA next=expr { builder.addAll($next.values); })* EOF
;
expr returns [List<ValueExtractor> values]
: a=atom { $values = Arrays.asList($a.val); }
| fields=fieldrange { $values = values($fields.fields); }
| '%' { $values = null; }
| ASTERISK { $values = values(layout); }
;
次に、パーサーを呼び出すと、次のようになります。
public static DataExtractor create(String dataspec) {
CharStream stream = new ANTLRInputStream(dataspec);
DataSpecificationLexer lexer = new DataSpecificationLexer(stream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
DataSpecificationParser parser = new DataSpecificationParser(tokens);
return parser.dataspec().extractor;
}
私が本当に欲しいのは
dataspec()
入力を解析できない場合に例外 (理想的にはチェックされたもの) をスローするための呼び出し- その例外が有用なメッセージを持ち、問題が見つかった行番号と位置へのアクセスを提供するため
次に、ネットワーク接続の切断や破損したファイルの読み取りなどを処理するのと同じ方法で、ユーザーに有用なメッセージを表示するのに最適な場所に、その例外をコールスタックにバブルアップさせます。
アクションがANTLR4で「高度」と見なされるようになったので、奇妙な方法で物事に取り組んでいる可能性がありますが、これを行うための「高度ではない」方法が何であるかを調べていません私たちのニーズに対してうまく機能しています。