パーサーが何をすべきかわからない場合のデフォルトの動作は、次のように端末にメッセージを出力することです。
1:23行目 '}'にDECIMALがありません
これは良いメッセージですが、間違った場所にあります。例外としてこれを受け取りたいです。
を使用してみましBailErrorStrategy
たParseCancellationException
が、メッセージなしでがスローされます(、によって引き起こされ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ではアクションが「高度」と見なされるようになったので、奇妙な方法で物事を進めているのかもしれませんが、この方法以降、これを行う「高度でない」方法がどうなるかについては調べていません。私たちのニーズのためにうまく機能しています。