Sven Panne <[EMAIL PROTECTED]> writes:

> [ I'm not quite sure if glasgow-haskell-bugs is the right place for
>   mailing this, but since Happy is now part of GHC... ]

It's as good a place as any...

> Given the following (heavily boilt down) specification, Happy prints the
> incredibly informative message "Fail: spontaneous" and dies.
> 
> --------------------------------------------
> %tokentype { Token }
> %token IDENTIFIER { TokenIdentifier }
>        '+'        { TokenPlus       }
> %%
> Expr :: { Int }
>    : Term                      { 42 }
> 
> Term :: { Int }
>    : IDENTIFIER                { 42 }
>    | Expr '+' Term             { 42 }
> --------------------------------------------

This is a bug that falls into the "how did it ever work" category.
Patch follows.

*** LALR.lhs    1997/09/09 16:31:45     1.6
--- LALR.lhs    1997/09/23 14:51:25
***************
*** 66,98 ****
  >             Just c  -> c
  >  where
  >
  >     nts = getNonTerminals g
  >     first_term = getFirstTerm g
- >
- >     (info,_) = foldr (\n (h,c) -> follow h n []) ([],[]) nts
- >     info' = map (\(n,rules) -> (n,map (\rule -> (rule,0)) rules)) info
- >
- >     follow h n loop
- >             | n `elem` loop = (h,[])
- >             | otherwise =
- >         case lookup n h of
- >             Nothing ->  let rules = lookupProdsOfName g n 
- >                             (h',c) = follows h rules [] (n:loop)
- >                         in
- >                         ((n,c) : h', c)
- >             Just c  -> (h, c)
- > 
- >     follows h [] rs loop = (h, rs)
- >     follows h (rule:rules) rs' loop = 
- >           case findRule g rule 0 of 
- >             (Just nt) | nt >= 0 && nt < first_term ->
- >                     let (h',c) = follow h nt loop
- >                         rs'' = filter (`notElem` rs') (rule:c) ++ rs'
- >                     in
- >                     follows h' rules rs'' loop
- >             _ -> follows h rules (if rule `elem` rs' 
- >                                     then rs' 
- >                                     else rule:rs') loop
  
  > closure0 :: GrammarInfo -> (Name -> RuleList) -> Set Lr0Item -> Set Lr0Item
  > closure0 g closureOfNT set = mkSet (foldr addRules emptySet set)
--- 66,87 ----
  >             Just c  -> c
  >  where
  >
+ >     info' = map (\(n,rules) -> (n,map (\rule -> (rule,0)) rules)) info
+ >     info = mkClosure (==) (\f -> map (follow f) f)
+ >                     (map (\nt -> (nt,lookupProdsOfName g nt)) nts)
+ 
+ >     follow f (nt,rules) = (nt, foldr union rules (map (followNT f) rules))
+ 
+ >     followNT f rule = 
+ >             case findRule g rule 0 of
+ >                     Just nt | nt >= 0 && nt < first_term ->
+ >                             case lookup nt f of
+ >                                     Just rs -> rs
+ >                                     Nothing -> error "followNT"
+ >                     _ -> []
+ 
  >     nts = getNonTerminals g
  >     first_term = getFirstTerm g
  
  > closure0 :: GrammarInfo -> (Name -> RuleList) -> Set Lr0Item -> Set Lr0Item
  > closure0 g closureOfNT set = mkSet (foldr addRules emptySet set)

> Another (probably easy-to-fix) glitch: Using comments and multi-line
> code confuses Happy's line numbering in error messages. (Yacc/Bison are
> not better, either, but why should one imitate bad habits?) It's quite
> hard to explain the advantages of frontend generators to students while
> not being able to find a simple typo...     :'-(

Ok, could you give an example?  I tried to fix most of the
wrong-line-number-in-error-message type problems, but I may have
missed some.

Cheers,
        Simon

-- 
Simon Marlow                                             [EMAIL PROTECTED]
University of Glasgow                       http://www.dcs.gla.ac.uk/~simonm/
finger for PGP public key

Reply via email to