How to process unary minus for constants by other way than expressions? (bison reduce/reduce conflict)

Marek Peca <marek@tynska.cuni.cz>
14 Mar 2007 14:31:48 -0400

          From comp.compilers

Related articles
How to process unary minus for constants by other way than expressions marek@tynska.cuni.cz (Marek Peca) (2007-03-14)
Re: How to process unary minus for constants by other way than express schmitz@i3s.unice.fr (Sylvain Schmitz) (2007-03-14)
| List of all articles for this month |
From: Marek Peca <marek@tynska.cuni.cz>
Newsgroups: comp.compilers
Date: 14 Mar 2007 14:31:48 -0400
Organization: Charles University Prague
Keywords: parse, question
Posted-Date: 14 Mar 2007 14:31:48 EDT

Dear compiler compilers,


I'm trying to write simple expression evaluator in flex/bison. The
aim is to evaluate math expr using infix operators + - / * ^, libm
functions such as pow, sin ot atan2, named variables and 1.234e-56
like constants. The expression will be parsed once over a time and a
produced tree will be then executed many times, so the tree should be
nearly optimal.


The general task is a holy simplicity itself, even given as an
example in bison's docs. However, I'd like to tune one detail: unary
minus for numbers. In lexer, I specify numbers without preceding
optional sign, the reason is to not to confuse binary and unary
minus. I want to distinguish two different cases in bison parser:


* unary minus before general expression -- it will produce n+1 order
subtree, calling unary minus function to the expression value;


* unary minus before number constant -- it should be applied at
"parse time" to the number to simplify the tree.


Is this solvable using bison, ie. is its set of parseable grammars
sufficient for this task? I know, I can optimize the tree after
parsing, its simple, but this would be very stupid, if it can be
easily specified in a bison input grammar description.


I tried something like this:
-----
%token NUMBER
%token IDENTIFIER
%left '-' '+'
%left UNEXP
%left UNNUM
%right '^'


%%


input: /* nic */
| input line
;


line: '\n'
| expr '\n'


expr: NUMBER { $$ = $1; }
                | '(' expr ')' { $$ = $2; }
| expr '+' expr { $$ = sub($1,$3); }
| expr '-' expr { $$ = add($1,$3); }
| expr '^' expr { $$ = pow($1,$3); }
| '-' NUMBER %prec UNNUM { $$ = -$2; }
| '-' expr %prec UNEXP { $$ = neg($2); }
;


%%
-----


then, I changed to
-----
expr: NUMBER
| expr_nonnum
;


expr_nonnum: '(' expr ')'
| '(' expr ')'
| expr '+' expr
| expr '-' expr
| expr '^' expr
| '-' NUMBER %prec UNNUM
| '-' expr_nonnum %prec UNEXP
;
-----


but without success.


Thank you for your help.


Best regards,
Marek P.


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.