ehaskell-0.7: EHaskell.hs
module EHaskell (
mkEhsSrc
) where
import Data.Char (isSpace, isAlphaNum)
import Data.Bool.Tools ((|||))
import Control.Monad.Tools (skipRet)
import Text.ParserCombinators.MTLParse (Parse, runParse, spot, token, tokens,
mplus, list, neList, optional,
endOfInput, still,
parseNot)
import Types (CodeText(..))
import MkCode (arrangeCode, mkSrcText, mkSrcCode,
mkSrcBegin, mkSrcCont, mkSrcEnd,
mkSrcImport, mkSrcDefinition, mkSrcTop,
mkSrcEq, mkSrcEqEq, mkSrcEqShow, mkSrcEqEqShow)
import GetCodeText (getCodeText)
data CodePos = Import { getModName :: String } | Top |
Definition { getVar :: String } | Inner
deriving (Eq, Show)
isImport, isDefinition :: CodePos -> Bool
isImport (Import _) = True
isImport _ = False
isDefinition (Definition _) = True
isDefinition _ = False
mkEhsSrc :: [ (String, String) ] -> String -> (String, [String])
mkEhsSrc defs src
= let posSrcPair = fst $ myHead $ runParse parsePairAll ([], getCodeText src)
importSrc = concat $ mLookupBy isImport posSrcPair
defSrc = concat (map snd $ deleteDef (map fst defs) posSrcPair) ++
unlines (map (\(var, val) -> var ++ " = " ++ val) defs)
topSrc = concat $ mLookup Top posSrcPair
innerSrc = concat $ mLookup Inner posSrcPair
mods = map getModName $ filter isImport $ map fst posSrcPair
in (arrangeCode (importSrc ++ defSrc ++ topSrc) innerSrc, mods)
where myHead (h:_) = h
myHead _ = error "parsePairAll in EHaskellNew module: parse error"
deleteDef :: [ String ] -> [ (CodePos, String) ] -> [ (CodePos, String) ]
deleteDef vars pairs = filter (flip notElem vars . getVar . fst) $
filter (isDefinition . fst ) pairs
parsePairAll, parsePair :: Parse (CodeText, String) [ (CodePos, String) ]
parsePairAll
= parsePair >>= endOfInput
parsePair
= fmap concat $ list $ parsePairText `mplus` parsePairCode `mplus`
parsePairTop `mplus` parsePairApply `mplus`
parsePairEq `mplus` parsePairEqEq `mplus`
parsePairEqShow `mplus` parsePairEqEqShow
parsePairText, parsePairCode, parsePairTop, parsePairApply,
parsePairEq, parsePairEqEq, parsePairEqShow, parsePairEqEqShow
:: Parse (CodeText, String) [ (CodePos, String) ]
parsePairText = do
(_, src) <- spot ((==Text).fst)
return [ (Inner, mkSrcText src) ]
parsePairCode = do
(_, src) <- spot ((==Code).fst)
return [ (Inner, mkSrcCode src) ]
parsePairTop = do
(_, src) <- spot ((==CodeTop).fst)
return [ makeIDT src ]
parsePairApply = do
(_, srcB) <- spot ((==CodeBegin).fst)
pcf <- parsePair
pcs <- fmap concat $ list $ do
(_, srcC) <- spot ((==CodeCont).fst)
pcsGen <- parsePair
return $ (Inner, mkSrcCont srcC) : pcsGen
(_, srcE) <- spot ((==CodeEnd).fst)
return $ (Inner, mkSrcBegin srcB) : pcf ++ pcs ++ [ (Inner, mkSrcEnd srcE) ]
parsePairEq = do
(_, src) <- spot ((==CodeEq).fst)
return $ [ (Inner, mkSrcEq src) ]
parsePairEqShow = do
(_, src) <- spot ((==CodeEqShow).fst)
return $ [ (Inner, mkSrcEqShow src) ]
parsePairEqEq = do
(_, src) <- spot ((==CodeEqEq).fst)
return $ [ (Inner, mkSrcEqEq src) ]
parsePairEqEqShow = do
(_, src) <- spot ((==CodeEqEqShow).fst)
return $ [ (Inner, mkSrcEqEqShow src) ]
makeIDT :: String -> ( CodePos, String )
makeIDT = fst . myHead . runParse parseIDT . (,) ""
where myHead (h:_) = h
myHead _ = error "parseIDT in EHaskellNew: parse error"
parseIDT, parseImport, parseDefinition, parseTop
:: Parse Char ( CodePos, String )
parseIDT = parseImport `mplus` parseDefinition `mplus` parseTop
parseImport = do
list $ spot isSpace
tokens "import"
neList $ spot isSpace
mdl <- list $ spot $ isAlphaNum ||| flip elem "."
imps <- fmap concat $ optional $ do
list $ spot isSpace
token '('
list (spot $ const True) >>= skipRet (token ')')
list $ spot isSpace
endOfInput ()
return (Import mdl, mkSrcImport mdl imps)
parseDefinition = do
list $ spot isSpace
var <- list (spot isVarChar) >>= skipRet (still $ spot $ not . isVarChar)
list $ spot isSpace
token '=' >> still (spot $ not . isSymbol)
list $ spot isSpace
val <- list (spot $ const True) >>= endOfInput
return (Definition var, mkSrcDefinition var val)
where
isVarChar = isAlphaNum ||| flip elem "_"
isSymbol = flip elem "!#$%&*+./<=>?@\\^|-~"
parseTop = do
still $ parseNot () $ parseImport `mplus` parseDefinition
list (spot isSpace) >> still (spot $ not . isSpace)
src <- list (spot $ const True) >>= endOfInput
return (Top, mkSrcTop src)
mLookup :: Eq a => a -> [ (a, b) ] -> [ b ]
mLookup x ps = map snd $ filter ((x==).fst) ps
mLookupBy :: (a -> Bool) -> [ (a, b) ] -> [ b ]
mLookupBy p ps = map snd $ filter (p . fst) ps