Зубр уменьшить / уменьшить конфликты
Я написал следующую грамматику:
%union{
string *s;
float num;
}
%token div_token mod_token sqrt_token it_token abs_token
%token <num> num_token
%token <s> Stampa
%type <num> E
%left '+' '-'
%left '*' '/' div_token mod_token
%left UMINUS
%left abs_token sqrt_token
%%
Program: Program Line '\n' { }
| Line '\n' { }
;
Line: Stampa {cout<<*$1<<endl;}
| E {cout<<$1<<endl; broj = $1;}
| it_token {cout<<broj<<endl;}
;
E: E '+' E {$$ = $1 + $3;}
| E '-' E {$$ = $1 - $3;}
| E '*' E {$$ = $1 * $3;}
| E '/' E {if($3!=0)
$$ = $1 / $3;
else
yyerror("Deljenje nulom");
}
| mod_token E E {$$ = (float)((int)$2 % (int)$3);}
| div_token E E {$$ = (float)((int)($2 / $3));}
| sqrt_token E { $$ = sqrt($2); }
| '(' E ')' {$$=$2;}
| abs_token E { $$ = abs($2);}
| '-' E %prec UMINUS {$$=-$2;}
| num_token {$$ = $1;}
;
Теперь бизоны нашли 8 уменьшений / уменьшений конфликтов. Когда я удаляю строку
| '-' E %prec UMINUS {$$=-$2;}
их нет Я думаю, что приоритеты и ассоциативная собственность хорошо определены. Может кто-нибудь сказать мне, как разрешать конфликты?
2 ответа
Теперь бизоны нашли 8 уменьшений / уменьшений конфликтов. Когда я удаляю строку
| '-' E %prec UMINUS {$$=-$2;}
их нет Я думаю, что приоритеты и ассоциативная собственность хорошо определены. Может кто-нибудь сказать мне, как разрешать конфликты?
Это должно решить проблему:
%union{
string *s;
float num;
}
%token div_token mod_token sqrt_token it_token abs_token
%token <num> num_token
%token <s> Stampa
%type <num> E
%left '+' '-'
%left '*' '/' div_token mod_token
%left UMINUS
%left abs_token sqrt_token
%%
Program: Program Line '\n' { }
| Line '\n' { }
;
Line: Stampa {cout<<*$1<<endl;}
| E {cout<<$1<<endl; broj = $1;}
| it_token {cout<<broj<<endl;}
;
E: E '+' E {$$ = $1 + $3;}
| E '-' E {$$ = $1 - $3;}
| E '*' E {$$ = $1 * $3;}
| E '/' E {if($3!=0)
$$ = $1 / $3;
else
yyerror("Deljenje nulom");
}
| E mod_token E {$$ = (float)((int)$1 % (int)$3);}
| E div_token E {$$ = (float)((int)($1 / $3));}
| sqrt_token E { $$ = sqrt($2); }
| '(' E ')' {$$=$2;}
| abs_token E { $$ = abs($2);}
| '-' %prec UMINUS E {$$=-$2;}
| num_token {$$ = $1;}
;
Это исправляет пару проблем. Вы, вероятно, имели в виду:
| E mod_token E {$$ = (float)((int)$1 % (int)$3);}
| E div_token E {$$ = (float)((int)($1 / $3));}
И более понятно написать следующее:
| '-' %prec UMINUS E {$$=-$2;}
Вы можете увидеть конфликты с бизоном -v
который производит xyz.output
:
state 35
6 E: E . '+' E
7 | E . '-' E
7 | E '-' E .
8 | E . '*' E
9 | E . '/' E
15 | '-' E
.
div_token reduce using rule 7 (E)
div_token [reduce using rule 15 (E)]
mod_token reduce using rule 7 (E)
mod_token [reduce using rule 15 (E)]
sqrt_token reduce using rule 7 (E)
sqrt_token [reduce using rule 15 (E)]
abs_token reduce using rule 7 (E)
abs_token [reduce using rule 15 (E)]
num_token reduce using rule 7 (E)
num_token [reduce using rule 15 (E)]
'+' reduce using rule 7 (E)
'+' [reduce using rule 15 (E)]
'-' reduce using rule 7 (E)
'-' [reduce using rule 15 (E)]
'*' reduce using rule 15 (E)
'/' reduce using rule 15 (E)
'\n' reduce using rule 15 (E)
'(' reduce using rule 7 (E)
'(' [reduce using rule 15 (E)]
')' reduce using rule 15 (E)
$default reduce using rule 7 (E)
Оператор сокращений на div_token
а также mod_token
подозрительны. Неоднозначность грамматики вызвана тем, что эти операторы применяются к двум выражениям E
,
РЕДАКТИРОВАТЬ
Возможно, вы хотите сохранить префикс div и мод операторов. Если это так, вам нужно устранить неоднозначность грамматики. Одним из возможных решений является:
| mod_token F F {$$ = (float)((int)$2 % (int)$3);}
| div_token F F {$$ = (float)((int)($2 / $3));}
| F
;
F: '(' E ')' {$$=$2;}
| sqrt_token E { $$ = sqrt($2); }
| abs_token E { $$ = abs($2);}
| '-' %prec UMINUS E {$$=-$2;}
| num_token {$$ = $1;}
;
и добавьте тип F
:
%type <num> E F
Отношения приоритета используются только для разрешения сдвига / уменьшения конфликтов. Их нельзя использовать для разрешения конфликтов уменьшения / уменьшения, поскольку сравнение приоритетов всегда выполняется между продукцией (которая может быть уменьшена) и токеном (который может быть смещен).
Имея это в виду, рассмотрим процесс разбора выражения:
div 7 - 3 - 2
(при условии, что div
как ты пишешь div_token
).
Каждый - может быть либо оператором вычитания инфикса, либо оператором отрицания префикса. В этом контексте, так как div
должно следовать ровно два выражения, ровно один из знаков минуса должен быть инфиксным. А какой? Это
div (7-3) (-2)
или же
div (7) (-3-2)
Но, конечно, возможны и другие контексты. Если бы выражение было div 7 - 3 - 2 a
тогда единственный действительный разбор будет div ((7-3)-2) 8
тогда как если бы выражение было div div 7 - 3 - 2
тогда разбор должен быть div (div 7 (-3)) (-2)
,
Вы можете получить более полное представление о конфликте, попросив Bison создать отчет о разборе, используя -v
вариант и глядя на .output
файл произведен. С вашей грамматикой этот отчет показывает, что конфликт уменьшения / уменьшения находится в состоянии 35, которое:
State 35
6 E: E . '+' E
7 | E . '-' E
7 | E '-' E .
8 | E . '*' E
9 | E . '/' E
15 | '-' E .
div_token reduce using rule 7 (E)
div_token [reduce using rule 15 (E)]
(actions truncated for space)
Возможные сокращения соответствуют позициям LR с .
в конце, которые E '-' E .
а также '-' E .
, Для большинства (но не для всех) токенов прогнозирования возможно любое из этих сокращений. (Приоритет *
над E: E '-' E
Правило исключает возможность первого сокращения, если *
предвкушающий персонаж; аналогично для /
.)
Подобное смешивание выражений infix и prefix обычно не очень хорошая идея, именно из-за этой неоднозначности.