Первоначально я написал длинный ответ о двусмысленности, но затем я внимательно рассмотрел вашу грамматику.Давайте немного уменьшим его и покажем, в чем проблемы:
%token IF COLOR BLACK
%%
statement
: statement command
| /*nothing*/
;
command
: IF {$$ = $1; printf ("IF\n");}
| ELSE {$$ = $1; printf("ELSE\n");}
| EQ {$$ = $1; printf("EQ\n");}
| THEN {$$ = $1; printf("THEN\n");}
| LPAREN {$$ = $1; printf("LPAREN\n");}
| RPAREN {$$ = $1; printf("RPAREN\n");}
| COLOR EQ BLACK {$$ = $3; printf("color is black\n");}
| IF LPAREN COLOR EQ BLACK RPAREN {$$ = $1; printf("WONT COMPILE\n");}
;
Как вы ожидаете, что выражение if(color = black)
будет проанализировано?Обратите внимание, что «color = black
» может уменьшиться до command
через COLOR EQ BLACK
или может быть «сдвинут» в стек, чтобы стать частью более длинного анализа IF LPAREN COLOR EQ BLACK RPAREN
.
Это объясняет конкретное предупреждениевы получаетеТеперь перейдем к остальной части вашей грамматики:
Вы не хотите писать свою грамматику, поэтому неполные утверждения имеют смысл.Обратите внимание, что одиночный символ «=
» является полным действительным command
и, следовательно, полным действительным statement
- это действительно то, что вы хотите?
Вы собираетесь переписать это с нуля,Начните с простого:
%token NUMBER COMMAND IF THEN ELSE COLOR BLACK
%%
statement
: COMMAND NUMBER
| IF cond THEN statement
| /* nothing */
;
cond
: '(' COLOR '=' BLACK ')'
;
Не проверено;но этого должно быть достаточно, чтобы вы начали.Если вам нужно что-то сделать при обнаружении токена, вы можете (например) заменить IF cond THEN COMMAND
на if cond then command
и добавить правила, такие как
if : IF { printf("%s\n", "IF"); }
;
then: THEN { printf("%s\n", "THEN"); }
;
Начните с простого, добавляйте медленно и выполняйте рефакторинг при получении правилслишком волосатый или повторяющийся.И проработайте учебное пособие, прежде чем приступить к большому проекту.Руководство GNU Bison содержит хороший учебник, как и Kernighan & Pike's Среда программирования Unix .