Как мне убедить Bison разобрать часть файла?

Если есть входной файл формы:

BEGIN
  stuff....
END

BEGIN
  stuff ...
END

и мой файл .y имеет вид

%token BEGIN
%token END
%start begin

begin:  BEGIN stuff END

и то, что я хочу сделать, это многократно вызывать yyparse, анализируя один BEGIN/END, пока eof.

Первый вызов yyparse сообщает:

syntax error, unexpected BEGIN, expecting $end.

что имеет смысл; bison хочет разобрать весь файл. Есть ли способ сделать bison более гибким в определении $end?


person user1538392    schedule 19.07.2012    source источник


Ответы (2)


Самый простой способ — добавить (пару) продуктов в начало файла .y:

input: begin | input begin;

Теперь yyparse будет анализировать несколько входных данных. Если вы ДЕЙСТВИТЕЛЬНО хотите вызывать yyparse несколько раз, вы, вероятно, могли бы избежать наказания:

begin: BEGIN stuff END { YYACCEPT; } ;

YYACCEPT — это специальная встроенная функция, которая заставляет yyparse немедленно возвращать значение 0 (после выполнения необходимой внутренней очистки). Я говорю «вероятно», так как это сработает только в том случае, если bison уменьшит begin с уменьшением по умолчанию (без просмотра вперед). Это будет иметь место, если это единственное правило для begin, а begin не используется в контексте, где его распознавание требует просмотра вперед.

person Chris Dodd    schedule 19.07.2012
comment
Я бы предпочел многократно вызывать yyparse; это имеет больше смысла для этого конкретного приложения. - person user1538392; 19.07.2012
comment
Я бы предпочел многократно вызывать yyparse; это имеет больше смысла для этого конкретного приложения. YYACCEPT возвращает немедленно, не выполняя семантическое правило; Я добавил begin0: begin {YYACCEPT;} ; чтобы заставить его работать. Теперь он обрабатывает все блоки и ошибки в EOF. Мне нужно добавить пустое правило для обработки EOF, и я думаю, что это заставит его работать. Спасибо. - person user1538392; 19.07.2012
comment
Да, добавление пустого правила, которое устанавливает указатель корня дерева на нуль, чтобы сообщить вызывающему приложению, что eof был достигнут, похоже, работает. - person user1538392; 19.07.2012
comment
YYACCEPT находится в семантическом действии -- если у вас уже было действие с begin, вы можете добавить YYACCEPT к (концу) этого действия - person Chris Dodd; 20.07.2012
comment
›› YYACCEPT находится в смысловом действии. Упс. Да. Я отформатировал его как мидруле и запутался. Теперь все лучше. Спасибо. - person user1538392; 21.07.2012
comment
Пустое правило на самом деле не работает; он возвращается на EOF или на тарабарщину. Я полагаю, мне нужно правило EOF, но я не знаю, как это сделать. - person user1538392; 21.07.2012
comment
Хорошо, посмотрел на bison-end-of-file, и теперь он проходит все мои регрессионные тесты. - person user1538392; 21.07.2012

Добавьте это в свою грамматику:

all_begins: begins
          ;

begins: begins begin
      | begin
      ;

Замените %start на:

%start all_begins

И просто вызовите yyparse() один раз.

person David Gorsline    schedule 19.07.2012