У меня очень простая грамматика, которая (я думаю) должна позволять добавлять только два элемента, например 1+1
или 2+3
.
grammar dumbCalculator;
expression: simple_add EOF;
simple_add: INT ADD INT;
INT:('0'..'9');
ADD : '+';
Я создаю свои классы С#, используя официальный файл jar ANTLR.
java -jar "antlr-4.9-complete.jar" C:\Users\Me\source\repos\ConsoleApp2\ConsoleApp2\dumbCalculator.g4 -o C:\Users\Me\source\repos\ConsoleApp2\ConsoleApp2\Dumb -Dlanguage=CSharp -no-listener -visitor
Что бы я ни пытался, синтаксический анализатор продолжает добавлять завершающие элементы, хотя это не должно быть разрешено.
Например, "1+1+1"
правильно анализируется как AST:
expression
simple_add
1
+
1
+
1
Хотя я специально написал, что expression
должно быть simple_add
, тогда EOF
и simple_add
это просто INT ADD INT
. Я понятия не имею, почему остальные принимаются, я ожидаю, что ANTLR выдаст исключение.
Вот как я тестирую свой парсер:
var inputStream = new AntlrInputStream("1+1+1");
var lexer = new dumbCalculatorLexer(inputStream);
lexer.RemoveErrorListeners();
lexer.AddErrorListener(new ThrowExceptionErrorListener());
var commonTokenStream = new CommonTokenStream(lexer);
var parser = new dumbCalculatorParser(commonTokenStream);
parser.RemoveErrorListeners();
parser.AddErrorListener(new ThrowExceptionErrorListener());
var ex = parser.expression();
ExploreAST(ex);
Почему остальная часть вывода принимается?
Классический сценарий, я нахожу свою ошибку через 5 минут после публикации в Stack Overflow.
Для тех, кто столкнулся с подобным сценарием, это произошло потому, что я явно не установил ErrorHandler
в своем синтаксическом анализаторе.
Наивно я ожидал, что все AddErrorListener
обработают ошибки, но каким-то образом есть определенная вещь, если вам нужно обработать ошибки перед посещением дерева.
мне нужно было добавить
parser.ErrorHandler = new BailErrorStrategy();
После этого я действительно получил исключения для неправильных входных строк.
Вероятно, это неправильно, я позволю тому, кто лучше знает ANTLR, прокомментировать это.