Skip to content

Commit 2ea6d2d

Browse files
author
Erik Boasson
committed
Extend topicidl quasi-quoter
1. Handle # <lineno> ... lines output by CPP, so that one can do {-# LANGUAGE CPP #-} [topicidl| #include "topics.idl" |] 2. Interpret lines of the form #pragma prefix T P to set the fieldname prefix of struct T to P, so that it can be set differently for each struct.
1 parent c4ad828 commit 2ea6d2d

File tree

3 files changed

+45
-10
lines changed

3 files changed

+45
-10
lines changed

src/DDS/IDL.hs

+27-8
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
module DDS.IDL where
22

33
import DDS.TopicXML
4-
import Control.Monad (void)
4+
import Control.Monad (void, liftM)
55
import Data.List (intercalate, intersperse)
66
import Data.Char (isSpace)
7+
import Data.Maybe
78
import Debug.Trace
89
import Text.Megaparsec
910
import Text.Megaparsec.String
@@ -16,19 +17,21 @@ parseIDL idl = case parse specification "(anonymous)" idl of
1617

1718
manySemi = flip endBy semi
1819

19-
specification = sc *> many definition_or_keylist <* eof
20+
specification = sc *> definitions <* eof
2021

21-
definition_or_keylist = keylist <|> definition
22+
definitions = liftM catMaybes $ many definition_or_keylist
23+
24+
definition_or_keylist = hashline <|> definition
2225

2326
definition = do
2427
d <- def_module <|> def_enum <|> def_type <|> def_struct <|> def_union <|> def_const <?> "definition"
2528
semi
26-
return d
29+
return $ Just d
2730

2831
def_module = do
2932
reserved "module"
3033
name <- identifier
31-
defs <- braces $ many definition_or_keylist
34+
defs <- braces $ definitions
3235
return $ DM name defs
3336

3437
def_enum = do
@@ -141,15 +144,31 @@ basetype =
141144
(sname >>= return . TR) <?>
142145
"type"
143146

147+
hashline = symbol "#" >> (pragma <|> linenumber)
148+
149+
pragma = symbol "pragma" >> (keylist <|> prefix)
150+
144151
keylist = do
145-
symbol "#"
146-
symbol "pragma"
147152
symbol "keylist"
148153
name <- snameE
149154
keys <- many fieldE
150155
void eol <|> eof
151156
sc
152-
return $ DK name keys
157+
return $ Just (DK name keys)
158+
159+
prefix = do
160+
symbol "prefix"
161+
name <- snameE
162+
prefix <- identifierE
163+
void eol <|> eof
164+
sc
165+
return $ Just (DP name prefix)
166+
167+
linenumber = do
168+
integer
169+
L.skipLineComment ""
170+
sc
171+
return Nothing
153172

154173
fieldE =
155174
sepBy1 identifierE dotE >>= return . intercalate "."

src/DDS/TH.hs

+12-1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,15 @@ genStruct deriv pfx sc (DS tn ms) = mkStructDataD deriv tn' cs
156156
cs = map (makeConstructor pfx sc) ms
157157
tn' = mkName $ cooknameU tn
158158

