приоритет бизонов не работает - PullRequest
3 голосов
/ 03 февраля 2011

Это мой гибкий код

%{
 #include "fl.tab.h"
%} 
    %% 
    [0-9]+  { yylval = atoi(yytext); 
        return INTEGER; } 
    \n  return 0;   
    [ \t]   ;   
    .   return yytext[0];
    %% 

И мой код бизона

%{ 
    #include <stdio.h> 
%} 
%token INTEGER
%left '+' '-'
%left '*'
%% 
Statement : expr {printf("%d\n",$1);}
        ;
expr :  expr '+' INTEGER  {$$ = $1 + $3;}
     |  expr '-' INTEGER  {$$ = $1 - $3;}
     |  expr '*' INTEGER  {$$ = $1 * $3;}        
     |  INTEGER {$$ = $1;}
     ;
%% 

int main(void){
   yyparse();
   return 0;
}

, когда я ввожу 4 + 5 * 2, он дает вывод как 18. Но правильный ответ долженбыть 14. Где я ошибаюсь?

Ответы [ 4 ]

7 голосов
/ 16 ноября 2012

Ваша проблема в том, что у вас есть expr OP INTEGER для каждого правила.

То, как вы это делаете, зубр анализирует как:

expr * 2 -> (4 + 5) * 2

Это заставляет приоритет идти влево, а не приоритет, определяемый вашими правилами приоритета.

Приоритет применяется только тогда, когда есть более одного способа для анализа текста, вместо того, что у вас есть, попробуйте

expr :  expr '+' expr  {$$ = $1 + $3;}
     |  expr '-' expr  {$$ = $1 - $3;}
     |  expr '*' expr  {$$ = $1 * $3;}        
     |  INTEGER {$$ = $1;}
     ;

Таким образом, 5 + 4 * 2 может быть проанализирован как ((5 + 4) * 2) или (5 + (4 * 2)), и зубр сверится с приоритетом для определения правильного анализа.

2 голосов
/ 03 февраля 2011

Вы можете форсировать приоритет, используя уменьшение:

expr    : sum
        ;

sum     : sum '+' product {$$ = $1 + $3;}
        | product
        ;

product : number '*' product {$$ = $1 * $3;}
        | number
        ;

number  : INTEGER
        ;

Таким образом, product уменьшается до sum.

0 голосов
/ 19 декабря 2013

Рассмотрим, например, следующую грамматику:

           %nonassoc "="
           %left "+"
           %left "*"
           %precedence "("
           %%
           stmt:
             exp
           | "var" "=" exp
           ;

           exp:
             exp "+" exp
           | exp "*" "num"
           | "(" exp ")"
           | "num"
           ;

Отчеты о бизонах:

           warning: useless precedence and associativity for "="
            %nonassoc "="
                      ^^^
           warning: useless associativity for "*", use %precedence
            %left "*"
                  ^^^
           warning: useless precedence for "("
            %precedence "("
                        ^^^

Вместо этого можно получить точно такой же анализатор со следующими директивами:

           %left "+"
           %precedence "*"

пожалуйста, попробуйте это, вы получите правильный ответ .....

0 голосов
/ 30 мая 2012

Я думаю, что все правила имеют приоритет 'INTEGER', так как это последний терминал

...