MorphParser.hs revision 3d3889e0cefcdce9b3f43c53aaa201943ac2e895
module LF.MorphParser where
import LF.Sign
import LF.Morphism
import Common.Lexer
import Common.Parsec
import Common.AnnoParser (commentLine)
import Text.ParserCombinators.Parsec
import System.Directory
import System.IO.Unsafe
import qualified Data.Map as Map
import Data.Maybe (fromMaybe)
readMorphism :: FilePath -> Morphism
readMorphism file =
let mor = unsafePerformIO $ readMorph file
in fromMaybe (error $ "readMorphism : Could not read the " ++
"morphism from " ++ show file) mor
readMorph :: FilePath -> IO (Maybe Morphism)
readMorph file = do
e <- doesFileExist file
if e then do
content <- readFile file
case runParser (parseMorphism << eof) () file content of
Right m -> return $ Just m
Left err -> error $ show err
else return Nothing
parseMorphism :: CharParser st Morphism
parseMorphism = do
skips $ manyTill anyChar (string "=")
pkeyword "Morphism"
skipChar '{'
mb <- parseWithEq "morphBase"
skipChar ','
mm <- parseWithEq "morphModule"
skipChar ','
mn <- parseWithEq "morphName"
skipChar ','
pkeyword "source"
skipChar '='
s <- parseSignature
skipChar ','
pkeyword "target"
skipChar '='
t <- parseSignature
skipChar ','
pkeyword "morphType"
skipChar '='
mt <- parseMorphType
skipChar ','
pkeyword "symMap"
skipChar '='
sm <- parseMap
skipChar '}'
return $ Morphism mb mm mn s t mt sm
-- | plain string parser with skip
pkeyword :: String -> CharParser st ()
pkeyword s = keywordNotFollowedBy s (alphaNum <|> char '/') >> return ()
keywordNotFollowedBy :: String -> CharParser st Char -> CharParser st String
keywordNotFollowedBy s c = skips $ try $ string s << notFollowedBy c
skips :: CharParser st a -> CharParser st a
skips = (<< skipMany
(forget space <|> forget commentLine <|> nestCommentOut <?> ""))
qString :: CharParser st String
qString = skips endsWithQuot
parensP :: CharParser st a -> CharParser st a
parensP p = between (skipChar '(') (skipChar ')') p
<|> p
bracesP :: CharParser st a -> CharParser st a
bracesP = between (skipChar '{') (skipChar '}')
bracketsP :: CharParser st a -> CharParser st a
bracketsP = between (skipChar '[') (skipChar ']')
endsWithQuot :: CharParser st String
endsWithQuot = do
skipChar '"'
manyTill anyChar (string "\"")
commaP :: CharParser st ()
commaP = skipChar ',' >> return ()
sepByComma :: CharParser st a -> CharParser st [a]
sepByComma p = sepBy1 p commaP
skipChar :: Char -> CharParser st ()
skipChar = forget . skips . char
parseWithEq :: String -> CharParser st String
parseWithEq s = do
pkeyword s
skipChar '='
qString
parseSym :: CharParser st Symbol
parseSym = do
pkeyword "Symbol"
skipChar '{'
sb <- parseWithEq "symBase"
skipChar ','
sm <- parseWithEq "symModule"
skipChar ','
sn <- parseWithEq "symName"
skipChar '}'
return $ Symbol sb sm sn
parse1Context :: CharParser st CONTEXT
parse1Context = do
skipChar '('
v <- qString
skipChar ','
e <- parseExp
option () $ skipChar ')'
return [(v, e)]
parseExp :: CharParser st EXP
parseExp = (pkeyword "Type" >> return Type)
<|> do
pkeyword "Var"
fmap Var qString
<|> do
pkeyword "Const"
fmap Const parseSym
<|> do
pkeyword "Appl"
ex <- parensP parseExp
exl <- bracketsP $ option [] $ sepByComma parseExp
return $ Appl ex exl
<|> do
pkeyword "Func"
exl <- bracketsP $ option [] $ sepByComma parseExp
ex <- parensP parseExp
return $ Func exl ex
<|> do
ty <- choice $ map (\ ty -> pkeyword ty >> return ty)
["Pi", "Lamb"]
c <- bracketsP $ option [] $ sepByComma parse1Context
e <- parensP parseExp
return $ (case ty of
"Pi" -> Pi
"Lamb" -> Lamb
_ -> error "Pi or Lamb expected.\n") (concat c) e
parseDef :: CharParser st DEF
parseDef = do
pkeyword "Def"
skipChar '{'
pkeyword "getSym"
skipChar '='
sym <- parseSym
skipChar ','
pkeyword "getType"
skipChar '='
tp <- parseExp
skipChar ','
pkeyword "getValue"
skipChar '='
val <- (pkeyword "Nothing" >> return Nothing)
<|> do pkeyword "Just"
e <- parensP parseExp
return $ Just e
skipChar '}'
return $ Def sym tp val
parseSignature :: CharParser st Sign
parseSignature = do
pkeyword "Sign"
skipChar '{'
sb <- parseWithEq "sigBase"
skipChar ','
sm <- parseWithEq "sigModule"
skipChar ','
pkeyword "getDefs"
skipChar '='
sd <- bracketsP $ option [] $ sepByComma parseDef
skipChar '}'
return $ Sign sb sm sd
parseMorphType :: CharParser st MorphType
parseMorphType =
choice $ map (\ t -> pkeyword (show t) >> return t)
[Definitional, Postulated, Unknown ]
parse1Map :: CharParser st (Symbol, EXP)
parse1Map = do
skipChar '('
s <- parseSym
skipChar ','
e <- parseExp
skipChar ')'
return (s, e)
parseMap :: CharParser st (Map.Map Symbol EXP)
parseMap = do
pkeyword "fromList"
fmap Map.fromList $ bracketsP $ option [] $ sepByComma parse1Map