El comportamiento predeterminado cuando el analizador no sabe qué hacer es imprimir mensajes en la terminal como:
línea 1:23 falta DECIMAL en '}'
Este es un buen mensaje, pero en el lugar equivocado. Prefiero recibir esto como una excepción.
Intenté usar el BailErrorStrategy
, pero esto arroja un ParseCancellationException
sin un mensaje (causado por un InputMismatchException
, también sin un mensaje).
¿Hay alguna manera de que pueda informar errores a través de excepciones mientras conserve la información útil en el mensaje?
Esto es lo que realmente busco: normalmente uso acciones en reglas para construir un objeto:
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); }
;
Luego, cuando invoco el analizador, hago algo como esto:
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;
}
Todo lo que realmente quiero es
- para que la
dataspec()
llamada arroje una excepción (idealmente una marcada) cuando la entrada no se puede analizar - para que esa excepción tenga un mensaje útil y proporcione acceso al número de línea y la posición donde se encontró el problema
Luego dejaré que esa excepción burbujee en la pila de llamadas donde sea más adecuado para presentar un mensaje útil al usuario, de la misma manera que manejaría una conexión de red caída, leer un archivo corrupto, etc.
Vi que las acciones ahora se consideran "avanzadas" en ANTLR4, así que tal vez estoy haciendo las cosas de una manera extraña, pero no he investigado cuál sería la forma "no avanzada" de hacer esto desde esta manera. ha funcionado bien para nuestras necesidades.