bison: одна ошибка вызывает дополнительную, но некорректную ошибку

В разделе класса моего кода, если я пишу об ошибке, несколько строк будут сообщены как ошибки, хотя этого не должно быть. Я помещаю «| error» в определенные места, где хорошо/безопасно восстанавливаться после ошибок, но я не думаю, что он его использует. Может быть, он пытается где-то возобновить среднее выражение?

Есть ли способ заставить Bison попытаться восстановиться в определенных местах? Как это работает и что я могу делать не так?

Я помещаю строку ошибки рядом с циклом. Вот пример:

SomeRuleLoop:
    | Rule ',' SomeRuleLoop
Rule:
      A
    | B
    | C
    | Error
A:
      AA AAB AABC
    | AA AAB AABC Z
...

Вот пример моих правил. Я вижу «ошибку funcBody» в своей консоли, однако в следующей строке появляется ошибка из-за первой ошибки. Несмотря на то, что каждое funcBodyRule является автономным.

funcBodyLoop:
    | funcBodyLoop funcBody

funcBody:
      funcBodyRule
    | error { printf("funcBody error"); $$=0; }
    | '#' EQ { printf("still in funcBody\n"); $$=0; }

Пробовал писать #== между строкой с первой ошибкой и строкой со второй. Я написал это, чтобы проверить, находится ли синтаксический анализатор в цикле funcbody. Это не выдает ошибку, поэтому это. Неважно, я добавил printf, а строка не печатается, так что, может быть, ее больше нет в цикле функций? Как я могу это исправить?


person Community    schedule 19.11.2010    source источник
comment
Будет почти невозможно помочь без некоторого кода, который поможет нам. Но это должен быть минимальный код, а не несколько сотен строк.   -  person Jonathan Leffler    schedule 20.11.2010
comment
@Jonathan Leffler: Вот где петля. я изменил свой вопрос   -  person    schedule 20.11.2010
comment
Вы знаете, что Yacc (Bison) чувствителен к регистру, поэтому альтернатива «Ошибка» не совпадает с «ошибкой» (которая «встроена» и имеет особое значение для восстановления после ошибки).   -  person Jonathan Leffler    schedule 20.11.2010
comment
@Jonathan Leffler: Хорошо, заметил. Я проверил, и я нигде не использую «Ошибка», только «Ошибка»   -  person    schedule 20.11.2010
comment
Пришлите мне код - смотрите мой профиль; Я посмотрю, смогу ли я разобраться в проблеме. Боюсь, этого фрагмента недостаточно для продолжения.   -  person Jonathan Leffler    schedule 26.11.2010
comment
@Jonathan Leffler: Урезанная версия, похоже, отлично справляется с ошибкой. Я спишу проблему на странности с конфликтами сдвига/уменьшения. Там ‹15 и код @(a,b,c) с ошибкой на ')', что не имеет смысла, потому что @( используется только в качестве параметров с ')' в конце. Я предположу, что это проблема с конфликтами, и исправлю это в другой день.   -  person    schedule 26.11.2010
comment
ОК - удачи в решении вопроса. Конфликты могут быть раздражающими.   -  person Jonathan Leffler    schedule 26.11.2010


Ответы (2)


Yacc и Bison обычно используют леворекурсивные правила, а показанные правила не являются леворекурсивными.

Как показано, первое правило эквивалентно:

SomeRuleLoop:
        /* Nothing */
    |   Rule ',' SomeRuleLoop
    ;

Это праворекурсивное правило, которое говорит, что SomeRuleLoop — это либо пустая строка токенов, либо правило, за которым следует запятая и еще несколько SomeRuleLoop. Обратите внимание, что это означает, что SomeRuleLoop заканчивается запятой, что, вероятно, не то, что вы имели в виду.

Первое правило, вероятно, должно гласить:

SomeRuleLoop:
        Rule
    |   SomeRuleLoop ',' Rule
    ;

Обратите внимание, что разрешение пустых альтернатив важно, но добавление их повсюду делает грамматику неоднозначной (больше конфликтов сдвига/уменьшения).


Вам также необходимо использовать маркер «ошибка» (все строчные буквы), а не «Ошибка» (смешанный регистр), чтобы указать точку, в которой может произойти восстановление после ошибки.

Однако я не уверен, в чем заключаются остальные ваши проблемы...

person Jonathan Leffler    schedule 20.11.2010
comment
Подожди, подожди... ты шутишь. Левая рекурсия? НЕ правильная рекурсия? Yikes, я делал это неправильно. Это может решить проблему с ошибкой. отпишусь когда все исправлю - person ; 20.11.2010
comment
Я совсем запутался. Я изменил правила, чтобы они оставались рекурсивными. Я вижу, что мое сообщение об ошибке печатается. Тем не менее, я все еще получаю сообщение об ошибке. я обновил вопрос - person ; 26.11.2010

Принуждение ';' или новые строки в конце ошибки решают ее. (| error my_end_of_statenent вместо | error)

person Community    schedule 09.02.2011