Using your grammar :
%token NEG FUNCALL SEMICOLON ID MINUS LPAREN RPAREN
%left NEG
%left FUNCALL
%%
input:
| input exp SEMICOLON
;
exp:
ID
| MINUS exp %prec NEG
| exp LPAREN exp RPAREN %prec FUNCALL
;
%%
bison (2.4.1) complains
exp:
4 | MINUS exp
...
state 6
4 exp: MINUS exp .
5 | exp . LPAREN exp RPAREN
LPAREN shift, and go to state 8
LPAREN [reduce using rule 4 (exp)]
$default reduce using rule 4 (exp)
state 8
5 exp: exp LPAREN . exp RPAREN
ID shift, and go to state 3
MINUS shift, and go to state 4
exp go to state 9
because when, in state 6, it sees a MINUS, followed by an expression
and the lookahed symbol is LPAREN, the parser can shift the symbol
LPAREN (expecting a function) or reduce MINUS exp to an exp (expecting a
exp). The latter is the default, so -f(); will be never recognized as an
function call.
You can rewrite the grammar in the following way, this is dirty but right:
%token NEG FUNCALL SEMICOLON ID MINUS LPAREN RPAREN
%left NEG
%left ID
%%
input:
| input exp SEMICOLON
;
exp:
ID
| MINUS exp %prec NEG
| ID LPAREN exp RPAREN
;
%%
If you don't like it, you have to introduce a precedence using the rules
rather than Context-Dependent Precedence (% prec % left % right ans so
on) breaking the "expression rule" in many rules.
A useful example is the C grammar:
http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
where postifix expression has an higher precedence than "numeric
expression" but no Context-Dependent Precedence is used. The grammar has
only one conflict, due to the "dangling else", but the default action of
bison fixes it.
%token NEG FUNCALL SEMICOLON ID MINUS LPAREN RPAREN
%left NEG
%%
input:
| input postfix_expression SEMICOLON
;
postfix_expression:
ID LPAREN exp RPAREN
;
exp:
ID
| MINUS exp %prec NEG
;
%%
A hint: you can use directly the token '(' rather than LPAREN in .y
file; of course lex has to return the char and not the token.
Luca
Tom Lieber ha scritto:
I either don't understand shift/reduce yet, or I don't understand
%prec. I believe the conflict in my grammar is that it can't decide
whether -a(b) is -(a(b)) or (-a)(b), which I thought using %prec would
solve. The essence of it is below, along with the corresponding
section of the output file:
%left NEG
%left FUNCALL
%%
input:
/* empty */
| input exp SEMICOLON
;
exp:
ID
| MINUS exp %prec NEG
| exp LPAREN exp RPAREN %prec FUNCALL
;
7: shift/reduce conflict (shift 9, reduce 4) on LPAREN
state 7
exp : MINUS exp . (4)
exp : exp . LPAREN exp RPAREN (5)
LPAREN shift 9
SEMICOLON reduce 4
RPAREN reduce 4
_______________________________________________
help-bison@gnu.org http://lists.gnu.org/mailman/listinfo/help-bison