{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE Safe #-}
module Parser.TypeCategory (
parseFilters,
parseScope,
parseScopedFunction,
singleDefine,
singleFilter,
singleRefine,
) where
import Text.Parsec
import Text.Parsec.String
import Parser.Common
import Parser.TypeInstance ()
import Types.Positional
import Types.TypeCategory
import Types.TypeInstance
import Types.Variance
instance ParseFromSource (AnyCategory SourcePos) where
sourceParser = parseValue <|> parseInstance <|> parseConcrete where
open = sepAfter (string_ "{")
close = sepAfter (string_ "}")
parseValue = labeled "value interface" $ do
c <- getPosition
try $ kwValue >> kwInterface
n <- sourceParser
ps <- parseCategoryParams
open
(rs,vs) <- parseRefinesFilters
fs <- flip sepBy optionalSpace $ parseScopedFunction (return ValueScope) (return n)
close
return $ ValueInterface [c] NoNamespace n ps rs vs fs
parseInstance = labeled "type interface" $ do
c <- getPosition
try $ kwType >> kwInterface
n <- sourceParser
ps <- parseCategoryParams
open
vs <- parseFilters
fs <- flip sepBy optionalSpace $ parseScopedFunction (return TypeScope) (return n)
close
return $ InstanceInterface [c] NoNamespace n ps vs fs
parseConcrete = labeled "concrete type" $ do
c <- getPosition
try kwConcrete
n <- sourceParser
ps <- parseCategoryParams
open
(rs,ds,vs) <- parseRefinesDefinesFilters
fs <- flip sepBy optionalSpace $ parseScopedFunction parseScope (return n)
close
return $ ValueConcrete [c] NoNamespace n ps rs ds vs fs
parseCategoryParams :: Parser [ValueParam SourcePos]
parseCategoryParams = do
(con,inv,cov) <- none <|> try fixedOnly <|> try noFixed <|> try explicitFixed
return $ map (apply Contravariant) con ++
map (apply Invariant) inv ++
map (apply Covariant) cov
where
none = do
notFollowedBy (string "<")
return ([],[],[])
fixedOnly = do
inv <- between (sepAfter $ string_ "<")
(sepAfter $ string_ ">")
(sepBy singleParam (sepAfter $ string_ ","))
return ([],inv,[])
noFixed = do
con <- between (sepAfter $ string_ "<")
(sepAfter $ string_ "|")
(sepBy singleParam (sepAfter $ string_ ","))
cov <- between nullParse
(sepAfter $ string_ ">")
(sepBy singleParam (sepAfter $ string_ ","))
return (con,[],cov)
explicitFixed = do
con <- between (sepAfter $ string_ "<")
(sepAfter $ string_ "|")
(sepBy singleParam (sepAfter $ string_ ","))
inv <- between nullParse
(sepAfter $ string_ "|")
(sepBy singleParam (sepAfter $ string_ ","))
cov <- between nullParse
(sepAfter $ string_ ">")
(sepBy singleParam (sepAfter $ string_ ","))
return (con,inv,cov)
singleParam = labeled "param declaration" $ do
c <- getPosition
n <- sourceParser
return (c,n)
apply v (c,n) = ValueParam [c] n v
singleRefine :: Parser (ValueRefine SourcePos)
singleRefine = do
c <- getPosition
try kwRefines
t <- sourceParser
return $ ValueRefine [c] t
singleDefine :: Parser (ValueDefine SourcePos)
singleDefine = do
c <- getPosition
try kwDefines
t <- sourceParser
return $ ValueDefine [c] t
singleFilter :: Parser (ParamFilter SourcePos)
singleFilter = try $ do
c <- getPosition
n <- sourceParser
f <- sourceParser
return $ ParamFilter [c] n f
parseCategoryRefines :: Parser [ValueRefine SourcePos]
parseCategoryRefines = sepAfter $ sepBy singleRefine optionalSpace
parseFilters :: Parser [ParamFilter SourcePos]
parseFilters = sepBy singleFilter optionalSpace
parseRefinesFilters :: Parser ([ValueRefine SourcePos],[ParamFilter SourcePos])
parseRefinesFilters = parsed >>= return . merge2 where
parsed = sepBy anyType optionalSpace
anyType = labeled "refine or param filter" $ put12 singleRefine <|> put22 singleFilter
parseRefinesDefinesFilters :: Parser ([ValueRefine SourcePos],
[ValueDefine SourcePos],
[ParamFilter SourcePos])
parseRefinesDefinesFilters = parsed >>= return . merge3 where
parsed = sepBy anyType optionalSpace
anyType =
labeled "refine or define or param filter" $ put13 singleRefine <|> put23 singleDefine <|> put33 singleFilter
instance ParseFromSource FunctionName where
sourceParser = labeled "function name" $ do
noKeywords
b <- lower
e <- sepAfter $ many alphaNum
return $ FunctionName (b:e)
parseScopedFunction :: Parser SymbolScope -> Parser CategoryName ->
Parser (ScopedFunction SourcePos)
parseScopedFunction sp tp = labeled "function" $ do
c <- getPosition
s <- try sp
t <- try tp
n <- try sourceParser
ps <- fmap Positional $ noParams <|> someParams
fa <- parseFilters
as <- fmap Positional $ typeList "argument type"
sepAfter_ (string "->")
rs <- fmap Positional $ typeList "return type"
return $ ScopedFunction [c] n t s as rs ps fa []
where
noParams = notFollowedBy (string "<") >> return []
someParams = between (sepAfter $ string_ "<")
(sepAfter $ string_ ">")
(sepBy singleParam (sepAfter $ string ","))
singleParam = labeled "param declaration" $ do
c <- getPosition
n <- sourceParser
return $ ValueParam [c] n Invariant
typeList l = between (sepAfter $ string_ "(")
(sepAfter $ string_ ")")
(sepBy (labeled l $ singleType) (sepAfter $ string ","))
singleType = do
c <- getPosition
t <- sourceParser
return $ PassedValue [c] t
parseScope :: Parser SymbolScope
parseScope = try categoryScope <|> try typeScope <|> valueScope
categoryScope :: Parser SymbolScope
categoryScope = kwCategory >> return CategoryScope
typeScope :: Parser SymbolScope
typeScope = kwType >> return TypeScope
valueScope :: Parser SymbolScope
valueScope = kwValue >> return ValueScope