Mam prostą gramatykę ANLTR i towarzyszący mu Gość. Wszystko działa świetnie, chyba że dane wejściowe są nieprawidłowe. Jeśli dane wejściowe są nieprawidłowe, błędy zostaną połknięte, a mój kalkulator zostanie wyświetlony z nieprawidłowym wynikiem.Czy można podać wyjątek, jeśli dane wejściowe nie są prawidłowe?
Próbowałem już zaimplementować detektor błędów, korzystając z metody lexera Recover
i ... no ... jeszcze pół tuzina innych rzeczy. Czy ktoś może mi pokazać, jak po prostu rzucić błąd, zamiast połknąć złe "żetony"? (. Używam cudzysłowu, bo są nie znaki na wszystkie znaki są niezdefiniowane w moim gramatyki.)
Ważny Wejście:
1 + 2 * 3 - 4
Nieprawidłowy Wejście:
1 + 2 + 3 (4)
Chcę rzucić ArgumentException
, jeśli parser/lexer natknie się na nawias (lub dowolną inną niezdefiniowaną postać). Obecnie wydaje się, że nieprawidłowe postacie znikają w eterze, a parser po prostu ślizga się, jakby nic nie było nie tak.
Jeśli uruchomię go w konsoli za pomocą komendy grun
, otrzymam następujące dane wyjściowe, więc rozpoznaje nieprawidłowe tokeny na pewnym poziomie.
Linia 1: 9 błąd żeton na uznanie: '(' 1:11 błąd
linia znak uznania pod adresem: ')'
i ten wynikający drzewo parse.
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);
Kalkulator:
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);
}
}
Spójrz na tę odpowiedź od autora Antlr4cs: http://stackoverflow.com/a/18486405/2573395 – Alex
Yup. Próbowałem tego @Alex. Odziedziczyłem po 'BaseErrorListener' i dołączałem go do mojego parsera, ale żadna z tych metod nigdy nie została wywołana. – RubberDuck
Uwaga dla siebie, nad jazdą coś tutaj może pomóc. Wydaje się, że nie ma zbyt wiele czasu, aby zapewnić zakończenie analizowania, gdy potrzebuję go zatrzymać. https://github.com/antlr/antlr4/blob/master/runtime/Java/src/org/antlr/v4/runt/DefaultErrorStrategy.java – RubberDuck