Fehlerbehandlung in ANTLR4

Das Standardverhalten, wenn der Parser nicht weiß, was zu tun ist, ist das Drucken von Nachrichten an das Terminal wie folgt:

Zeile 1:23 fehlt DECIMAL bei '}'

Dies ist eine gute Nachricht, aber am falschen Ort. Ich möchte dies lieber als Ausnahme erhalten.

Ich habe versucht, die zu verwendenBailErrorStrategy, aber das wirft einParseCancellationException ohne Nachricht (verursacht durch aInputMismatchException(auch ohne Nachricht).

Gibt es eine Möglichkeit, Fehler über Ausnahmen zu melden, während die nützlichen Informationen in der Nachricht erhalten bleiben?

Ich bin wirklich auf der Suche nach: Normalerweise verwende ich Aktionen in Regeln, um ein Objekt zu erstellen:

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); }
    ;

Wenn ich dann den Parser aufrufe, mache ich so etwas:

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;
}

Alles was ich wirklich will ist

für diedataspec() Aufruf zum Auslösen einer Ausnahme (im Idealfall einer aktivierten), wenn die Eingabe nicht analysiert werden kannDamit diese Ausnahme eine nützliche Nachricht enthält und Sie Zugriff auf die Zeilennummer und die Position erhalten, an der das Problem gefunden wurde

Dann lasse ich diese Ausnahmebedingung den Callstack hochsprudeln, um dem Benutzer eine nützliche Nachricht zu übermitteln - genau so, wie ich mit einer unterbrochenen Netzwerkverbindung, dem Lesen einer beschädigten Datei usw. umgehen würde.

Ich habe gesehen, dass Aktionen in ANTLR4 jetzt als "fortgeschritten" betrachtet werden, also gehe ich vielleicht auf seltsame Weise vor, aber ich habe nicht untersucht, wie die "nicht fortgeschrittene" Art dies zu tun wäre, seitdem hat gut für unsere Bedürfnisse gearbeitet.

Antworten auf die Frage(3)

Ihre Antwort auf die Frage