module Text.XML.HaXml.DtdToHaskell.Convert
( dtd2TypeDef
) where
import Data.List (intercalate,nub)
import Text.XML.HaXml.Types hiding (Name)
import Text.XML.HaXml.DtdToHaskell.TypeDef
data Record = R [AttDef] ContentSpec
dtd2TypeDef :: [MarkupDecl] -> [TypeDef]
dtd2TypeDef :: [MarkupDecl] -> [TypeDef]
dtd2TypeDef =
((QName, Record) -> [TypeDef]) -> [(QName, Record)] -> [TypeDef]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (QName, Record) -> [TypeDef]
convert ([(QName, Record)] -> [TypeDef])
-> ([MarkupDecl] -> [(QName, Record)]) -> [MarkupDecl] -> [TypeDef]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(QName, Record)] -> [(QName, Record)]
forall a. [a] -> [a]
reverse ([(QName, Record)] -> [(QName, Record)])
-> ([MarkupDecl] -> [(QName, Record)])
-> [MarkupDecl]
-> [(QName, Record)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(QName, Record)] -> [MarkupDecl] -> [(QName, Record)]
database []
where
database :: [(QName, Record)] -> [MarkupDecl] -> [(QName, Record)]
database [(QName, Record)]
db [] = [(QName, Record)]
db
database [(QName, Record)]
db (MarkupDecl
m:[MarkupDecl]
ms) =
case MarkupDecl
m of
(Element (ElementDecl QName
n ContentSpec
cs)) ->
case QName -> [(QName, Record)] -> Maybe Record
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup QName
n [(QName, Record)]
db of
Maybe Record
Nothing -> [(QName, Record)] -> [MarkupDecl] -> [(QName, Record)]
database ((QName
n, [AttDef] -> ContentSpec -> Record
R [] ContentSpec
cs)(QName, Record) -> [(QName, Record)] -> [(QName, Record)]
forall a. a -> [a] -> [a]
:[(QName, Record)]
db) [MarkupDecl]
ms
(Just (R [AttDef]
as ContentSpec
_)) -> [(QName, Record)] -> [MarkupDecl] -> [(QName, Record)]
database (QName -> Record -> [(QName, Record)] -> [(QName, Record)]
forall t t. Eq t => t -> t -> [(t, t)] -> [(t, t)]
replace QName
n ([AttDef] -> ContentSpec -> Record
R [AttDef]
as ContentSpec
cs) [(QName, Record)]
db) [MarkupDecl]
ms
(AttList (AttListDecl QName
n [AttDef]
as)) ->
case QName -> [(QName, Record)] -> Maybe Record
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup QName
n [(QName, Record)]
db of
Maybe Record
Nothing -> [(QName, Record)] -> [MarkupDecl] -> [(QName, Record)]
database ((QName
n, [AttDef] -> ContentSpec -> Record
R [AttDef]
as ContentSpec
EMPTY)(QName, Record) -> [(QName, Record)] -> [(QName, Record)]
forall a. a -> [a] -> [a]
:[(QName, Record)]
db) [MarkupDecl]
ms
(Just (R [AttDef]
a ContentSpec
cs)) -> [(QName, Record)] -> [MarkupDecl] -> [(QName, Record)]
database (QName -> Record -> [(QName, Record)] -> [(QName, Record)]
forall t t. Eq t => t -> t -> [(t, t)] -> [(t, t)]
replace QName
n ([AttDef] -> ContentSpec -> Record
R ([AttDef] -> [AttDef]
forall a. Eq a => [a] -> [a]
nub ([AttDef]
a[AttDef] -> [AttDef] -> [AttDef]
forall a. [a] -> [a] -> [a]
++[AttDef]
as)) ContentSpec
cs) [(QName, Record)]
db) [MarkupDecl]
ms
MarkupDecl
_ -> [(QName, Record)] -> [MarkupDecl] -> [(QName, Record)]
database [(QName, Record)]
db [MarkupDecl]
ms
replace :: t -> t -> [(t, t)] -> [(t, t)]
replace t
_ t
_ [] = [Char] -> [(t, t)]
forall a. HasCallStack => [Char] -> a
error [Char]
"dtd2TypeDef.replace: no element to replace"
replace t
n t
v (x :: (t, t)
x@(t
n0,t
_):[(t, t)]
db)
| t
nt -> t -> Bool
forall a. Eq a => a -> a -> Bool
==t
n0 = (t
n,t
v)(t, t) -> [(t, t)] -> [(t, t)]
forall a. a -> [a] -> [a]
: [(t, t)]
db
| Bool
otherwise = (t, t)
x(t, t) -> [(t, t)] -> [(t, t)]
forall a. a -> [a] -> [a]
: t -> t -> [(t, t)] -> [(t, t)]
replace t
n t
v [(t, t)]
db
convert :: (QName, Record) -> [TypeDef]
convert :: (QName, Record) -> [TypeDef]
convert (N [Char]
n, R [AttDef]
as ContentSpec
cs) =
case ContentSpec
cs of
ContentSpec
EMPTY -> Modifier -> [[StructType]] -> [TypeDef]
modifier Modifier
None []
ContentSpec
ANY -> Modifier -> [[StructType]] -> [TypeDef]
modifier Modifier
None [[StructType
Any]]
(Mixed Mixed
PCDATA) -> Modifier -> [[StructType]] -> [TypeDef]
modifier Modifier
None [[StructType
String]]
(Mixed (PCDATAplus [QName]
ns)) -> Modifier -> [[StructType]] -> [TypeDef]
modifier Modifier
Star ([StructType
StringMixed]
[StructType] -> [[StructType]] -> [[StructType]]
forall a. a -> [a] -> [a]
: (QName -> [StructType]) -> [QName] -> [[StructType]]
forall a b. (a -> b) -> [a] -> [b]
map ((StructType -> [StructType] -> [StructType]
forall a. a -> [a] -> [a]
:[]) (StructType -> [StructType])
-> (QName -> StructType) -> QName -> [StructType]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> StructType
Defined (Name -> StructType) -> (QName -> Name) -> QName -> StructType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Name
name
([Char] -> Name) -> (QName -> [Char]) -> QName -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \(N [Char]
n)->[Char]
n)
[QName]
ns)
(ContentSpec CP
cp) ->
case CP
cp of
(TagName (N [Char]
n') Modifier
m) -> Modifier -> [[StructType]] -> [TypeDef]
modifier Modifier
m [[Name -> StructType
Defined ([Char] -> Name
name [Char]
n')]]
(Choice [CP]
cps Modifier
m) -> Modifier -> [[StructType]] -> [TypeDef]
modifier Modifier
m ((CP -> [StructType]) -> [CP] -> [[StructType]]
forall a b. (a -> b) -> [a] -> [b]
map ((StructType -> [StructType] -> [StructType]
forall a. a -> [a] -> [a]
:[])(StructType -> [StructType])
-> (CP -> StructType) -> CP -> [StructType]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.CP -> StructType
inner) [CP]
cps)
(Seq [CP]
cps Modifier
m) -> Modifier -> [[StructType]] -> [TypeDef]
modifier Modifier
m [(CP -> StructType) -> [CP] -> [StructType]
forall a b. (a -> b) -> [a] -> [b]
map CP -> StructType
inner [CP]
cps]
[TypeDef] -> [TypeDef] -> [TypeDef]
forall a. [a] -> [a] -> [a]
++ (AttDef -> [TypeDef]) -> [AttDef] -> [TypeDef]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (QName -> AttDef -> [TypeDef]
mkAttrDef ([Char] -> QName
N [Char]
n)) [AttDef]
as
where
attrs :: AttrFields
attrs :: AttrFields
attrs = (AttDef -> (Name, StructType)) -> [AttDef] -> AttrFields
forall a b. (a -> b) -> [a] -> [b]
map (QName -> AttDef -> (Name, StructType)
mkAttrField ([Char] -> QName
N [Char]
n)) [AttDef]
as
modifier :: Modifier -> [[StructType]] -> [TypeDef]
modifier Modifier
None [[StructType]]
sts = [[StructType]] -> AttrFields -> Bool -> Name -> [TypeDef]
mkData [[StructType]]
sts AttrFields
attrs Bool
False ([Char] -> Name
name [Char]
n)
modifier Modifier
m [[StructType
st]] = [[StructType]] -> AttrFields -> Bool -> Name -> [TypeDef]
mkData [[Modifier -> StructType -> StructType
modf Modifier
m StructType
st]] AttrFields
attrs Bool
False ([Char] -> Name
name [Char]
n)
modifier Modifier
m [[StructType]]
sts = [[StructType]] -> AttrFields -> Bool -> Name -> [TypeDef]
mkData [[Modifier -> StructType -> StructType
modf Modifier
m (Name -> StructType
Defined ([Char] -> Name
name_ [Char]
n))]]
AttrFields
attrs Bool
False ([Char] -> Name
name [Char]
n) [TypeDef] -> [TypeDef] -> [TypeDef]
forall a. [a] -> [a] -> [a]
++
[[StructType]] -> AttrFields -> Bool -> Name -> [TypeDef]
mkData [[StructType]]
sts [] Bool
True ([Char] -> Name
name_ [Char]
n)
inner :: CP -> StructType
inner :: CP -> StructType
inner (TagName (N [Char]
n') Modifier
m) = Modifier -> StructType -> StructType
modf Modifier
m (Name -> StructType
Defined ([Char] -> Name
name [Char]
n'))
inner (Choice [CP]
cps Modifier
m) = Modifier -> StructType -> StructType
modf Modifier
m ([StructType] -> StructType
OneOf ((CP -> StructType) -> [CP] -> [StructType]
forall a b. (a -> b) -> [a] -> [b]
map CP -> StructType
inner [CP]
cps))
inner (Seq [CP]
cps Modifier
None) = [StructType] -> StructType
Tuple ((CP -> StructType) -> [CP] -> [StructType]
forall a b. (a -> b) -> [a] -> [b]
map CP -> StructType
inner [CP]
cps)
inner (Seq [CP]
cps Modifier
m) = Modifier -> StructType -> StructType
modf Modifier
m ([StructType] -> StructType
Tuple ((CP -> StructType) -> [CP] -> [StructType]
forall a b. (a -> b) -> [a] -> [b]
map CP -> StructType
inner [CP]
cps))
modf :: Modifier -> StructType -> StructType
modf Modifier
None StructType
x = StructType
x
modf Modifier
Query StructType
x = StructType -> StructType
Maybe StructType
x
modf Modifier
Star StructType
x = StructType -> StructType
List StructType
x
modf Modifier
Plus StructType
x = StructType -> StructType
List1 StructType
x
mkData :: [[StructType]] -> AttrFields -> Bool -> Name -> [TypeDef]
mkData :: [[StructType]] -> AttrFields -> Bool -> Name -> [TypeDef]
mkData [] AttrFields
fs Bool
aux Name
n = [Bool -> Name -> AttrFields -> Constructors -> TypeDef
DataDef Bool
aux Name
n AttrFields
fs []]
mkData [[StructType]
ts] AttrFields
fs Bool
aux Name
n = [Bool -> Name -> AttrFields -> Constructors -> TypeDef
DataDef Bool
aux Name
n AttrFields
fs [(Name
n, [StructType]
ts)]]
mkData [[StructType]]
tss AttrFields
fs Bool
aux Name
n = [Bool -> Name -> AttrFields -> Constructors -> TypeDef
DataDef Bool
aux Name
n AttrFields
fs (([StructType] -> (Name, [StructType]))
-> [[StructType]] -> Constructors
forall a b. (a -> b) -> [a] -> [b]
map (Name -> [StructType] -> (Name, [StructType])
mkConstr Name
n) [[StructType]]
tss)]
where
mkConstr :: Name -> [StructType] -> (Name, [StructType])
mkConstr Name
m [StructType]
ts = (Name -> [StructType] -> Name
mkConsName Name
m [StructType]
ts, [StructType]
ts)
mkConsName :: Name -> [StructType] -> Name
mkConsName (Name [Char]
x [Char]
m) [StructType]
sts = [Char] -> [Char] -> Name
Name [Char]
x ([Char]
m[Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++[Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"_" ((StructType -> [Char]) -> [StructType] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map StructType -> [Char]
flatten [StructType]
sts))
flatten :: StructType -> [Char]
flatten (Maybe StructType
st) = StructType -> [Char]
flatten StructType
st
flatten (List StructType
st) = StructType -> [Char]
flatten StructType
st
flatten (List1 StructType
st) = StructType -> [Char]
flatten StructType
st
flatten (Tuple [StructType]
sts) =
[Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"_" ((StructType -> [Char]) -> [StructType] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map StructType -> [Char]
flatten [StructType]
sts)
flatten StructType
StringMixed = [Char]
"Str"
flatten StructType
String = [Char]
"Str"
flatten (OneOf [StructType]
sts) =
[Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"_" ((StructType -> [Char]) -> [StructType] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map StructType -> [Char]
flatten [StructType]
sts)
flatten StructType
Any = [Char]
"Any"
flatten (Defined (Name [Char]
_ [Char]
m)) = [Char]
m
mkAttrDef :: QName -> AttDef -> [TypeDef]
mkAttrDef :: QName -> AttDef -> [TypeDef]
mkAttrDef QName
_ (AttDef QName
_ AttType
StringType DefaultDecl
_) =
[]
mkAttrDef QName
_ (AttDef QName
_ (TokenizedType TokenizedType
_) DefaultDecl
_) =
[]
mkAttrDef (N [Char]
e) (AttDef (N [Char]
n) (EnumeratedType (NotationType [[Char]]
nt)) DefaultDecl
_) =
[Name -> [Name] -> TypeDef
EnumDef ([Char] -> [Char] -> Name
name_a [Char]
e [Char]
n) (([Char] -> Name) -> [[Char]] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map ([Char] -> [Char] -> [Char] -> Name
name_ac [Char]
e [Char]
n) [[Char]]
nt)]
mkAttrDef (N [Char]
e) (AttDef (N [Char]
n) (EnumeratedType (Enumeration [[Char]]
es)) DefaultDecl
_) =
[Name -> [Name] -> TypeDef
EnumDef ([Char] -> [Char] -> Name
name_a [Char]
e [Char]
n) (([Char] -> Name) -> [[Char]] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map ([Char] -> [Char] -> [Char] -> Name
name_ac [Char]
e [Char]
n) [[Char]]
es)]
mkAttrField :: QName -> AttDef -> (Name,StructType)
mkAttrField :: QName -> AttDef -> (Name, StructType)
mkAttrField (N [Char]
e) (AttDef (N [Char]
n) AttType
typ DefaultDecl
req) = ([Char] -> [Char] -> Name
name_f [Char]
e [Char]
n, AttType -> DefaultDecl -> StructType
mkType AttType
typ DefaultDecl
req)
where
mkType :: AttType -> DefaultDecl -> StructType
mkType AttType
StringType DefaultDecl
REQUIRED = StructType
String
mkType AttType
StringType DefaultDecl
IMPLIED = StructType -> StructType
Maybe StructType
String
mkType AttType
StringType (DefaultTo v :: AttValue
v@(AttValue [Either [Char] Reference]
_) Maybe FIXED
_) = StructType -> [Char] -> StructType
Defaultable StructType
String (AttValue -> [Char]
forall a. Show a => a -> [Char]
show AttValue
v)
mkType (TokenizedType TokenizedType
_) DefaultDecl
REQUIRED = StructType
String
mkType (TokenizedType TokenizedType
_) DefaultDecl
IMPLIED = StructType -> StructType
Maybe StructType
String
mkType (TokenizedType TokenizedType
_) (DefaultTo v :: AttValue
v@(AttValue [Either [Char] Reference]
_) Maybe FIXED
_) =
StructType -> [Char] -> StructType
Defaultable StructType
String (AttValue -> [Char]
forall a. Show a => a -> [Char]
show AttValue
v)
mkType (EnumeratedType EnumeratedType
_) DefaultDecl
REQUIRED = Name -> StructType
Defined ([Char] -> [Char] -> Name
name_a [Char]
e [Char]
n)
mkType (EnumeratedType EnumeratedType
_) DefaultDecl
IMPLIED = StructType -> StructType
Maybe (Name -> StructType
Defined ([Char] -> [Char] -> Name
name_a [Char]
e [Char]
n))
mkType (EnumeratedType EnumeratedType
_) (DefaultTo v :: AttValue
v@(AttValue [Either [Char] Reference]
_) Maybe FIXED
_) =
StructType -> [Char] -> StructType
Defaultable (Name -> StructType
Defined ([Char] -> [Char] -> Name
name_a [Char]
e [Char]
n)) (Name -> [Char]
hName ([Char] -> [Char] -> [Char] -> Name
name_ac [Char]
e [Char]
n (AttValue -> [Char]
forall a. Show a => a -> [Char]
show AttValue
v)))