Я слоняюсь с зубрами, когда читаю книгу об этом, и я работаю над простым инфиксным калькулятором, где я использую грамматику для определения приоритета, а не %left/%right
и порядок таких объявлений.
Большинство калькуляторов зубров, которые я видел, имеют факториал как функцию, а не как оператор, поэтому эти примеры не помогли.
В настоящее время у меня есть:
15 calclist:
16 | calclist expr EOL { printf(" = %d\n", $2); }
17 | calclist EOL { /* nada */ }
18 ;
19 expr:
20 term
21 | expr '+' term { $$ = $1 + $3; }
22 | expr '-' term { $$ = $1 - $3; }
23 ;
24 term:
25 factor
26 | term '*' factor { $$ = $1 * $3; }
27 | term '/' factor { $$ = $1 / $3; }
28 ;
29 factor:
30 '|' factor { $$ = $2 > 0 ? $2 : -$2; }
31 | '-' factor { $$ = 0 - $2; }
32 | '(' expr ')' { $$ = $2; }
33 | '(' expr ')' '!' { $$ = factorial($2); }
34 | NUMBER '!' { $$ = factorial($1); }
35 | NUMBER
36 ;
Линии33 и 34 кажутся слишком многословными.Я чувствовал, что правильный способ сделать это - заменить 33/34 на:
33 | factor '!' { $$ = factorial($1); }
Но затем я получаю конфликты сдвига / уменьшения с помощью операторов отрицания / значения абс, что имеет смысл, когда я смотрю на calc.output
файл, созданный с помощью bison -v
.
Есть ли более чистый способ сделать это, поддерживая грамматику expr / term / factor, которая определяет приоритет оператора?Или мое рабочее решение - лучшее, что я могу сделать, учитывая мои ограничения (наложенные самостоятельно или иным образом).