Yacc / Bison, минимизируйте количество, группируя математические операции - PullRequest
4 голосов
/ 11 сентября 2009

Я смотрю на источник 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); }

ПРИМЕЧАНИЕ: я использую бизона.

Ответы [ 2 ]

6 голосов
/ 22 сентября 2009

Проблема с их группировкой заключается в том, что вы теряете приоритеты в правилах - у вас есть только одно правило, которое имеет различный приоритет, в зависимости от того, какой это 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: '*' { $$ = '*'; }
     | '/' { $$ = '/'; }
;
1 голос
/ 11 сентября 2009

Вы можете сделать это двумя способами:

  • На этапе lex определите распознавание операторов и предоставьте символ терминала (в вашем синтаксисе mathOp) со значением оператора '+', '-' ...
  • Используя mathOp в качестве нетерминала, вы можете вернуть некоторое связанное значение:

    mathOp: '+' {$$ = '+'; } | '-' {$$ = '-'; } ...

Тогда использование будет выглядеть (обратите внимание на 2 доллара):

| expr mathOp expr         { $$ = opr($2, 2, $1, $3); }

может быть, вы захотите определить более сложный mathOp, чем использовать% type

...