{-# LANGUAGE NoImplicitPrelude #-} {- BNF Converter: Template Generator Copyright (C) 2004 Author: Markus Forberg 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA -} module BNFC.Backend.Haskell.CFtoTemplate (cf2Template) where import Prelude' import BNFC.Backend.Haskell.Utils (catvars) import BNFC.CF import BNFC.PrettyPrint type ModuleName = String cf2Template :: ModuleName -> ModuleName -> ModuleName -> Bool -> CF -> String cf2Template skelName absName errName functor cf = unlines [ "module "++ skelName ++ " where\n" , "-- Haskell module generated by the BNF converter\n" , "import " ++ absName , "import " ++ errName , "type Result = Err String\n" , "failure :: Show a => a -> Result" , "failure x = Bad $ \"Undefined case: \" ++ show x\n" , unlines $ map (render . \(s,xs) -> case_fun functor s xs) $ specialData cf ++ cf2data cf ] {- ---- cf2Template :: ModuleName -> CF -> String cf2Template name cf = unlines [ "module Skel"++ name ++ " where\n", "-- Haskell module generated by the BNF converter\n", "import Abs" ++ name, "import ErrM", "type Result = Err String\n", "failure :: Show a => a -> Result", "failure x = Bad $ \"Undefined case: \" ++ show x\n", unlines $ map (\(s,xs) -> case_fun s (toArgs xs)) $ specialData cf ++ cf2data cf ] where toArgs [] = [] toArgs ((cons,args):xs) = (cons ++ " " ++ names False (map (checkRes . var) args) (1 :: Int)) : toArgs xs names _ [] _ = [] names b (x:xs) n | elem x xs = (x ++ show n) ++ " " ++ names True xs (n+1) | otherwise = (x ++ if b then show n else "") ++ " " ++ names b xs (if b then n+1 else 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"] -} -- | -- >>> case_fun False (Cat "Expr") [("EInt", [TokenCat "Integer"]), ("EAdd", [Cat "Expr", Cat "Expr"])] -- transExpr :: Expr -> Result -- transExpr x = case x of -- EInt integer -> failure x -- EAdd expr1 expr2 -> failure x -- -- >>> case_fun True (Cat "Expr") [("EInt", [TokenCat "Integer"]), ("EAdd", [Cat "Expr", Cat "Expr"])] -- transExpr :: Show a => Expr a -> Result -- transExpr x = case x of -- EInt _ integer -> failure x -- EAdd _ expr1 expr2 -> failure x -- -- TokenCat are not generated as functors: -- >>> case_fun True (TokenCat "MyIdent") [("MyIdent", [TokenCat "String"])] -- transMyIdent :: MyIdent -> Result -- transMyIdent x = case x of -- MyIdent string -> failure x case_fun :: Bool -> Cat -> [(Fun,[Cat])] -> Doc case_fun functor' cat xs = vcat [ fname <+> "::" <+> iffunctor "Show a =>" <+> type_ <+> "-> Result" , fname <+> "x = case x of" , nest 2 $ vcat (map mkOne xs) ] where -- If the functor option is set AND the category is not a token type, -- then the type is a functor. iffunctor doc | functor' && not (isTokenCat cat) = doc | otherwise = empty type_ = cat' <+> iffunctor "a" fname = "trans" <> cat' cat' = text (show cat) mkOne (cons, args) = let ns = catvars args -- names False (map (checkRes .var) args) 1 in text cons <+> iffunctor "_" <+> hsep ns <+> "-> failure x"