Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grammar that bison/byacc reports 35 reduce/reduce conflicts but happy none #260

Open
mingodad opened this issue Nov 16, 2023 · 5 comments
Open

Comments

@mingodad
Copy link

While converting this grammar https://github.com/diku-dk/futhark/blob/master/src/Language/Futhark/Parser/Parser.y to use in https://mingodad.github.io/parsertl-playground/playground/ I found that bison/yacc/kmyacc reports 35 reduce/reduce conflicts but happy none.

Attached is the grammar converted using happy -i command line to get the expanded grammar and adding the missing parts manually (%tokens, %prec, ...):

happy -v
Happy Version 1.19.8 Copyright (c) 1993-1996 Andy Gill, Simon Marlow (c) 1997-2005 Simon Marlow

happy -i Parser.y

bison-nb -v Parser-yacc.y
Parser-yacc.y: warning: 35 reduce/reduce conflicts [-Wconflicts-rr]
Parser-yacc.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples
Parser-yacc.y:209.8-21: warning: rule useless in parser due to conflicts [-Wother]
  209 | Exp2 : Atom ".." Exp2 ;
      |        ^~~~~~~~~~~~~~

grammars.zip

@andreasabel
Copy link
Member

The translation of these precedences
https://github.com/diku-dk/futhark/blob/aaf9939c6955abf2b55ff0b1f3e07f445ea2b537/src/Language/Futhark/Parser/Parser.y#L165-L186
to bison seems to be written at

@mingodad What would be an example that parses wrongly with the happy-generated parser because happy misses conflicts?
And what would be the LR state that should display a conflict? (For LR state description see e.g. the happy-generated .info file.)

@andreasabel
Copy link
Member

andreasabel commented Nov 19, 2023

The happy grammar has this:

%right '...' '..'
%left juxtprec

RangeExp
  : Exp2 '...' Exp2     
  | Exp2 '..' Exp2 '...' Exp2 

Exp2 
     | RangeExp                  
     | Exp2 '..' Atom            
     | Atom '..' Exp2   
     | ApplyList 

ApplyList 
          : Atom ApplyList %prec juxtprec
          | Atom %prec juxtprec

The bison grammar has the same:

%right "..." ".."
%left juxtprec

RangeExp : Exp2 "..." Exp2 ;
RangeExp : Exp2 ".." Exp2 "..." Exp2 ;

Exp2 : RangeExp ;
Exp2 : Exp2 ".." Atom ;
Exp2 : Atom ".." Exp2 ;        
Exp2 : ApplyList ;
ApplyList : Atom ApplyList %prec juxtprec ;
ApplyList : Atom %prec juxtprec ;

The counterexample given by bison is:

$ bison -Wcounterexamples --report=cex Parser-yacc.y 
Parser-yacc.y: warning: 35 reduce/reduce conflicts [-Wconflicts-rr]
Parser-yacc.y: warning: reduce/reduce conflict on tokens "...", ...
  Example: Exp2 ".." Atom • "..." Exp2
  First reduce derivation
    RangeExp
    ↳ 274: Exp2                    "..." Exp2
           ↳ 170: Exp2 ".." Atom •
  Second reduce derivation
    RangeExp
    ↳ 277: Exp2 ".." Exp2                 "..." Exp2
                     ↳ 178: ApplyList
                            ↳ 180: Atom •
Parser-yacc.y:209.8-21: warning: rule useless in parser due to conflicts [-Wother]
  209 | Exp2 : Atom ".." Exp2 ;
      |        ^~~~~~~~~~~~~~

So bison claims here that Atom -> ApplyList -> Exp2 is a valid reduction even if the next token is "..." which has a higher precedence ("...") than the rule ApplyList: Atom (juxtprec).

According to happys spec, this is not a valid reduction, see https://haskell-happy.readthedocs.io/en/latest/using.html#how-precedence-works . So, from the perspective of happy, there is no conflict.

@mingodad Can you argue that a conflict actually exists? Or how should we proceed with this issue?

@mingodad
Copy link
Author

The documentation https://haskell-happy.readthedocs.io/en/latest/using.html#how-precedence-works clearly talk about shift/reduce but not about reduce/reduce.
I'm still making my head around this issue like in the lemon parser as well https://sqlite.org/forum/forumpost/9cb2fc0e6e11768c .

The main issue is applying precedence to mask/hide/resolve reduce/reduce conflicts intentional or unintentional, I mean we can add precedence to solve shift/reduce conflicts but it also can hide as solved reduce/reduce conflicts in other places without letting us now about then.

For example the sqlite3 grammar splitting expr in expr/expr2 seems to fix the reduce/reduce conflict (still in testing) like PostgreSQL does (also CG-SQL) see https://mingodad.github.io/parsertl-playground/playground/ in examples SQLite3 parser (partially working) and SQLite3 modified parser (partially working).

I'm still working on it and as soon I found an answer I'll tell you.

@ricomariani
Copy link

I hadn't considered the possibly that bison doesn't use precedence at all for the reduce/reduce case. In this case it seems that one of the choices would immediately lead to a syntax error and happy figures that out. I think Bison doesn't have enough lookahead to see that it will be in a corner...

@BenHanson
Copy link

The best I could find is https://www.ibm.com/docs/en/zos/2.1.0?topic=ambiguities-rules-help-remove

"Precedence is not consulted in reduce-reduce conflicts. yacc always reduces by the earliest grammar rule, regardless of precedence"

I wasn't sure if this also applied to bison, which is why I resorted to looking at the bison source code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants