parsergen-0.2.0.3: src/ParserGen/Types.hs
{-# LANGUAGE RecordWildCards #-}
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)
-- get size to skip taking into account its repetition and sign if exists
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 df = case fieldParser df of
CustomParser _ -> False
HardcodedString _ -> False
_ -> isNothing (fieldName df)
data ParserType
= CustomParser Exp -- user provided parser, ex: issue
| UnsignedParser -- type/newtype wrapper around supported datatypes
| SignedParser -- type/newtype wrapper around numerical datatypes only
| HardcodedString String -- raw string, ex "B7014"
deriving (Show, Eq)
data Repacker = Repacker
{ repackerName :: String
, repackerConstructor :: String
, repackerFields :: [RepackerField]
} deriving (Show)
data RepackerField = RepackerField
{ repackerFieldName :: String
, repackerFieldUnparser :: Maybe Exp
} deriving (Show)