4

This is my flex code

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

And my bison code

%{ 
    #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;
}

when i input 4 + 5 * 2 it give the output as 18. But the correct answer should be 14. Where am i getting it wrong ?

user574183
  • 710
  • 1
  • 10
  • 22

4 Answers4

9

Your problem is that you have expr OP INTEGER for each rule.

The way you have it bison parses it as:

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

It forces precedence to go to the left instead of precedence being determined by your precedence rules.

Precedence only applies when there is more than one way to parse the text, instead of what you have, try

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

That way 5 + 4 * 2 can be parsed as either ((5 + 4) * 2) or (5 + (4 * 2)), and bison will consult precedence to determine the correct parse.

Bruno Vieira
  • 3,884
  • 1
  • 23
  • 35
Cooper Burns
  • 91
  • 1
  • 1
2

You can force precedence using reduction:

expr    : sum
        ;

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

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

number  : INTEGER
        ;

That way, product is reduced before sum.

Linus Kleen
  • 33,871
  • 11
  • 91
  • 99
  • but isn't the %left keyword used to make bison resolve precedence issues ? My way it should work don't you think ? I wonder why it doesnt work for me. :( – user574183 Feb 03 '11 at 11:16
  • 2
    No. `%left` indicates associativity. `1 + 2 + 3` is reduced to `(1+2)+3` when it's left associative. For right associativity it would be `1+(2+3)`. – Linus Kleen Feb 03 '11 at 11:21
  • 1
    what happens if i don't define associativity ? – user574183 Feb 03 '11 at 11:31
  • 1
    Good question. I suppose, it defaults to left associativity. – Linus Kleen Feb 03 '11 at 11:39
  • well i removed all the %left statements and placed %right '*' . Still no luck. What can i do. – user574183 Feb 03 '11 at 11:41
  • 2
    Replacing isn't what you want: `1 - 2 - 3` would actually be `1 - (2 - 3)` for right associativity. That gives a wholly different result. Regarding operator precedence, [consult the bison manual](http://dinosaur.compilertools.net/bison/bison_8.html#SEC71) where it says: *The relative precedence of different operators is controlled by the order in which they are declared.* – Linus Kleen Feb 03 '11 at 11:48
  • well but the problem is in my bison seem to ignore the associativity rules that i set. for both right and left associativity rules i get the same answer. how can i fix that ? – user574183 Feb 03 '11 at 12:03
  • 2
    Honestly, I encountered this problem, too. I came up with the above example to circumvent spontaneous "precedence-ignoring". – Linus Kleen Feb 03 '11 at 12:17
  • 1
    %left '+' '-' is it the same as %left '-' '+' ? – user574183 Feb 03 '11 at 12:34
  • 1
    _The relative precedence of different operators is controlled by the order `of the lines` in which they are declared_. See also "Shift/Reduce Conflicts and Operator Precedence" in "flex & bison by John R. Levine" where he calls it explicit precedence. I find his advice for when not to use (extra) reduction rules quite valid. – Michael Ambrus Jul 26 '20 at 10:27
0

I think all rules have precedence of 'INTEGER' since it is the last terminal

dsrbecky
  • 151
  • 1
  • 4
-2

Consider for instance the following grammar:

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

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

Bison reports:

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

One would get the exact same parser with the following directives instead:

           %left "+"
           %precedence "*"

please try this you will get right answer.....

Sundar
  • 25
  • 3
  • https://www.gnu.org/software/bison/manual/html_node/Bison-Options.html. See the warnings under the section "precedence". This guy just copy-pasted it. – Nate Symer Dec 14 '17 at 22:38