Hmm. I tried to attach the .ly file to the bug report just sent, but that
didn't seem to work. So here it is (not) again:

-------------------------------------------------------------------------

Ebnf2psParser.ly --- happy grammar for Ebnf2ps input
(1)  A happy specification for a grammar in EBNF
(2)  A happy specification for the happy input language
(3)  A happy specification for the yacc input language


> {
> module Ebnf2psParser (theEbnfParser, theHappyParser, theYaccParser) where
> import AbstractSyntax
> import Lexer
> import List
> }


> %name ebnf2psParser
> %tokentype { Token' }
> %token
>       EBNF         { EbnfInput     }   
>       HAPPY        { HappyInput    }
>       YACC         { YaccInput     }
>       id_tok       { Ident' $$     }
>       cid_tok      { CIdent' $$    }
>       ";"          { SemiColon     }
>       ":"          { Colon         }
>       "::"         { DoubleColon   }
>       "%%"         { DoublePercent }
>       "%"          { Percent       }
>       "|"          { Bar           }
>       "{"          { OpenBrace     }
>       "}"          { ClosingBrace  }
>       "."          { Dot           }
>       "="          { Equal         }
>       "+"          { Plus          }
>       "["          { OpenBrack     }
>       "]"          { ClosingBrack  }
>       "("          { OpenParen     }
>       ")"          { ClosingParen  }
>       "/"          { Slash         }
>       any_string   { String' $$    }
>       any_symbol   { Symbol' $$    }
>       number       { Number' _     }

Scheint in der neuen Happy-Version nicht mehr verfugbar zu sein. In der
Dokumentation wird jedenfalls darauf hingewiesen, da? das newline-token in
zukunftigen Versionen moglicherweise abgeschafft wird.
   > %newline        { Newline       }

> %%

> ebnf2psparse    :: { [Production] }
> ebnf2psparse    :  EBNF   ebnfInput                       { $2 }
>                 |  HAPPY  happyInput                      { $2 }
>                 |  YACC   yaccInput                       { $2 }


(1) happy specification for a grammar in EBNF

> ebnfInput       :: { [Production] }
> ebnfInput       :  ebnfProductions                        { $1 }

> ebnfProductions :: { [Production] }
> ebnfProductions :  ebnfProduction                         { [$1] }
>                 |  ebnfProductions ebnfProduction         { $1 ++ [$2] }

> ebnfProduction  :: { Production }
> ebnfProduction  :  ebnfNonterminal 
>                    ebnfOptString "=" ebnfTerm ";"         { ProdProduction $1 $2 $4 }
                
> ebnfOptString   :: { [String] }
> ebnfOptString   :  any_string                             { [$1] }
>                 |                                         { [] }

> ebnfNonterminal :: { String }
> ebnfNonterminal :  id_tok                                 { $1 }

> ebnfTerm        :: { Production }
> ebnfTerm        :  ebnfFactors                            { ProdTerm $1 }     

> ebnfFactors     :: { [Production] }
> ebnfFactors     :  ebnfFactor                             { [$1] }
>                 |  ebnfFactors "|" ebnfFactor             { $1 ++ [$3] }

> ebnfFactor      :: { Production }
> ebnfFactor      :  ebnfExtAtoms                           { ProdFactor $1 }

> ebnfExtAtoms    :: { [Production] }
> ebnfExtAtoms    :  ebnfExtAtom                            { [$1] }
>                 |  ebnfExtAtom ebnfExtAtoms               { $1 : $2 }

> ebnfExtAtom     :: { Production }
> ebnfExtAtom     :  ebnfAtom                               { $1 }
>                 |  ebnfAtom "/" ebnfAtom                  { ProdRepeatWithAtom $1 $3 
>}
>                 |  ebnfAtom "+"                           { ProdRepeat1 $1 }

> ebnfAtom        :: { Production }
> ebnfAtom        :  id_tok                                 { ProdNonterminal $1 }
>                 |  any_string                             { ProdTerminal $1 }
>                 |  "(" ebnfTerm ")"                       { $2 }
>                 |  "[" ebnfTerm "]"                       { ProdOption $2 }   
>                 |  "{" ebnfTerm "}"                       { ProdRepeat $2 }



(2) happy specification for the happy input language

> happyInput       :: { [Production] }
> happyInput       :  happyOptCode 
>                     happyTokInfos 
>                     "%%" 
>                     happyRules 
>                     happyOptCode                          { happyPrepare $2 $4 }

> happyRules       :: { [Production] }
> happyRules       :  happyRule happyRules                  { $1 : $2 }
>                  |  happyRule                             { [$1] }

> happyRule        :: { Production }
> happyRule        :  id_tok "::" happyCode happyHRule      { ProdProduction $1 [] $4 }
>                  |  id_tok ":" happyProds                 { ProdProduction $1 [] 
>(ProdTerm $3) }

> happyHRule       :: { Production }
> happyHRule       :  id_tok ":" happyProds                 { ProdTerm $3 }
>                  |         ":" happyProds                 { ProdTerm $2 }

> happyProds       :: { [Production] }
> happyProds       :  happyProd "|" happyProds              { $1 : $3 }
>                  |  happyProd                             { [$1] }

> happyProd        :: { Production }
> happyProd        :  happyProdItems happyCode ";"          { ProdFactor $1 }
>                  |  happyProdItems happyCode              { ProdFactor $1 }

> happyProdItems   :: { [Production] }
> happyProdItems   :  happyProdItem happyProdItems          { $1 : $2 }
>                  |                                        { [] }

> happyProdItem    :: { Production }
> happyProdItem    :  any_string                            { ProdTerminal    $1 }
>                  |  id_tok                                { ProdNonterminal $1 }

> happyTokInfos    :: { [String] }
> happyTokInfos    :  happyTokInfo happyTokInfos            { $1 ++ $2 }
>                  |  happyTokInfo                          { $1 }

> happyTokInfo     :: { [String] }
> happyTokInfo     :  "%" id_tok happyTokInfoRest           { $3 }

> happyTokInfoRest :: { [String] }
> happyTokInfoRest :  happyCode                             { [] }
>                  |  id_tok                                { [] }
>                  |  happyCode happyCode happyCode         { [] }
>                  |  happyTokenList                        { $1 }      

> happyTokenList   :: { [String] }
> happyTokenList   :  id_tok happyCode happyTokenList       { $1 : $3 }
>                  |  any_string happyCode happyTokenList   { $3 }
>                  |                                        { [] }

here goes happy optCode:

> happyOptCode     :: { () }
> happyOptCode     :  happyCode                             { () }
>                  |                                        { () }

> happyCode        :: { () }
> happyCode        :  "{" happyCodeBody "}"                 { () }

> happyCodeBody    :: { () }
> happyCodeBody    :  happyCodeItem happyCodeBody           { () }
>                  |  happyCodeItem                         { () }

> happyCodeItem    :: { () }
> happyCodeItem    :  any_string                            { () }
>                  |  id_tok                                { () }
>                  |  happyCode                             { () }
>                  |  any_symbol                            { () }
>                  |  ":"                                   { () }
>                  |  ";"                                   { () }
>                  |  "::"                                  { () }
>                  |  "|"                                   { () }
>                  |  "%%"                                  { () }
>                  |  "%"                                   { () }



(3) happy specification for the yacc input language 

> yaccInput       :: { [Production] }
> yaccInput       :  "%%" yaccRules yaccEnd                 { yaccPrepare $2 }

> yaccRules       :: { [Production] }
> yaccRules       :  yaccRhs                                { [$1] }
>                 |  yaccRules yaccRule                     { $1 ++ [$2] }

> yaccRule        :: { Production }
> yaccRule        :  yaccRhs                                { $1 }
>                 |  "|" yaccRbody yaccPrec                 { ProdFactor $2 }

> yaccRhs         :: { Production }
> yaccRhs         :  cid_tok ":" yaccRbody yaccPrec         { ProdProduction $1 [] 
>(ProdTerm [ProdFactor $3]) }

> yaccRbody       :: { [Production] }
> yaccRbody       :  yaccRbody yaccIdent                    { $1 ++ [$2] }
>                 |  yaccRbody yaccAction                   { $1 }
>                 |                                         { [] }

> yaccPrec        :: { () }
> yaccPrec        :  "%" id_tok yaccIdent                   { () }
>                 |  "%" id_tok yaccIdent yaccAction        { () }
>                 | yaccPrec ";"                            { () }
>                 |                                         { () }

> yaccIdent       :: { Production }
> yaccIdent       :  id_tok                                 { ProdTerminal $1 }
>                 |  any_string                             { ProdTerminal $1 }

> yaccAction      :: { () }
> yaccAction      :  "{" "}"                                { () }

> yaccEnd         :: { () }
> yaccEnd         :  "%%"                                   { () }
>                 |                                         { () }




> {

alt, mit Zeilennummerangabe:
   > happyError :: Int -> [Token'] -> a
   > happyError i ts = error ("Parse error in (line " ++ show i ++ ") " ++
   >                          case ts of
   >                          [] -> " at EOF\n"
   >                          _  ->  "before\n" ++ showList (take 20 (dropWhile 
(==Newline) ts)) [] ++ "\n")

neu, ohne:
> happyError :: [Token'] -> a
> happyError ts = error ("Parse error in " ++
>                          case ts of
>                          [] -> " at EOF\n"
>                          _  ->  "before\n" ++ showList (take 20 (dropWhile 
>(==Newline) ts)) [] ++ "\n")

A preprocessor for literal scripts (slow)

> unlit :: String -> String
> unlit = unlines . map p . lines
>     where p ('>':' ':cs)  = cs
>           p ('>':'\t':cs) = cs
>           p _             = [] 

A preprocessor for yacc scripts 

> yaccpreprocessor :: String -> String 
> yaccpreprocessor "" = ""
> yaccpreprocessor ('%':'%':cs) = '%':'%': yaccRules cs
> yaccpreprocessor ('\n':cs)    = '\n':yaccpreprocessor cs
> yaccpreprocessor (_:cs)       = yaccpreprocessor cs   
 
> yaccRules :: String -> String 
> yaccRules "" = ""
> yaccRules ('/':'*':cs) = yaccRules (dropCComment 0 cs)
> yaccRules ('%':'{':cs) = yaccRules  (dropCSyntax cs)
> yaccRules ('%':'%':cs) = "%%" 
> yaccRules ('\'':'{':'\'':cs) = '\'':'{':'\'': yaccRules cs
> yaccRules ('{':cs)     = '{':yaccRules (dropActions 0 cs)
> yaccRules (c:cs)       = c:yaccRules cs
 
> dropCSyntax :: String -> String
> dropCSyntax "" = ""
> dropCSyntax ('%':'}':cs) = cs
> dropCSyntax ('\n':cs) = '\n':dropCSyntax cs
> dropCSyntax (c:cs) = dropCSyntax cs
 
> dropCComment :: Int -> String -> String
> dropCComment _ "" = ""
> dropCComment n ('/':'*':cs) = dropCComment (n+1) cs
> dropCComment n ('\n':cs) = '\n':dropCComment n cs
> dropCComment n ('*':'/':cs) 
>              | n == 0 = cs
>              | otherwise = dropCComment (n-1) cs
> dropCComment n (c:cs) = dropCComment n cs

 
> dropActions :: Int -> String -> String 
> dropActions _ "" = ""
> dropActions n ('"':cs) = dropActions n css where (_,css) = lexString cs
> dropActions n ('\'':'{':'\'':cs) = dropActions n cs
> dropActions n ('\'':'}':'\'':cs) = dropActions n cs
> dropActions n ('{':cs) = dropActions (n+1) cs
> dropActions n ('\n':cs) = '\n':dropActions n cs
> dropActions n ('}':cs) 
>             | n == 0 = '}':cs
>             | otherwise = dropActions (n-1) cs
> dropActions n (c:cs) = dropActions n cs                 


A postprocessor for a grammar in EBNF and a postprocessor to make happy happy

> data Token'
>        = EbnfInput
>        | HappyInput
>        | YaccInput
>        | Newline
>        | Ident'  String 
>        | CIdent' String
>        | Symbol' String
>        | String' String
>        | Number' String
>        | Percent
>        | DoublePercent
>        | OpenBrace  
>        | ClosingBrace
>        | Bar 
>        | SemiColon 
>        | DoubleColon 
>        | Colon
>        | OpenBrack 
>        | ClosingBrack
>        | OpenParen 
>        | ClosingParen
>        | Dot 
>        | Equal 
>        | Plus 
>        | Slash
>   deriving Eq


> instance Show Token' where 
>  showsPrec n (Ident' s) = showChar '[' . showString s . showString "] "
>  showsPrec n (CIdent' s) = showChar '/' . showString s . showString "/"
>  showsPrec n (Symbol' "\n") = showChar '\n'
>  showsPrec n (Symbol' s) = showChar '<' . showString s . showString "> "
>  showsPrec n (String' s) = showChar '"' . showString s . showString "\" "     
>  showsPrec n (Number' s) = showChar ' ' . showString s . showChar ' ' 
>  showsPrec n Percent = showString "%"
>  showsPrec n DoublePercent = showString "%% "
>  showsPrec n OpenBrace = showString "{ "
>  showsPrec n ClosingBrace = showString "} "
>  showsPrec n OpenBrack = showString "[ "
>  showsPrec n ClosingBrack = showString "] "
>  showsPrec n OpenParen = showString "( "
>  showsPrec n ClosingParen = showString ") "
>  showsPrec n Bar = showString "| "
>  showsPrec n SemiColon = showString "; "
>  showsPrec n DoubleColon = showString ":: "
>  showsPrec n Colon = showString ": "
>  showsPrec n Dot = showString ". "
>  showsPrec n Equal = showString "= "
>  showsPrec n Plus = showString "+ "
>  showsPrec n Slash = showString "/ "
>  showsPrec n Newline = showString "\n"
>  showsPrec n YaccInput = showString "\n>>YACC input format<<\n"
>  showsPrec n EbnfInput  = showString "\n>>EBNF input format<<\n" 
>  showsPrec n HappyInput = showString "\n>>HAPPY input format<<\n" 
>  showList [] = id
>  showList (x:xs) = shows x . showList xs


a ebnf postlexer

> ebnf_postlexer = \s -> EbnfInput : map f s
>   where f (Symbol "\n") = Newline
>         f (Symbol "=")  = Equal
>         f (Symbol ".")  = Dot
>         f (Symbol "|")  = Bar
>         f (Symbol "/")  = Slash
>         f (Symbol "+")  = Plus
>         f (Symbol "(")  = OpenParen
>         f (Symbol "[")  = OpenBrack
>         f (Symbol "{")  = OpenBrace
>         f (Symbol ")")  = ClosingParen                        
>         f (Symbol "]")  = ClosingBrack
>         f (Symbol "}")  = ClosingBrace
>         f (Symbol ";")  = SemiColon
>         f (Symbol s)    = Symbol' s
>         f (Ident s)     = Ident'  s
>         f (String s)    = String' s
>         f (Number n)    = Symbol' n

a happy postlexer

> happy_postlexer = \s -> HappyInput : map f s
>   where f (Symbol "\n") = Newline
>         f (Symbol "%%") = DoublePercent
>         f (Symbol "%")  = Percent
>         f (Symbol "{")  = OpenBrace
>         f (Symbol "}")  = ClosingBrace
>         f (Symbol "::") = DoubleColon
>         f (Symbol ":")  = Colon
>         f (Symbol ";")  = SemiColon
>         f (Symbol "|")  = Bar
>         f (Symbol s)    = Symbol' s
>         f (Ident s)     = Ident'  s
>         f (String s)    = String' s
>         f (Number n)    = Symbol' n

a yacc postlexer

> yacc_postlexer s = YaccInput : f s
>   where toSkip [] = False
>         toSkip (Symbol "\n":cs') = toSkip cs'
>         toSkip (Symbol ":":_) = True
>         toSkip (c:_) = False
>         f [] = []
>         f (Symbol "\n":cs) = Newline : f cs
>         f (Symbol "%":cs)  = Percent : f cs
>         f (Symbol "%%":cs) = DoublePercent : f cs
>         f (Symbol "|":cs)  = Bar : f cs
>         f (Symbol "{":cs)  = OpenBrace : f cs
>         f (Symbol "}":cs)  = ClosingBrace : f cs
>         f (Symbol ";":cs)  = SemiColon : f cs
>         f (Symbol ":":cs)  = Colon : f cs
>         f (Symbol c :cs) = (Symbol' c): f cs
>         f (String c :cs) = (String' c): f cs
>         f (Number c :cs) = (Number' c): f cs
>         f (Ident c :cs) | toSkip cs = (CIdent' c): f cs
>                         | otherwise = (Ident' c): f cs


> happyPrepare terminalsyms = map (happyPrepare' terminalsyms)
> happyPrepare' ts (ProdProduction s1 s2 prod)  = ProdProduction s1 s2 (happyPrepare' 
>ts prod)
> happyPrepare' ts (ProdFactor prods) = ProdFactor (map (happyPrepare' ts) prods)
> happyPrepare' ts (ProdTerminal s) = ProdTerminal s
> happyPrepare' ts (ProdOption prod) = ProdOption (happyPrepare' ts prod)
> happyPrepare' ts (ProdRepeat prod) = ProdRepeat (happyPrepare' ts prod)
> happyPrepare' ts (ProdRepeat1 prod) = ProdRepeat1 (happyPrepare' ts prod)
> happyPrepare' ts (ProdRepeatWithAtom p1 p2) = ProdRepeatWithAtom (happyPrepare' ts 
>p1) (happyPrepare' ts p2)
> happyPrepare' ts (ProdPlus) = ProdPlus
> happyPrepare' ts (ProdSlash prod) = ProdSlash (happyPrepare' ts prod)
> happyPrepare' ts (ProdTerm prods) = ProdTerm (map (happyPrepare' ts) prods)
> happyPrepare' ts (ProdNonterminal s) 
>      | s `elem` ts = ProdTerminal s
>      | otherwise   = ProdNonterminal s

                
> yaccPrepare happyresult =
>   [noDup (getNt nt) | nt <- nub nonterminals]
>   where (nonterminals, prods) = transform happyresult [] []
>         getNt str = [yaccPrepare' nonterminals p | p@(ProdProduction nt _ _) <- 
>prods, str == nt] 
>         transform [] as bs = (as,bs)
>         transform ((ProdProduction nt aliases (ProdTerm ps)):pss) as bs =
>               transform pss' (nt:as) bs'
>               where (factors, pss') = span isProdFactor pss 
>                     bs' = bs ++ [ProdProduction nt aliases (ProdTerm ps')]
>                     ps' = ps ++ factors       
>         noDup [p] = p
>         noDup (ProdProduction nt aliases (ProdTerm ps):p':ps') = 
>               ProdProduction nt aliases 
>                (ProdTerm (foldr (\ (ProdProduction _ _ (ProdTerm prods')) ps1 -> 
>ps1++prods') ps (p':ps')))
>         isProdFactor p = case p of { ProdFactor _ -> True;  _ -> False}

> yaccPrepare' nts (ProdProduction s1 s2 prod) = ProdProduction s1 s2 (yaccPrepare' 
>nts prod)
> yaccPrepare' nts (ProdFactor prods) = ProdFactor (map (yaccPrepare' nts) prods)
> yaccPrepare' nts (ProdTerm prods) = ProdTerm (map (yaccPrepare' nts) prods)
> yaccPrepare' nts (ProdOption prod) = ProdOption (yaccPrepare' nts prod)
> yaccPrepare' nts (ProdRepeat prod) = ProdRepeat (yaccPrepare' nts prod)
> yaccPrepare' nts (ProdRepeat1 prod) = ProdRepeat1 (yaccPrepare' nts prod)
> yaccPrepare' nts (ProdRepeatWithAtom p1 p2) = ProdRepeatWithAtom (yaccPrepare' nts 
>p1) (yaccPrepare' nts p2)
> yaccPrepare' nts (ProdPlus) = ProdPlus
> yaccPrepare' nts (ProdSlash prod) = ProdSlash (yaccPrepare' nts prod)
> yaccPrepare' nts (ProdTerminal s) 
>     | s `elem` nts = ProdNonterminal s
>     | otherwise = ProdTerminal s


> theEbnfParser  = ebnf2psParser . ebnf_postlexer  . lexer . uncomment
> theHappyParser = ebnf2psParser . happy_postlexer . lexer . unlit
> theYaccParser  = ebnf2psParser . yacc_postlexer  . lexer . yaccpreprocessor

> }


Reply via email to