@@ -5,7 +5,7 @@
55module Data.THGen.XML.Internal where
66
77import Control.DeepSeq
8−import Control.Lens hiding (repeated, enum, (&), Strict)
8+import Control.Lens hiding (repeated, enum, (&))
99import Control.Lens.Internal.FieldTH (makeFieldOpticsForDec)
1010import qualified Data.Char as C
1111import Data.List.NonEmpty (NonEmpty)
@@ -15,7 +15,7 @@ import Data.THGen.Compat as THC
1515import Data.THGen.Enum
1616import qualified Data.Text as T
1717import GHC.Generics (Generic)
18−import Language.Haskell.TH as TH hiding (Strict)
18+import Language.Haskell.TH as TH
1919import Prelude hiding ((+), (*), (^))
2020import qualified Text.XML as X
2121import Text.XML.DOM.Parser hiding (parseContent)
@@ -23,22 +23,10 @@ import Text.XML.DOM.Parser.Internal.Content
2323import Text.XML.ParentAttributes
2424import qualified Text.XML.Writer as XW
2525
26−data ParserMode
27− = Strict
28− | Lenient
2926
30−data GenType
31− = Parser
32− | Generator
33− | ParserAndGenerator
34− | LenientParser
35− | LenientParserAndGenerator
27+data GenType = Parser | Generator | Both
3628
37−isLenientType :: GenType -> Bool
38−isLenientType = \case
39− LenientParser -> True
40− LenientParserAndGenerator -> True
41− _ -> False
29+data GenerateLens = Lens | NoLens
4230
4331data XmlFieldPlural
4432 = XmlFieldPluralMandatory -- Occurs exactly 1 time (Identity)
@@ -69,7 +57,7 @@ data IsoXmlDescRecordPart
6957 | IsoXmlDescRecordAttribute IsoXmlDescAttribute
7058 | IsoXmlDescRecordContent IsoXmlDescContent
7159
72−data IsoXmlDescRecord = IsoXmlDescRecord GenType [IsoXmlDescRecordPart]
60+data IsoXmlDescRecord = IsoXmlDescRecord GenType GenerateLens [IsoXmlDescRecordPart]
7361
7462makePrisms ''IsoXmlDescRecord
7563
@@ -90,26 +78,34 @@ appendField
9078 -> IsoXmlDescRecord
9179 -> IsoXmlDescPreField
9280 -> IsoXmlDescRecord
93−appendField plural (IsoXmlDescRecord genType fields) (IsoXmlDescPreField name ty) =
94− let xfield = IsoXmlDescRecordField $ IsoXmlDescField plural name ty
95− in IsoXmlDescRecord genType (xfield:fields)
81+appendField
82+ plural
83+ (IsoXmlDescRecord genType generateLens fields)
84+ (IsoXmlDescPreField name ty) =
85+ let xfield = IsoXmlDescRecordField $ IsoXmlDescField plural name ty
86+ in IsoXmlDescRecord genType generateLens (xfield:fields)
9687
9788appendAttribute
9889 :: XmlAttributePlural
9990 -> IsoXmlDescRecord
10091 -> IsoXmlDescPreAttribute
10192 -> IsoXmlDescRecord
102−appendAttribute plural (IsoXmlDescRecord genType fields) (IsoXmlDescPreAttribute name ty) =
103− let xattribute = IsoXmlDescRecordAttribute $ IsoXmlDescAttribute plural name ty
104− in IsoXmlDescRecord genType (xattribute:fields)
93+appendAttribute
94+ plural
95+ (IsoXmlDescRecord genType generateLens fields)
96+ (IsoXmlDescPreAttribute name ty) =
97+ let xattribute = IsoXmlDescRecordAttribute $ IsoXmlDescAttribute plural name ty
98+ in IsoXmlDescRecord genType generateLens (xattribute:fields)
10599
106100appendContent
107101 :: IsoXmlDescRecord
108102 -> IsoXmlDescPreContent
109103 -> IsoXmlDescRecord
110−appendContent (IsoXmlDescRecord genType fields) (IsoXmlDescPreContent name ty) =
111− let xcontent = IsoXmlDescRecordContent $ IsoXmlDescContent name ty
112− in IsoXmlDescRecord genType (xcontent:fields)
104+appendContent
105+ (IsoXmlDescRecord genType generateLens fields)
106+ (IsoXmlDescPreContent name ty) =
107+ let xcontent = IsoXmlDescRecordContent $ IsoXmlDescContent name ty
108+ in IsoXmlDescRecord genType generateLens (xcontent:fields)
113109
114110(!), (?), (*), (+) :: IsoXmlDescRecord -> IsoXmlDescPreField -> IsoXmlDescRecord
115111(!) = appendField XmlFieldPluralMandatory
@@ -147,11 +143,11 @@ class Description name desc | desc -> name where
147143infix 0 =:=
148144
149145instance Description PrefixName IsoXmlDescRecord where
150− prefixName =:= (IsoXmlDescRecord genType descRecordParts) =
151− isoXmlGenerateDatatype genType prefixName (reverse descRecordParts)
146+ prefixName =:= (IsoXmlDescRecord genType generateLens descRecordParts) =
147+ isoXmlGenerateDatatype genType generateLens prefixName (reverse descRecordParts)
152148
153−record :: GenType -> IsoXmlDescRecord
154−record gt = IsoXmlDescRecord gt []
149+record :: GenType -> GenerateLens -> IsoXmlDescRecord
150+record gt gl = IsoXmlDescRecord gt gl []
155151
156152enum :: GenType -> IsoXmlDescEnum
157153enum gt = IsoXmlDescEnum gt []
@@ -160,7 +156,7 @@ instance Description ExhaustivenessName IsoXmlDescEnum where
160156 exhaustivenessName =:= (IsoXmlDescEnum genType descEnumCons) =
161157 isoXmlGenerateEnum genType exhaustivenessName (reverse descEnumCons)
162158
163−instance (m ~ Q) => IsString (m TH.Type -> IsoXmlDescPreField) where
159+instance IsString (TH.TypeQ -> IsoXmlDescPreField) where
164160 fromString = IsoXmlDescPreField
165161
166162instance IsString IsoXmlDescPreField where
@@ -168,10 +164,10 @@ instance IsString IsoXmlDescPreField where
168164 where
169165 ty = (TH.conT . TH.mkName) ("Xml" ++ over _head C.toUpper (xmlLocalName name))
170166
171−instance (m ~ Q) => IsString (m TH.Type -> IsoXmlDescPreAttribute) where
167+instance IsString (TH.TypeQ -> IsoXmlDescPreAttribute) where
172168 fromString = IsoXmlDescPreAttribute
173169
174−instance (m ~ Q) => IsString (m Type -> IsoXmlDescPreContent) where
170+instance IsString (TH.TypeQ -> IsoXmlDescPreContent) where
175171 fromString = IsoXmlDescPreContent
176172
177173instance IsString IsoXmlDescPreAttribute where
@@ -197,7 +193,7 @@ instance IsString ExhaustivenessName where
197193 fromString strName = ExhaustivenessName strName NonExhaustive
198194
199195makeNamePrefix :: String -> String
200−makeNamePrefix = map C.toLower . filter (\c -> C.isUpper c || C.isDigit c)
196+makeNamePrefix = map C.toLower . filter C.isUpper
201197
202198funSimple :: TH.Name -> TH.ExpQ -> TH.DecQ
203199funSimple name body = TH.funD name [ TH.clause [] (TH.normalB body) [] ]
@@ -225,14 +221,11 @@ isoXmlGenerateEnum genType (ExhaustivenessName strName' exh) enumCons = do
225221 (return [])
226222 [t|ToXmlAttribute $(TH.conT name)|]
227223 [funSimple 'toXmlAttribute [e|T.pack . show|]]
228− genFromDomInst mode = do
224+ genFromDomInst = do
229225 TH.instanceD
230226 (return [])
231227 [t|FromDom $(TH.conT name)|]
232− [case mode of
233− Strict -> funSimple 'fromDom [e|parseContent readContent|]
234− Lenient -> funSimple 'fromDom [e|ignoreBlank $ parseContent readContent|]
235− ]
228+ [funSimple 'fromDom [e|parseContent readContent|]]
236229 genFromAttributeInst = do
237230 TH.instanceD
238231 (return [])
@@ -244,30 +237,28 @@ isoXmlGenerateEnum genType (ExhaustivenessName strName' exh) enumCons = do
244237 toXmlAttributeInst <- genToXmlAttributeInst
245238 return $ enumDecls ++ [toXmlInst, toXmlAttributeInst]
246239 Parser -> do
247− fromDomInst <- genFromDomInst Strict
248− fromAttributeInst <- genFromAttributeInst
249− return $ enumDecls ++ [fromDomInst, fromAttributeInst]
250− LenientParser -> do
251− fromDomInst <- genFromDomInst Lenient
240+ fromDomInst <- genFromDomInst
252241 fromAttributeInst <- genFromAttributeInst
253242 return $ enumDecls ++ [fromDomInst, fromAttributeInst]
254− ParserAndGenerator -> 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
243+ Both -> do
262244 toXmlInst <- genToXmlInst
263245 toXmlAttributeInst <- genToXmlAttributeInst
264− fromDomInst <- genFromDomInst Lenient
246+ fromDomInst <- genFromDomInst
265247 fromAttributeInst <- genFromAttributeInst
266248 return $ enumDecls ++ [toXmlInst, toXmlAttributeInst,
267249 fromDomInst, fromAttributeInst]
268250
269−isoXmlGenerateDatatype :: GenType -> PrefixName -> [IsoXmlDescRecordPart] -> TH.DecsQ
270−isoXmlGenerateDatatype genType (PrefixName strName' strPrefix') descRecordParts = do
251+isoXmlGenerateDatatype
252+ :: GenType
253+ -> GenerateLens
254+ -> PrefixName
255+ -> [IsoXmlDescRecordPart]
256+ -> TH.DecsQ
257+isoXmlGenerateDatatype
258+ genType
259+ generateLens
260+ (PrefixName strName' strPrefix')
261+ descRecordParts = do
271262 let
272263 isNewtype = length descRecordParts == 1
273264 strName = "Xml" ++ strName'
@@ -284,14 +275,11 @@ isoXmlGenerateDatatype genType (PrefixName strName' strPrefix') descRecordParts
284275 IsoXmlDescField fieldPlural rawName fieldType = descField
285276 fieldStrName = xmlLocalName rawName
286277 fName = TH.mkName (fieldName fieldStrName)
287− fType' = case fieldPlural of
278+ fType = case fieldPlural of
288279 XmlFieldPluralMandatory -> fieldType
289280 XmlFieldPluralOptional -> [t| Maybe $fieldType |]
290281 XmlFieldPluralRepeated -> [t| [$fieldType] |]
291282 XmlFieldPluralMultiplied -> [t| NonEmpty $fieldType |]
292− fType = if isLenientType genType
293− then [t| Maybe $fType' |]
294− else fType'
295283 in if isNewtype
296284 then THC.varStrictType fName (THC.nonStrictType fType)
297285 else THC.varStrictType fName (THC.strictType fType)
@@ -326,7 +314,7 @@ isoXmlGenerateDatatype genType (PrefixName strName' strPrefix') descRecordParts
326314 [ ]
327315
328316 let
329− genFromDomInst mode = do
317+ genFromDomInst = do
330318 let
331319 exprHeader = [e|pure $(TH.conE name)|]
332320 exprRecordParts = do
@@ -340,9 +328,8 @@ isoXmlGenerateDatatype genType (PrefixName strName' strPrefix') descRecordParts
340328 fieldParse = case fieldPlural of
341329 XmlFieldPluralMandatory -> [e|inElem|]
342330 _ -> [e|inElemTrav|]
343− in case mode of
344− Strict -> [e|$fieldParse $exprFieldStrName fromDom|]
345− Lenient -> [e|$fieldParse $exprFieldStrName (ignoreBlank fromDom)|]
331+ in
332+ [e|$fieldParse $exprFieldStrName fromDom|]
346333 IsoXmlDescRecordAttribute descAttribute ->
347334 let
348335 IsoXmlDescAttribute attributePlural attributeStrName _ = descAttribute
@@ -428,21 +415,12 @@ isoXmlGenerateDatatype genType (PrefixName strName' strPrefix') descRecordParts
428415 return $ [termDecl] ++ lensDecls ++
429416 [toXmlInst, toXmlParentAttributesInst, nfDataInst]
430417 Parser -> do
431− fromDomInst <- genFromDomInst Strict
432− return $ [termDecl] ++ lensDecls ++ [fromDomInst, nfDataInst]
433− LenientParser -> do
434− fromDomInst <- genFromDomInst Lenient
418+ fromDomInst <- genFromDomInst
435419 return $ [termDecl] ++ lensDecls ++ [fromDomInst, nfDataInst]
436− ParserAndGenerator -> do
437− toXmlInst <- genToXmlInst
438− toXmlParentAttributesInst <- genToXmlParentAttributeInst
439− fromDomInst <- genFromDomInst Strict
440− return $ [termDecl] ++ lensDecls ++
441− [fromDomInst, toXmlInst, toXmlParentAttributesInst, nfDataInst]
442− LenientParserAndGenerator -> do
420+ Both -> do
443421 toXmlInst <- genToXmlInst
444422 toXmlParentAttributesInst <- genToXmlParentAttributeInst
445− fromDomInst <- genFromDomInst Lenient
423+ fromDomInst <- genFromDomInst
446424 return $ [termDecl] ++ lensDecls ++
447425 [fromDomInst, toXmlInst, toXmlParentAttributesInst, nfDataInst]
448426