159+
overridePrefix :: String -> Scope -> String -> String
160+
overridePrefix pfx sc nm
161+
| (isNothing . scParent) sc = pfx
162+
| isJust mpfx' = pfx'
163+
| otherwise = pfx
164+
where
165+
(_, mpfx') = lookupDef (nm ++ "'Prefix") sc
166+
Just (DP _ pfx') = mpfx'
167+
159168
genUnion :: [TH.Name] -> String -> Scope -> Def -> [Dec]
160169
genUnion deriv pfx sc (DU tn dt cs) = mkUnionDataD deriv tn' ccs
161170
where
@@ -172,7 +181,9 @@ genEnum deriv pfx sc (DE tn es) =
172181
tn' = mkName $ cooknameU tn
173182

174183
genDef :: [TH.Name] -> String -> Scope -> Def -> [Dec]
175-
genDef deriv pfx sc def@(DS tn _) = genStruct deriv pfx sc def ++ genSerdes pfx tn
184+
genDef deriv pfx sc def@(DS tn _) = genStruct deriv pfx' sc def ++ genSerdes pfx' tn
185+
where
186+
pfx' = overridePrefix pfx sc tn
176187
genDef deriv pfx sc def@(DE tn _) = genEnum deriv "" sc def ++ genSerdes "" tn
177188
genDef deriv pfx sc def@(DU tn _ _) = genUnion deriv pfx sc def ++ genSerdes pfx tn
178189

src/DDS/TopicXML.hs

+6-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ topicsFromMetaData md = concatMap (fDef "" sc) ds
3838
fDef pr sc (DE n es) = []
3939
fDef pr sc (DK n ks) = [makeTopicMD pr sc n ks]
4040
fDef pr sc (DC n v) = []
41+
fDef pr sc (DP n pfx) = []
4142
fT :: String -> Scope -> T -> [TopicMD]
4243
fT pr sc (TDef d) = fDef pr sc d
4344
fT pr sc (TSeq b t) = fT pr sc t
@@ -179,7 +180,7 @@ xpMetaData = xpWrap (MD, \(MD ds) -> ds) $
179180
xpElem "MetaData" $ xpAddFixedAttr "version" "1.0.0" $ xpickle
180181

181182
type Name = String
182-
data Def = DT Name T | DM Name [Def] | DS Name [M] | DU Name T [UC] | DE Name [E] | DC Name Int | DK Name [Name] deriving (Show, Eq)
183+
data Def = DT Name T | DM Name [Def] | DS Name [M] | DU Name T [UC] | DE Name [E] | DC Name Int | DK Name [Name] | DP Name Name deriving (Show, Eq)
183184
instance XmlPickler Def where
184185
xpickle = xpAlt tag ps
185186
where
@@ -190,6 +191,7 @@ instance XmlPickler Def where
190191
tag (DE _ _) = 4
191192
tag (DC _ _) = 5 -- Const isn't part of OSPL meta data, temp for getting enum const in Scope
192193
tag (DK _ _) = 6 -- Keylist isn't part, but should've been :) (certainly makes parsing IDL easier)
194+
tag (DP _ _) = 7 -- Field prefix (Haskell specific)
193195
ps = [ xpWrap (uncurry DT, \(DT nm t) -> (nm, t)) $
194196
(xpElem "TypeDef" $ xpPair (xpAttr "name" xpText) xpickle)
195197
, xpWrap (uncurry DM, \(DM nm ds) -> (nm, ds)) $
@@ -204,6 +206,8 @@ instance XmlPickler Def where
204206
(xpElem "Const" $ xpPair (xpAttr "name" xpText) $ xpickle)
205207
, xpWrap (\(nm, ks) -> DK nm (splitOn "," ks), \(DK nm ks) -> (nm, intercalate "," ks)) $
206208
(xpElem "KeyList" $ xpPair (xpAttr "name" xpText) (xpAttr "keys" xpText))
209+
, xpWrap (\(nm, pfx) -> DP nm pfx, \(DP nm pfx) -> (nm, pfx)) $
210+
(xpElem "FieldPrefix" $ xpPair (xpAttr "name" xpText) (xpAttr "prefix" xpText))
207211
]
208212

209213
data E = E Name Int deriving (Show, Eq)
@@ -307,6 +311,7 @@ cDef ps t@(DE nm es) = res
307311
cDef ps t@(DT nm _) = Scope ps [] [(nm, t)]
308312
cDef ps t@(DC nm _) = Scope ps [] [(nm, t)]
309313
cDef ps (DK _ _) = Scope ps [] []
314+
cDef ps t@(DP nm pfx) = Scope ps [] [(nm ++ "'Prefix", t)] -- a bit of a hack to use a 'Prefix suffix
310315

311316
cT :: Maybe Scope -> T -> Scope
312317
cT ps (TDef d) = cDef ps d

0 commit comments

Comments
 (0)