{-# LANGUAGE TemplateHaskell #-} {- BNF Converter: Pretty-printer generator Copyright (C) 2004 Author: Aarne Ranta This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -} module Language.LBNF.CFtoPrinter (cf2Printer) where import Language.LBNF.CF import Language.LBNF.Utils import Language.LBNF.Runtime import Data.List (intersperse) import Data.Char(toLower) import Language.Haskell.TH import Language.Haskell.TH.Syntax cf2Printer :: CF -> Q [Dec] cf2Printer cf = sequence $ concat [ if hasIdent cf then [identRule cf] else [], [ownPrintRule cf own | (own,_) <- tokenPragmas cf], rules cf ] {- showsPrintRule cf t = unlines $ [ "instance Print " ++ t ++ " where", " prt _ x = doc (shows x)", ifList cf t ] -} identRule cf = ownPrintRule cf "Ident" ownPrintRule :: CF -> String -> DecQ ownPrintRule cf own = do i <- newName "i" let posn = if isPositionCat cf own then conP (mkName own) [tupP [wildP, varP i]] else conP (mkName own) [varP i] body = normalB [|doc (showString $(varE i))|] prtc = funD ('prt) [clause [wildP, posn] body []] instanceD (cxt []) (appT (conT $ ''Print) $ conT $ mkName own) [prtc] {-unlines $ [ "instance Print " ++ own ++ " where", " prt _ (" ++ own ++ posn ++ ") = doc (showString i)", ifList cf own ] where posn = if isPositionCat cf own then " (_,i)" else " i" -} -- copy and paste from CFtoTemplate rules :: CF -> [Q Dec] rules cf = map (\(s,xs) -> case_fun s (map toArgs xs) (ifList cf s)) $ cf2data cf where toArgs (cons,Left args) = ((cons, names (map (checkRes . var) args) (0 :: Int)), ruleOf cons) toArgs (cons,Right reg) = ((cons, names ["s"] (0 :: Int)), ruleOf cons) names [] _ = [] names (x:xs) n | elem x xs = (x ++ show n) : names xs (n+1) | otherwise = x : names xs n var ('[':xs) = var (init xs) ++ "s" var "Ident" = "id" var "Integer" = "n" var "String" = "str" var "Char" = "c" var "Double" = "d" var xs = map toLower xs checkRes s | elem s reservedHaskell = s ++ "'" | otherwise = s reservedHaskell = ["case","class","data","default","deriving","do","else","if", "import","in","infix","infixl","infixr","instance","let","module", "newtype","of","then","type","where","as","qualified","hiding"] ruleOf s = maybe undefined id $ lookup s (rulesOfCF cf) -- case_fun :: Cat -> [(Con,Rule)] -> Q Dec case_fun cat xs lst = instanceD (cxt []) (appT (conT ''Print) $ conT $ mkName cat) $ [newName "i" >>= \i -> newName "x" >>= prtc i] ++ lst where prtc i n = funD ('prt) [clause [varP i,varP n] (body) []] where body = normalB $ caseE (varE n) $ map mtch xs mtch ((c,xx),r) = match (conP (mkName c) [varP (mkName x)|x <- xx]) (normalB [| prPrec $(varE i) $(litE $ IntegerL $ toInteger $ precCat $ fst r) $(mkRhs xx (snd r)) |]) [] {- unlines [ "instance Print" +++ cat +++ "where", " prt i" +++ "e = case e of", unlines $ map (\ ((c,xx),r) -> " " ++ c +++ unwords xx +++ "->" +++ "prPrec i" +++ show (precCat (fst r)) +++ mkRhs xx (snd r)) xs ] -} ifList :: CF -> String -> [DecQ] ifList cf cat = mkListRule $ nil cat ++ one cat ++ cons cat where nil cat = [(listP [],mkRhs [] its) | (f,(c,its)) <- rulesOfCF cf, isNilFun f , normCatOfList c == cat] one cat = [(listP [varP $ mkName "x"], mkRhs ["x"] its) | (f,(c,its)) <- rulesOfCF cf, isOneFun f , normCatOfList c == cat] cons cat = [(conP '(:) [varP $ mkName "x",varP $ mkName "xs"], mkRhs ["x","xs"] its) | (f,(c,its)) <- rulesOfCF cf, isConsFun f , normCatOfList c == cat] mkListRule [] = [] mkListRule rs = [do es <- newName "es" funD 'prtList [clause [varP es] (normalB $ caseE (varE es) $ map mtch rs) []]] mtch (p,e) = match p (normalB e) [] mkRhs :: [String] -> Either [Either String String] a -> ExpQ mkRhs args (Left its) = [| concatD $(listE $ mk args its) |] where mk args (Left "#" : items) = mk args items mk (arg:args) (Left c : items) = prt' c (arg) : mk args items mk args (Right s : items) = [| doc (showString $(lift (s :: String))) |] : mk args items mk _ _ = [] prt' :: String -> String -> ExpQ prt' c arg = [| prt $(lift $ precCat c) $(varE $ mkName arg) |] mkRhs args (Right reg) = [|doc (showString $(varE $ mkName "s"))|] {- "(concatD [" ++ unwords (intersperse "," (mk args its)) ++ "])" where mk args (Left "#" : items) = mk args items mk (arg:args) (Left c : items) = (prt c +++ arg) : mk args items mk args (Right s : items) = ("doc (showString" +++ show s ++ ")") : mk args items mk _ _ = [] prt c = "prt" +++ show (precCat c) -}