Reputation: 15163
I'm learning yacc, and this code snippet I got out of a book doesn't seem to be applying the precedence rules correctly.
Here's the yacc file:
%{
#include <stdio.h>
extern int yylex();
void yyerror (char const *msg);
%}
%token NAME NUMBER
%left '+' '-'
%left '*' '/'
%%
statement: NAME '=' expression
| expression { printf("= %d\n", $1); }
;
expression: expression '+' NUMBER { $$ = $1 + $3; }
| expression '-' NUMBER { $$ = $1 - $3; }
| expression '*' NUMBER { $$ = $1 * $3; }
| expression '/' NUMBER { if ($3) $$ = $1 / $3;
else yyerror("divide by zero"); }
| '-' expression { $$ = -$2; }
| '(' expression ')' { $$ = $2; }
| NUMBER { $$ = $1; }
;
%%
Here's the lex:
%{
#include "y.tab.h"
#include <stdio.h>
extern int yylval;
%}
%%
[0-9]+ { yylval = atoi(yytext); return NUMBER; }
[ \t] { ; }
\n { return 0; }
. { return yytext[0]; }
%%
I compile it with:
lex foo.l
yacc -d foo.y
clang -o foo lex.yy.c y.tab.c -ly -ll
Running it multiplication-first gives the right answer:
> ./foo
3 * 2 + 1
= 7
But when the multiplication happens second, it gives the wrong answer:
> ./foo
4 + 5 * 2
= 18
Adding the lines %left '+' '-'
and %left '*' '/'
in the yacc file were supposed to fix this, but they didn't. Can anyone tell me why?
Upvotes: 0
Views: 909
Reputation: 126203
The precedence rules only serve to resolve ambiguities in the grammar. If your grammar directly encodes the precedences, then there are no ambiguities for the precedence rules to resolve.
Defining your grammar as expr: expr op NUMBER
defines the precedence of all operators as being the same and evaluates them strictly left-to-right. You want to define the grammar as expr: expr op expr
for each operator, so that the grammar is ambiguous, and the precendence rules can resolve the ambiguity.
Upvotes: 1
Reputation:
Your specification of the productions is wrong, though. It should be expression '+' expression
instead of expression '+' NUMBER
(and similarly in the case of each operator), i. e. both sides are expressions, you don't want to prohibit addition of two expressions, do you.
Upvotes: 2