ubcc/src/Ubc/Parse/Syntax/Struct.hs

56 lines
1.9 KiB
Haskell

module Ubc.Parse.Syntax.Struct
( Struct(..)
, parse
)
where
import Control.Monad ((<$!>))
import Text.Parsec
( choice,
many,
try,
ParsecT,
)
import Ubc.Parse.Syntax.Data.Struct (Struct(..))
import Ubc.Parse.Syntax.VariableType (VariableType)
import qualified Ubc.Parse.Syntax.Language as UbcLanguage
import qualified Ubc.Parse.Syntax.VariableType as VariableType
import qualified Ubc.Parse.Syntax.Data.Struct as Struct
import qualified Ubc.Parse.Syntax.Function as Function
type VariableName = String
data StructStatement = Variable VariableName VariableType
| Function Function.Function
parse :: Monad m => ParsecT String u m Struct
parse = do
_ <- UbcLanguage.reserved "struct"
structIdentifier <- UbcLanguage.identifier
foldl accumulateStruct (Struct structIdentifier [] []) <$!> UbcLanguage.braces (many structMember)
accumulateStruct :: Struct -> StructStatement -> Struct
accumulateStruct s (Variable n t) = Struct.addVariable s n t
accumulateStruct s (Function f) = Struct.addFunction s f
structMember :: Monad m => ParsecT String u m StructStatement
structMember = choice [ structVariableOrFunction ]
structVariableOrFunction :: Monad m => ParsecT String u m StructStatement
structVariableOrFunction = do
(typeName, identifier) <- try $ do
typeName <- UbcLanguage.typeName
objectIdentifier <- UbcLanguage.identifier
return (VariableType.fromString typeName, objectIdentifier)
choice
[ parseVariable typeName identifier
, Function <$!> Function.parsePrefixed typeName identifier
] -- TODO: Functions on structs
parseVariable :: Monad m => VariableType -> String -> ParsecT String u m StructStatement
parseVariable variableType variableName = do
_ <- UbcLanguage.semicolon
return $ Variable variableName variableType