Функция lexer yylex
должна вернуть 0, чтобы указать конец ввода. Однако ваша реализация просто проходит через значение, возвращаемое getchar
, которое будет EOF
(обычно -1).
Кроме того, ваш ввод почти наверняка будет содержать символ новой строки, который также будет передан парсеру.
Поскольку анализатор не распознает ни \n
, ни EOF
, он выдает сообщение об ошибке, когда получает один из них.
Как минимум, вы должны изменить yylex
правильно реагировать на конец ввода:
int yylex(void) {
int ch = getchar();
return (ch == EOF) ? 0 : ch;
}
Но вам все равно придется иметь дело с новой строки charactets, либо путем обработки их в лексический (возможно, не обращая внимания их или, возможно, возвращение конца ввода imdication), или путем обработки их в вашей грамматике.
Обратите внимание, что парсеры, основанные на бизонах/yacc, всегда анализируют весь входной поток, а не только самую длинную последовательность, удовлетворяющую грамматике. Это можно скорректировать с некоторой работой - см. Документацию для специального действия YYACCEPT
, но стандартное поведение обычно является желательным при разборе.
Кстати, пожалуйста, используйте стандартные условные условные обозначения в ваших грамматиках bison/yacc, чтобы избежать проблем и во избежание запутывания читателей. Обычно мы резервируем UPPER_CASE
для символов терминала, так как они также используются в качестве констант времени компиляции в лексере. Нетерминалы обычно записываются в lower_case
, хотя некоторые предпочитают использовать CamelCase
. Для терминалов вам необходимо избегать использования имен, зарезервированных стандартной библиотекой (например, EOF
) или (f) lex (BEGIN
) или bison/yacc (END
). В руководствах есть списки зарезервированных имен.