Manipulando Erros no ANTLR4
O comportamento padrão quando o analisador não sabe o que fazer é imprimir mensagens no terminal como:
linha 1:23 faltando DECIMAL em '}'
Esta é uma boa mensagem, mas no lugar errado. Eu prefiro receber isso como uma exceção.
Eu tentei usar oBailErrorStrategy
, mas isso lança umParseCancellationException
sem uma mensagem (causada por umInputMismatchException
, também sem uma mensagem).
Existe uma maneira que eu possa fazer para relatar erros através de exceções, mantendo as informações úteis na mensagem?
Aqui está o que eu realmente procuro - normalmente uso ações em regras para criar um 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); }
;
Então quando invoco o parser eu faço algo assim:
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;
}
Tudo o que eu realmente quero é
para odataspec()
chamada para lançar uma exceção (de preferência uma marcada) quando a entrada não pode ser analisadapara que a exceção tenha uma mensagem útil e forneça acesso ao número da linha e à posição em que o problema foi encontradoEntão, deixarei a exceção borbulhar no callstack para onde for mais adequado para apresentar uma mensagem útil ao usuário - da mesma maneira que lidaria com uma conexão de rede perdida, lendo um arquivo corrompido etc.
Eu vi que as ações agora são consideradas "avançadas" no ANTLR4, então talvez eu esteja fazendo as coisas de uma maneira estranha, mas eu não olhei para o que seria a maneira "não avançada" de fazer isso tem funcionado bem para as nossas necessidades.