Бесполезное правило из-за конфликтов в YACC

Сообщение об ошибке:

bison -vdy tjc.y
conflicts: 2 shift/reduce
tjc.y:72.26-29: warning: rule useless in parser due to conflicts: return_type: type

РЕДАКТИРОВАТЬ 2: дальнейшее сокращение грамматики до следующих правил. Та же ошибка из-за того же конфликта. Если я удалю field_decl в правилах, конфликт исчезнет.

member_decl:      field_decl |  method_decl;

field_decl: STATIC type IDENT EQ SEMI;

method_decl:      STATIC return_type IDENT LPAR RPAR;

type:             INT | FLOAT;

return_type:      type | VOID;

Вот раздел с конфликтом сдвига / уменьшения в y.output:

state 18

7 field_decl: STATIC type . IDENT EQ SEMI
14 return_type: type .

IDENT  shift, and go to state 23

IDENT  [reduce using rule 14 (return_type)]

Пожалуйста, помогите мне увидеть, что здесь происходит не так.

2 ответа

Решение

Я думаю, что анализ Perry того, почему у вас проблемы, является правильным.

Мне удалось получить аналогичные предупреждения с этой полной грамматикой (идентичной вашей, но с %token правила на месте, чтобы я мог его скомпилировать):

%token STATIC IDENT FLOAT INT VOID LPAR RPAR EQ SEMI

%%
member_decl:    field_decl |  method_decl;
field_decl:     STATIC type IDENT EQ SEMI;
method_decl:    STATIC return_type IDENT LPAR RPAR;
type:           INT | FLOAT;
return_type:    type | VOID;
%%

Учитывая анализ, я бы, наверное, исправил это так:

%token STATIC IDENT FLOAT INT VOID LPAR RPAR EQ SEMI

%%
member_decl:    field_decl |  method_decl;
field_decl:     STATIC type IDENT EQ SEMI;
method_decl:    STATIC type IDENT LPAR RPAR;
type:           INT | FLOAT | VOID;
%%

Компилируется без ошибок в Bison. Вам просто нужно добавить семантическую проверку в обработке для field_decl что гарантирует, что соответствующие type ($2) не является VOID,

Итак, проблема может быть в следующем: вы генерируете синтаксический анализатор LALR(1). Посмотрев один раз, вы не сможете различить правила field_decl и method_decl. Зачем? Поскольку оба выглядят одинаково, так как на первый взгляд парсер не может отличить тип return_type от типа (оба могут содержать INT или FLOAT). Я не уверен на 100%, поскольку моя память о различиях между LR, LALR и т. Д. Сейчас все нечеткая, но может показаться, что это проблема - на это особенно указывает тот факт, что при попытке удаления field_decl ошибка исчезла.

Другие вопросы по тегам