Yacc / Bison, минимизируйте количество, сгруппировав математические операции
Вопрос
Я смотрю на исходный код calc здесь http://epaperpress.com/lexandyacc/
Я вижу эти строки в calc.y
| expr '+' expr { $$ = opr('+', 2, $1, $3); }
| expr '-' expr { $$ = opr('-', 2, $1, $3); }
| expr '*' expr { $$ = opr('*', 2, $1, $3); }
| expr '/' expr { $$ = opr('/', 2, $1, $3); }
| expr '<' expr { $$ = opr('<', 2, $1, $3); }
| expr '>' expr { $$ = opr('>', 2, $1, $3); }
Есть ли способ сгруппировать их?значит, я могу вместо этого написать что-то вроде приведенного ниже?
| expr mathOp expr { $$ = opr(mathOp, 2, $1, $3); }
| expr cmpOp expr { $$ = opr(cmpOp, 2, $1, $3); }
ПРИМЕЧАНИЕ:Я использую bison.
Решение
Проблема с их группировкой заключается в том, что вы теряете приоритеты в правилах - у вас есть только одно правило, которое имеет различный приоритет, в зависимости от того, какой это mathop, который bison / yacc не может обработать. Тем не менее, вы можете группировать операции одного и того же уровня приоритета вместе
expr: expr mulOp expr { $ = opr($2, 2, $1, $3); } %prec '*'
| expr addOp expr { $ = opr($2, 2, $1, $3); } %prec '+'
| expr relOp expr { $ = opr($2, 2, $1, $3); } %prec '<'
:
mulOp: '*' { $ = '*'; }
| '/' { $ = '/'; }
;
Другие советы
Вы можете сделать это двумя способами:
- На этапе lex определите распознавание операторов и укажите терминальный символ (в вашем синтаксисе mathOp) со значением оператора '+', '-' ...
Используя mathOp как нетерминальный, вы можете вернуть некоторое связанное значение:
Мэтоп :'+' { $$ = '+';} | '-' { $$ = '-';} ...
Тогда использование будет выглядеть следующим образом (обратите внимание на 2 доллара):
| expr mathOp expr { $$ = opr($2, 2, $1, $3); }
возможно, вы хотели бы определить более сложный mathOp, а затем использовать %type