help-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Misunderstanding %prec?


From: Luca
Subject: Re: Misunderstanding %prec?
Date: Sun, 25 Jan 2009 14:41:10 +0100
User-agent: Thunderbird 2.0.0.19 (Windows/20081209)

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






reply via email to

[Prev in Thread] Current Thread [Next in Thread]