[comp.compilers] Yacc precedence bug

slv@seg.npl.co.uk (S Voogd) (01/10/91)

Dear comp.compiler-readers,

While working with YACC, we came across a POSSIBLE BUG
in the precedence mechanism of YACC.

You can give a token a precedence and associativity by
declaring this in the declaration-part of a YACC-file
According to the manual you can also change the precedence 
and associativity of a token in the grammar-rules by
using the '%prec'-mechanism.

But it seems to us that this mechanism doesn't work!!!

We enclose a simple desk calculator and reverse the usual
precedence of '+' with '*' using the '%prec'-mechanism.
It seems that the associativity of tokens can be changed.(?)
But their precedence levels are now the same.

Are we doing something wrong?
Is this a BUG on YACC?
If it is a bug, is there a way of changing the prec. and
ass. of tokens ? (We really need it!)

Please mail us with comments, results etc. or discuss this on the net. 

         Simon Voogd            Graeme Parkin 
e-mail : slv@seg.npl.co.uk      gip@seg.npl.co.uk
Tel    : +44 81 943 7009        +44 81 943 7006
         National Physical Laboratory (UK)

--------Test Results-----------------------------------------

normal precedences :
	4+7*2 = 4+(7*2) = 18
	2*7+4 = (2*7)+4 = 18
reversed precedences :
	4+7*2 = (4+7)*2 = 22
	2*7+4 = 2*(7+4) = 22
BUT the enclosed calculator gives the following results :
	4+7*2 = 22 [ = (4+7)*2  ]
	2*7+4 = 18 [ = (2*7)+4  ] (surely should be 22 !!!!!)

--------Simple Desk Calculator-------------------------------
%{
#include <stdio.h>
#define YYSTYPE double
%}

%token  NUMBER
%left PLUS
%left MUL

%%
lines	:	lines expr '\n'
			{printf("%g\n", $2); }
	|	lines '\n'
	|
	|	error '\n'
			{ yyerror("reenter last line:");
			  yyerrok; }
	;

expr	:	expr PLUS expr %prec MUL
			{ $$ = $1 + $3; }
	|	expr MUL expr %prec PLUS
			{ $$ = $1 * $3; }
	|	NUMBER
	;
%%

yylex()
{	int	c;

	while((c = getchar()) == ' ') {}
	if(isdigit(c))
	{	yylval = c - '0';
		return(NUMBER);
	}
	if(c == '+')
	{	yylval = PLUS;
		return(PLUS);
	}
	if(c == '*')
	{	yylval = MUL;
		return(MUL);
	}
	if(c == EOF)
	{	yylval = 0;
		return(EOF);
	}
	return(c);
}

yywrap(){};

yyerror(s) char *s;{
	fprintf(stderr,"%s\n",s);
	};

main(){
	return(yyparse() );
	}
-------------------------------------------------------------
[This does appear to confuse yacc's precedence mechanism -- the two
productions are indeed treated as of equal precedence.  The standard unary
minus precedence does work, I haven't narrowed the bug further. -John]
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.