Das Standardverhalten, wenn der Parser nicht weiß, was zu tun ist, besteht darin, Nachrichten wie folgt an das Terminal zu drucken:
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 verwenden BailErrorStrategy
, aber dies wirft eine ParseCancellationException
ohne Nachricht (verursacht durch eine InputMismatchException
, auch ohne Nachricht).
Gibt es eine Möglichkeit, Fehler über Ausnahmen zu melden, während die nützlichen Informationen in der Nachricht erhalten bleiben?
Folgendes ist mir wirklich wichtig: Normalerweise verwende ich Aktionen in Regeln, um ein Objekt aufzubauen:
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
- Damit der
dataspec()
Aufruf eine Ausnahme auslöst (idealerweise eine aktivierte), wenn die Eingabe nicht analysiert werden kann - Damit diese Ausnahme eine nützliche Nachricht enthält und Zugriff auf die Zeilennummer und die Position bietet, an der das Problem gefunden wurde
Dann lasse ich diese Ausnahme den Callstack dahin sprudeln, wo es am besten geeignet ist, dem Benutzer eine nützliche Nachricht zu präsentieren - genauso 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" angesehen werden, also gehe ich die Dinge vielleicht auf seltsame Weise an, aber ich habe nicht untersucht, wie die "nicht fortgeschrittene" Art, dies zu tun, seit dieser Weise aussehen würde hat gut für unsere Bedürfnisse gearbeitet.