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