Ho una semplice grammatica ANLTR e un accompagnatore. Tutto funziona alla grande, a meno che l'input non sia valido. Se l'input non è valido, gli errori vengono ingeriti e la mia calcolatrice esce con l'output sbagliato.È possibile generare un'eccezione se l'input non è valido?
Ho provato a implementare un listener di errori, a cavallo del metodo Recover
del lexer e ... beh ... una mezza dozzina di altre cose oggi. Qualcuno può mostrarmi come lanciare semplicemente un errore invece di inghiottire brutti "token"? (. Io uso le virgolette perché sono non gettoni a tutti i personaggi non sono definiti nella mia grammatica.)
ingresso valido:
1 + 2 * 3 - 4
Invalid Input:
1 + 2 + 3 (4)
Voglio lanciare un ArgumentException
se il parser/lexer trova la parentesi (o qualsiasi altro carattere non definito). Attualmente, i personaggi non validi sembrano scomparire nell'etere e il parser si muove semplicemente come se nulla fosse sbagliato.
Se lo eseguo nella console con il comando grun
, ottengo il seguente output, quindi riconosce i token non validi su qualche livello.
linea 1: errore di 9 Token riconoscimento a: '(' errore
linea di token 01:11 riconoscimento a: ')'
e questo albero sintattico risultante.
BasicMath.g4
grammar BasicMath;
/*
* Parser Rules
*/
compileUnit : expression+ EOF;
expression :
expression MULTIPLY expression #Multiplication
| expression DIVIDE expression #Division
| expression ADD expression #Addition
| expression SUBTRACT expression #Subtraction
| NUMBER #Number
;
/*
* Lexer Rules
*/
NUMBER : INT; //Leave room to extend what kind of math we can do.
INT : ('0'..'9')+;
MULTIPLY : '*';
DIVIDE : '/';
SUBTRACT : '-';
ADD : '+';
WS : [ \t\r\n] -> channel(HIDDEN);
Calcolatrice:
public static class Calculator
{
public static int Evaluate(string expression)
{
var lexer = new BasicMathLexer(new AntlrInputStream(expression));
var tokens = new CommonTokenStream(lexer);
var parser = new BasicMathParser(tokens);
var tree = parser.compileUnit();
var visitor = new IntegerMathVisitor();
return visitor.Visit(tree);
}
}
Dai un'occhiata a questa risposta dell'autore Antlr4cs: http://stackoverflow.com/a/18486405/2573395 – Alex
Yup. Ho provato che @Alex. Ho ereditato dal 'BaseErrorListener' e l'ho collegato al mio parser, ma nessuno di questi metodi è mai stato chiamato. – RubberDuck
Nota per se stessi, cavalcare qualcosa qui dentro potrebbe aiutare. Sembra che siano andate le lunghe distanze per garantire che l'analisi sia completa quando ne ho bisogno. https://github.com/antlr/antlr4/blob/master/runtime/Java/src/org/antlr/v4/runtime/DefaultErrorStrategy.java – RubberDuck