module Language.GroteTrap.Language (
Language(..), language,
Operator(..),
Fixity1(..), Fixity2(..),
isUnary, isBinary, isAssoc,
findOperator,
Function(..),
findFunction,
function1, function2
) where
data Language a = Language
{ variable :: Maybe (String -> a)
, number :: Maybe (Int -> a)
, operators :: [Operator a]
, functions :: [Function a]
}
language :: Language a
language = Language
{ variable = Nothing
, number = Nothing
, operators = []
, functions = []
}
data Operator a
=
Unary
{ opSem1 :: a -> a
, opFixity1 :: Fixity1
, opPrio :: Int
, opToken :: String
}
|
Binary
{ opSem2 :: a -> a -> a
, opFixity2 :: Fixity2
, opPrio :: Int
, opToken :: String
}
|
Assoc
{ opSemN :: [a] -> a
, opPrio :: Int
, opToken :: String
}
data Fixity1
= Prefix
| Postfix
deriving (Show, Enum, Eq)
data Fixity2
= InfixL
| InfixR
deriving (Show, Enum, Eq)
isUnary, isBinary, isAssoc :: Operator a -> Bool
isUnary (Unary _ _ _ _) = True
isUnary _ = False
isBinary (Binary _ _ _ _) = True
isBinary _ = False
isAssoc (Assoc _ _ _) = True
isAssoc _ = False
findOperator :: Monad m => String -> (Operator a -> Bool) -> [Operator a] -> m (Operator a)
findOperator name f os = case filter (\o -> f o && opToken o == name) os of
[] -> fail ("no such operator: " ++ name)
[o] -> return o
_ -> fail ("duplicate operator: " ++ name)
data Function a = Function
{ fnSem :: [a] -> a
, fnName :: String
}
function1 :: (a -> a) -> String -> Function a
function1 f = Function (\[x] -> f x)
function2 :: (a -> a -> a) -> String -> Function a
function2 f = Function (\[x, y] -> f x y)
findFunction :: Monad m => String -> [Function a] -> m (Function a)
findFunction name fs = case filter ((== name) . fnName) fs of
[] -> fail ("no such function: " ++ name)
[f] -> return f
_ -> fail ("duplicate function: " ++ name)