私はANTLR4のパーサーの特定のエラーメッセージを取得したいと思います。 そして、私はエラーを処理する2つの方法があることを発見しました:errorListenerとerrorHandler。ANTLR4のerrorListenerとerrorHandlerの違いは何ですか?
// set error handler
parser.removeErrorListeners();
parser.addErrorListener(new QueryErrorListener());
parser.setErrorHandler(new BailErrorStrategy());
しかし、私はそれらの違いについて混乱しています。
私は、errorListenerは特定のエラーメッセージを受け取ることができますが、それを印刷することもログを記録することもできますが、例外をスローすることはできません。ベローとして
は、ErrorListenerのimplemention:
public class QueryErrorListener extends BaseErrorListener {
private static final Logger LOGGER = LoggerFactory.getLogger(QueryDispatcher.class);
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol,
int line, int charPositionInLine, String msg,
RecognitionException e)
{
List<String> stack = ((Parser)recognizer).getRuleInvocationStack(); Collections.reverse(stack);
String errorMessage = "line "+line+":"+charPositionInLine+" at "+
offendingSymbol+": "+msg;
LOGGER.error("rule stack: "+stack);
LOGGER.error(errorMessage);
QueryParseErrorStrategy queryParseErrorStrategy = new QueryParseErrorStrategy();
}
}
同時に、のErrorHandlerは、任意の特定のメッセージなし例外ParseCancellationExceptionを投げることができます。
public class BailErrorStrategy extends DefaultErrorStrategy {
/** Instead of recovering from exception {@code e}, re-throw it wrapped
* in a {@link ParseCancellationException} so it is not caught by the
* rule function catches. Use {@link Exception#getCause()} to get the
* original {@link RecognitionException}.
*/
@Override
public void recover(Parser recognizer, RecognitionException e) {
for (ParserRuleContext context = recognizer.getContext(); context != null; context = context.getParent()) {
context.exception = e;
}
throw new ParseCancellationException(e);
}
/** Make sure we don't attempt to recover inline; if the parser
* successfully recovers, it won't throw an exception.
*/
@Override
public Token recoverInline(Parser recognizer)
throws RecognitionException
{
InputMismatchException e = new InputMismatchException(recognizer);
for (ParserRuleContext context = recognizer.getContext(); context != null; context = context.getParent()) {
context.exception = e;
}
throw new ParseCancellationException(e);
}
/** Make sure we don't attempt to recover from problems in subrules. */
@Override
public void sync(Parser recognizer) { }
}
私は怒鳴るよう、ParseCancellationExceptionから詳細メッセージを取得するには、転送方法を追加し、解決策を見つけることを試みるました。
私はRecognitionExceptionのTokenオブジェクトから何らかのメッセージを受け取ることができますが、行/ charPositionInLine/offendingSymbolメッセージしか見つけることができません。「xxxがない」などの詳細メッセージがどこにあるのかわかりません。 「yyy」を期待する」
public class ANTLRExceptionTransfer {
public static SemanticException transfer(RecognitionException re) {
String errorMsg = "";
Recognizer<?, ?> recognizer = re.getRecognizer();
Token offendingSymbol = re.getOffendingToken();
int line = offendingSymbol.getLine();
int charPositionInLine = offendingSymbol.getCharPositionInLine();
// ????????
String msg = "";
List<String> stack = ((Parser)recognizer).getRuleInvocationStack();
Collections.reverse(stack);
String errorMessage = "rule stack: "+stack;
errorMessage = "\nline "+line+":"+charPositionInLine+" at "+
offendingSymbol+": "+msg;
return new SemanticException(errorMessage);
}
}
errorHandlerを使用するのは正しい方法ですか? 特定のエラーメッセージで例外を取得するにはどうすればよいですか?
私は今RecognitionExceptionから基本情報を得ることができますが、errorListenerのような読み取り可能なメッセージを作成する方法はまだ分かりません[行1:4632 [@ 1289,4632:4632 = '}'、<46>、1:4632 ]:無関係な入力 '}'期待する '、']。 ANTLR4が提供する利用可能な方法はありますか? – lulijun