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 > }