module ParserGen.Types
( Decl (..)
, unzipDecls
, Datatype (..)
, DataConstructor (..)
, getConstructorWidth
, DataField (..)
, getFieldWidth
, getFieldRepeatType
, getFieldHasRepeat
, getFieldIsIgnored
, ParserType (..)
, Repacker (..)
, RepackerField (..)
) where
import Data.Maybe (isJust, isNothing)
import Language.Haskell.TH (Exp, Type (..))
data Decl
= DatatypeDecl Datatype
| RepackerDecl Repacker
deriving (Show)
unzipDecls :: [Decl] -> ([Datatype], [Repacker])
unzipDecls decls =
( [d | DatatypeDecl d <- decls]
, [r | RepackerDecl r <- decls]
)
data Datatype
= Datatype
{ typeName :: String
, typeConstrs :: [DataConstructor]
} deriving (Show)
data DataConstructor
= DataConstructor
{ constrName :: String
, constrPrefix :: Maybe String
, constrFields :: [DataField]
} deriving (Show)
getConstructorWidth :: DataConstructor -> Int
getConstructorWidth = sum . map getFieldWidth . constrFields
data DataField
= DataField
{ fieldName :: Maybe String
, fieldRepeat :: Maybe Int
, fieldType :: Type
, fieldStrict :: Bool
, fieldWidth :: Int
, fieldParser :: ParserType
} deriving (Show)
getFieldWidth :: DataField -> Int
getFieldWidth (DataField {..}) =
let width = fieldWidth + if fieldParser == SignedParser then 1 else 0
times = maybe 1 id fieldRepeat
in width * times
getFieldRepeatType :: DataField -> Type
getFieldRepeatType df
| getFieldHasRepeat df = AppT ListT $ fieldType df
| otherwise = fieldType df
getFieldHasRepeat :: DataField -> Bool
getFieldHasRepeat = isJust . fieldRepeat
getFieldIsIgnored :: DataField -> Bool
getFieldIsIgnored = isNothing . fieldName
data ParserType
= CustomParser Exp
| UnsignedParser
| SignedParser
| HardcodedString String
deriving (Show, Eq)
data Repacker = Repacker
{ repackerName :: String
, repackerConstructor :: String
, repackerFields :: [RepackerField]
} deriving (Show)
data RepackerField = RepackerField
{ repackerFieldName :: String
, repackerFieldUnparser :: Maybe Exp
} deriving (Show)