@@ -5,7 +5,7 @@
5module Data.THGen.XML.Internal where
5module Data.THGen.XML.Internal where
7import Control.DeepSeq
7import Control.DeepSeq
8−import Control.Lens hiding (repeated, enum, (&), Strict)
8+import Control.Lens hiding (repeated, enum, (&))
9import Control.Lens.Internal.FieldTH (makeFieldOpticsForDec)
9import Control.Lens.Internal.FieldTH (makeFieldOpticsForDec)
10import qualified Data.Char as C
10import qualified Data.Char as C
11import Data.List.NonEmpty (NonEmpty)
11import Data.List.NonEmpty (NonEmpty)
@@ -15,7 +15,7 @@ import Data.THGen.Compat as THC
15import Data.THGen.Enum
15import Data.THGen.Enum
16import qualified Data.Text as T
16import qualified Data.Text as T
17import GHC.Generics (Generic)
17import GHC.Generics (Generic)
18−import Language.Haskell.TH as TH hiding (Strict)
18+import Language.Haskell.TH as TH
19import Prelude hiding ((+), (*), (^))
19import Prelude hiding ((+), (*), (^))
20import qualified Text.XML as X
20import qualified Text.XML as X
21import Text.XML.DOM.Parser hiding (parseContent)
21import Text.XML.DOM.Parser hiding (parseContent)
@@ -23,22 +23,10 @@ import Text.XML.DOM.Parser.Internal.Content
23import Text.XML.ParentAttributes
23import Text.XML.ParentAttributes
24import qualified Text.XML.Writer as XW
24import qualified Text.XML.Writer as XW
30−data GenType
27+data GenType = Parser | Generator | Both
35− | LenientParserAndGenerator
37−isLenientType :: GenType -> Bool
29+data GenerateLens = Lens | NoLens
39− LenientParser -> True
40− LenientParserAndGenerator -> True
43data XmlFieldPlural
31data XmlFieldPlural
44 = XmlFieldPluralMandatory -- Occurs exactly 1 time (Identity)
32 = XmlFieldPluralMandatory -- Occurs exactly 1 time (Identity)
@@ -69,7 +57,7 @@ data IsoXmlDescRecordPart
69 | IsoXmlDescRecordAttribute IsoXmlDescAttribute
57 | IsoXmlDescRecordAttribute IsoXmlDescAttribute
70 | IsoXmlDescRecordContent IsoXmlDescContent
58 | IsoXmlDescRecordContent IsoXmlDescContent
72−data IsoXmlDescRecord = IsoXmlDescRecord GenType [IsoXmlDescRecordPart]
60+data IsoXmlDescRecord = IsoXmlDescRecord GenType GenerateLens [IsoXmlDescRecordPart]
74makePrisms ''IsoXmlDescRecord
62makePrisms ''IsoXmlDescRecord
@@ -90,26 +78,34 @@ appendField
90 -> IsoXmlDescRecord
78 -> IsoXmlDescRecord
91 -> IsoXmlDescPreField
79 -> IsoXmlDescPreField
92 -> IsoXmlDescRecord
80 -> IsoXmlDescRecord
93−appendField plural (IsoXmlDescRecord genType fields) (IsoXmlDescPreField name ty) =
83+ (IsoXmlDescRecord genType generateLens fields)
84+ (IsoXmlDescPreField name ty) =
94− let xfield = IsoXmlDescRecordField $ IsoXmlDescField plural name ty
85+ let xfield = IsoXmlDescRecordField $ IsoXmlDescField plural name ty
95− in IsoXmlDescRecord genType (xfield:fields)
86+ in IsoXmlDescRecord genType generateLens (xfield:fields)
97appendAttribute
88appendAttribute
98 :: XmlAttributePlural
89 :: XmlAttributePlural
99 -> IsoXmlDescRecord
90 -> IsoXmlDescRecord
100 -> IsoXmlDescPreAttribute
91 -> IsoXmlDescPreAttribute
101 -> IsoXmlDescRecord
92 -> IsoXmlDescRecord
95+ (IsoXmlDescRecord genType generateLens fields)
102−appendAttribute plural (IsoXmlDescRecord genType fields) (IsoXmlDescPreAttribute name ty) =
96+ (IsoXmlDescPreAttribute name ty) =
103− let xattribute = IsoXmlDescRecordAttribute $ IsoXmlDescAttribute plural name ty
97+ let xattribute = IsoXmlDescRecordAttribute $ IsoXmlDescAttribute plural name ty
104− in IsoXmlDescRecord genType (xattribute:fields)
98+ in IsoXmlDescRecord genType generateLens (xattribute:fields)
106appendContent
100appendContent
107 :: IsoXmlDescRecord
101 :: IsoXmlDescRecord
108 -> IsoXmlDescPreContent
102 -> IsoXmlDescPreContent
109 -> IsoXmlDescRecord
103 -> IsoXmlDescRecord
105+ (IsoXmlDescRecord genType generateLens fields)
110−appendContent (IsoXmlDescRecord genType fields) (IsoXmlDescPreContent name ty) =
106+ (IsoXmlDescPreContent name ty) =
111− let xcontent = IsoXmlDescRecordContent $ IsoXmlDescContent name ty
107+ let xcontent = IsoXmlDescRecordContent $ IsoXmlDescContent name ty
112− in IsoXmlDescRecord genType (xcontent:fields)
108+ in IsoXmlDescRecord genType generateLens (xcontent:fields)
114(!), (?), (*), (+) :: IsoXmlDescRecord -> IsoXmlDescPreField -> IsoXmlDescRecord
110(!), (?), (*), (+) :: IsoXmlDescRecord -> IsoXmlDescPreField -> IsoXmlDescRecord
115(!) = appendField XmlFieldPluralMandatory
111(!) = appendField XmlFieldPluralMandatory
@@ -147,11 +143,11 @@ class Description name desc | desc -> name where
147infix 0 =:=
143infix 0 =:=
149instance Description PrefixName IsoXmlDescRecord where
145instance Description PrefixName IsoXmlDescRecord where
150− prefixName =:= (IsoXmlDescRecord genType descRecordParts) =
146+ prefixName =:= (IsoXmlDescRecord genType generateLens descRecordParts) =
151− isoXmlGenerateDatatype genType prefixName (reverse descRecordParts)
147+ isoXmlGenerateDatatype genType generateLens prefixName (reverse descRecordParts)
153−record :: GenType -> IsoXmlDescRecord
149+record :: GenType -> GenerateLens -> IsoXmlDescRecord
154−record gt = IsoXmlDescRecord gt []
150+record gt gl = IsoXmlDescRecord gt gl []
156enum :: GenType -> IsoXmlDescEnum
152enum :: GenType -> IsoXmlDescEnum
157enum gt = IsoXmlDescEnum gt []
153enum gt = IsoXmlDescEnum gt []
@@ -160,7 +156,7 @@ instance Description ExhaustivenessName IsoXmlDescEnum where
160 exhaustivenessName =:= (IsoXmlDescEnum genType descEnumCons) =
156 exhaustivenessName =:= (IsoXmlDescEnum genType descEnumCons) =
161 isoXmlGenerateEnum genType exhaustivenessName (reverse descEnumCons)
157 isoXmlGenerateEnum genType exhaustivenessName (reverse descEnumCons)
163−instance (m ~ Q) => IsString (m TH.Type -> IsoXmlDescPreField) where
159+instance IsString (TH.TypeQ -> IsoXmlDescPreField) where
164 fromString = IsoXmlDescPreField
160 fromString = IsoXmlDescPreField
166instance IsString IsoXmlDescPreField where
162instance IsString IsoXmlDescPreField where
@@ -168,10 +164,10 @@ instance IsString IsoXmlDescPreField where
169 ty = (TH.conT . TH.mkName) ("Xml" ++ over _head C.toUpper (xmlLocalName name))
165 ty = (TH.conT . TH.mkName) ("Xml" ++ over _head C.toUpper (xmlLocalName name))
171−instance (m ~ Q) => IsString (m TH.Type -> IsoXmlDescPreAttribute) where
167+instance IsString (TH.TypeQ -> IsoXmlDescPreAttribute) where
172 fromString = IsoXmlDescPreAttribute
168 fromString = IsoXmlDescPreAttribute
174−instance (m ~ Q) => IsString (m Type -> IsoXmlDescPreContent) where
170+instance IsString (TH.TypeQ -> IsoXmlDescPreContent) where
175 fromString = IsoXmlDescPreContent
171 fromString = IsoXmlDescPreContent
177instance IsString IsoXmlDescPreAttribute where
173instance IsString IsoXmlDescPreAttribute where
@@ -197,7 +193,7 @@ instance IsString ExhaustivenessName where
197 fromString strName = ExhaustivenessName strName NonExhaustive
193 fromString strName = ExhaustivenessName strName NonExhaustive
199makeNamePrefix :: String -> String
195makeNamePrefix :: String -> String
200−makeNamePrefix = map C.toLower . filter (\c -> C.isUpper c || C.isDigit c)
196+makeNamePrefix = map C.toLower . filter C.isUpper
202funSimple :: TH.Name -> TH.ExpQ -> TH.DecQ
198funSimple :: TH.Name -> TH.ExpQ -> TH.DecQ
203funSimple name body = TH.funD name [ TH.clause [] (TH.normalB body) [] ]
199funSimple name body = TH.funD name [ TH.clause [] (TH.normalB body) [] ]
@@ -225,14 +221,11 @@ isoXmlGenerateEnum genType (ExhaustivenessName strName' exh) enumCons = do
225 (return [])
221 (return [])
226 [t|ToXmlAttribute $(TH.conT name)|]
222 [t|ToXmlAttribute $(TH.conT name)|]
227 [funSimple 'toXmlAttribute [e|T.pack . show|]]
223 [funSimple 'toXmlAttribute [e|T.pack . show|]]
228− genFromDomInst mode = do
224+ genFromDomInst = do
229 TH.instanceD
225 TH.instanceD
230 (return [])
226 (return [])
231 [t|FromDom $(TH.conT name)|]
227 [t|FromDom $(TH.conT name)|]
233− Strict -> funSimple 'fromDom [e|parseContent readContent|]
234− Lenient -> funSimple 'fromDom [e|ignoreBlank $ parseContent readContent|]
228+ [funSimple 'fromDom [e|parseContent readContent|]]
236 genFromAttributeInst = do
229 genFromAttributeInst = do
237 TH.instanceD
230 TH.instanceD
238 (return [])
231 (return [])
@@ -244,30 +237,28 @@ isoXmlGenerateEnum genType (ExhaustivenessName strName' exh) enumCons = do
244 toXmlAttributeInst <- genToXmlAttributeInst
237 toXmlAttributeInst <- genToXmlAttributeInst
245 return $ enumDecls ++ [toXmlInst, toXmlAttributeInst]
238 return $ enumDecls ++ [toXmlInst, toXmlAttributeInst]
246 Parser -> do
239 Parser -> do
247− fromDomInst <- genFromDomInst Strict
240+ fromDomInst <- genFromDomInst
248− fromAttributeInst <- genFromAttributeInst
249− return $ enumDecls ++ [fromDomInst, fromAttributeInst]
251− fromDomInst <- genFromDomInst Lenient
252 fromAttributeInst <- genFromAttributeInst
241 fromAttributeInst <- genFromAttributeInst
253 return $ enumDecls ++ [fromDomInst, fromAttributeInst]
242 return $ enumDecls ++ [fromDomInst, fromAttributeInst]
254− ParserAndGenerator -> do
243+ Both -> do
255− toXmlInst <- genToXmlInst
256− toXmlAttributeInst <- genToXmlAttributeInst
257− fromDomInst <- genFromDomInst Strict
258− fromAttributeInst <- genFromAttributeInst
259− return $ enumDecls ++ [toXmlInst, toXmlAttributeInst,
260− fromDomInst, fromAttributeInst]
261− LenientParserAndGenerator -> do
262 toXmlInst <- genToXmlInst
244 toXmlInst <- genToXmlInst
263 toXmlAttributeInst <- genToXmlAttributeInst
245 toXmlAttributeInst <- genToXmlAttributeInst
264− fromDomInst <- genFromDomInst Lenient
246+ fromDomInst <- genFromDomInst
265 fromAttributeInst <- genFromAttributeInst
247 fromAttributeInst <- genFromAttributeInst
266 return $ enumDecls ++ [toXmlInst, toXmlAttributeInst,
248 return $ enumDecls ++ [toXmlInst, toXmlAttributeInst,
267 fromDomInst, fromAttributeInst]
249 fromDomInst, fromAttributeInst]
269−isoXmlGenerateDatatype :: GenType -> PrefixName -> [IsoXmlDescRecordPart] -> TH.DecsQ
251+isoXmlGenerateDatatype
255+ -> [IsoXmlDescRecordPart]
257+isoXmlGenerateDatatype
270−isoXmlGenerateDatatype genType (PrefixName strName' strPrefix') descRecordParts = do
260+ (PrefixName strName' strPrefix')
261+ descRecordParts = do
272 isNewtype = length descRecordParts == 1
263 isNewtype = length descRecordParts == 1
273 strName = "Xml" ++ strName'
264 strName = "Xml" ++ strName'
@@ -284,14 +275,11 @@ isoXmlGenerateDatatype genType (PrefixName strName' strPrefix') descRecordParts
284 IsoXmlDescField fieldPlural rawName fieldType = descField
275 IsoXmlDescField fieldPlural rawName fieldType = descField
285 fieldStrName = xmlLocalName rawName
276 fieldStrName = xmlLocalName rawName
286 fName = TH.mkName (fieldName fieldStrName)
277 fName = TH.mkName (fieldName fieldStrName)
287− fType' = case fieldPlural of
278+ fType = case fieldPlural of
288 XmlFieldPluralMandatory -> fieldType
279 XmlFieldPluralMandatory -> fieldType
289 XmlFieldPluralOptional -> [t| Maybe $fieldType |]
280 XmlFieldPluralOptional -> [t| Maybe $fieldType |]
290 XmlFieldPluralRepeated -> [t| [$fieldType] |]
281 XmlFieldPluralRepeated -> [t| [$fieldType] |]
291 XmlFieldPluralMultiplied -> [t| NonEmpty $fieldType |]
282 XmlFieldPluralMultiplied -> [t| NonEmpty $fieldType |]
292− fType = if isLenientType genType
293− then [t| Maybe $fType' |]
295 in if isNewtype
283 in if isNewtype
296 then THC.varStrictType fName (THC.nonStrictType fType)
284 then THC.varStrictType fName (THC.nonStrictType fType)
297 else THC.varStrictType fName (THC.strictType fType)
285 else THC.varStrictType fName (THC.strictType fType)
@@ -326,7 +314,7 @@ isoXmlGenerateDatatype genType (PrefixName strName' strPrefix') descRecordParts
329− genFromDomInst mode = do
317+ genFromDomInst = do
331 exprHeader = [e|pure $(TH.conE name)|]
319 exprHeader = [e|pure $(TH.conE name)|]
332 exprRecordParts = do
320 exprRecordParts = do
@@ -340,9 +328,8 @@ isoXmlGenerateDatatype genType (PrefixName strName' strPrefix') descRecordParts
340 fieldParse = case fieldPlural of
328 fieldParse = case fieldPlural of
341 XmlFieldPluralMandatory -> [e|inElem|]
329 XmlFieldPluralMandatory -> [e|inElem|]
342 _ -> [e|inElemTrav|]
330 _ -> [e|inElemTrav|]
343− in case mode of
331+ in
344− Strict -> [e|$fieldParse $exprFieldStrName fromDom|]
345− Lenient -> [e|$fieldParse $exprFieldStrName (ignoreBlank fromDom)|]
332+ [e|$fieldParse $exprFieldStrName fromDom|]
346 IsoXmlDescRecordAttribute descAttribute ->
333 IsoXmlDescRecordAttribute descAttribute ->
348 IsoXmlDescAttribute attributePlural attributeStrName _ = descAttribute
335 IsoXmlDescAttribute attributePlural attributeStrName _ = descAttribute
@@ -428,21 +415,12 @@ isoXmlGenerateDatatype genType (PrefixName strName' strPrefix') descRecordParts
428 return $ [termDecl] ++ lensDecls ++
415 return $ [termDecl] ++ lensDecls ++
429 [toXmlInst, toXmlParentAttributesInst, nfDataInst]
416 [toXmlInst, toXmlParentAttributesInst, nfDataInst]
430 Parser -> do
417 Parser -> do
431− fromDomInst <- genFromDomInst Strict
418+ fromDomInst <- genFromDomInst
432− return $ [termDecl] ++ lensDecls ++ [fromDomInst, nfDataInst]
434− fromDomInst <- genFromDomInst Lenient
435 return $ [termDecl] ++ lensDecls ++ [fromDomInst, nfDataInst]
419 return $ [termDecl] ++ lensDecls ++ [fromDomInst, nfDataInst]
436− ParserAndGenerator -> do
420+ Both -> do
437− toXmlInst <- genToXmlInst
438− toXmlParentAttributesInst <- genToXmlParentAttributeInst
439− fromDomInst <- genFromDomInst Strict
440− return $ [termDecl] ++ lensDecls ++
441− [fromDomInst, toXmlInst, toXmlParentAttributesInst, nfDataInst]
442− LenientParserAndGenerator -> do
443 toXmlInst <- genToXmlInst
421 toXmlInst <- genToXmlInst
444 toXmlParentAttributesInst <- genToXmlParentAttributeInst
422 toXmlParentAttributesInst <- genToXmlParentAttributeInst
445− fromDomInst <- genFromDomInst Lenient
423+ fromDomInst <- genFromDomInst
446 return $ [termDecl] ++ lensDecls ++
424 return $ [termDecl] ++ lensDecls ++
447 [fromDomInst, toXmlInst, toXmlParentAttributesInst, nfDataInst]
425 [fromDomInst, toXmlInst, toXmlParentAttributesInst, nfDataInst]