2009-11-18 6 views
9

Если я забыл положить пустую строку в конце любого из моих файлов, моя программа получит синтаксическую ошибку. Проблема в том, что моя грамматика ожидает, что новая строка закончит текущую строку. Поскольку новая строка не существует, бизон генерирует синтаксическую ошибку, поскольку она не завершает правило.bison конец файла

Как это решить? Я пробовал сделать <<EOF>> return MY_EOF НО, но когда я делаю это, лекс вылетает из-за ужасной смерти. Я думаю, что есть код в EOF по умолчанию, который я не звоню. Я понятия не имею, какие функции они могут быть. Использование EOF создать ошибку symbol EOF is used, but is not defined as a token and has no rules

ответ

14

Вы можете использовать гибкое EOF правила для добавления новой строки к входу:

<<EOF>> { static int once = 0; return once++ ? 0 : '\n' } 
+1

Великий волшебный трюк, работает для меня. – blueshift

+4

Обратите внимание, что если вы хотите сделать это в лексисе повторного входа, вы должны вместо этого использовать '{static int once = 0; return (один раз =! один раз)? NEWLINE: 0; } ', поскольку в противном случае первый файл будет препятствовать распознаванию новых строк при любых будущих вызовах. –

+0

@ Hach-Que Хорошая точка - в этом случае используйте: '{if (! Yyextra-> eof) {yyextra-> eof = true; return NEWLINE; } else {yyterminate(); }} 'и добавьте поле« eof »в ваш контекст. – nevelis

4

В вашем ЛЕКСЕ файл

#define yyterminate() return token::END 

В файле YACC

%token END 0 "end of file" 
+0

Я видел гавань лексема :: до того, используете ли вы ++ версии C? Мне пришлось изменить его, чтобы вернуть MY_END Но% токена MY_END 0 «конец файла» получите мне предупреждение. ./test.y:90.11-75: предупреждение: правило никогда не уменьшается из-за конфликтов: $ accept: program "end of file «'. Кажется, что работает, но я не уверен на 100%. – 2009-11-19 09:21:27

+0

Да, это версия на С ++. – DevDevDev

2

Фактически, чтобы поймать конец файла в lex | flex, вы можете использовать yywrap() функция, которая вызывается лексическим анализатором, если достигнут конец входного файла.

Это решение доступно как для lex, так и для flex.the обратного вызова yywrap() указывает EOF, поэтому вы можете переопределить эту функцию и ввести задачу, необходимую в конце входного потока.

+1

. Вы пропустили 'yywrap () '? – blueshift

+2

@blueshift Нет, я не пропустил yywarp, это макрос, автоматически вызываемый, когда мы доходим до конца текущего буфера, он возвращает 1, когда нет буфера для чтения или 0, если есть – Aymanadou

+3

Я использую flex и имею 'yywrap() ', но не' yywarp() '. Ты уверен? – blueshift

1

Предыдущие работы отлично подходят для меня.

Если вы используете C Бизон (не C++), просто используйте END для маркера :: END и в YACC файле %token END

Если бы еще один вопрос, после этого, если макросы не возвращаются YY_NULL, он никогда не заканчивается (бесконечный цикл)

Она может быть решена так:

bool term = false; 
#define yyterminate() return (term = !term)?END : YY_NULL