1 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
2 {-# LANGUAGE StandaloneDeriving #-}
3 {-# LANGUAGE TypeFamilies #-}
4 {-# LANGUAGE OverloadedStrings #-}
5 {-# LANGUAGE ViewPatterns #-}
6 module Language.RNC.Write where
8 import Control.Applicative (Applicative(..))
10 import Data.Functor.Compose (Compose(..))
11 import Data.Semigroup hiding (option)
12 import Data.Text (Text)
13 import Prelude hiding (any)
14 import qualified Data.Text as Text
16 import Language.RNC.Sym
17 import Language.RNC.Fixity
21 = Writer { unWriter :: RuleMode -> (Infix, Side) -> Pair -> Text }
23 instance Show (Writer a) where
24 show = Text.unpack . runWriter
25 instance Functor Writer where
26 fmap _f (Writer x) = Writer x
27 instance Applicative Writer where
28 pure _ = writeText $ "\"\""
29 Writer f <*> Writer x = Writer $ \rm po pp ->
31 f rm (op, SideL) pp <> ", " <> x rm (op, SideR) pp
32 where op = infixB SideL 10
33 instance Sym_Rule Writer where
34 rule n (Writer w) = Writer $ \rm po pp ->
36 RuleMode_Body -> w RuleMode_Ref po pp
38 type instance Perm Writer = Compose [] Writer
39 instance Sym_Interleaved Writer where
40 interleaved (Compose []) = writeText "empty"
41 interleaved (Compose [Writer w]) = Writer w
42 interleaved (Compose l@(_:_)) = Writer $ \rm po pp ->
44 Text.intercalate " & " $
45 (unWriter <$> l) <*> pure rm <*> pure (op, SideL) <*> pure PairParen
46 where op = infixB SideL 2
47 _f <$$> Writer w = Compose [Writer w]
48 _f <$?> (_,Writer w) = Compose [Writer $ unWriter $ optional $ Writer w]
49 _f <$*> Writer w = Compose [Writer $ unWriter $ many (Writer w)]
50 Compose ws <||> Writer w = Compose (Writer . unWriter <$> ws <> [Writer w])
51 Compose ws <|?> (_,Writer w) =
52 Compose ((Writer . unWriter <$> ws) <>
53 [Writer $ unWriter $ optional $ Writer w])
54 Compose ws <|*> (Writer w) =
55 Compose (Writer . unWriter <$> ws <>
56 [Writer $ unWriter $ many $ Writer w])
57 instance Sym_RNC Writer where
58 position (Writer w) = Writer w
59 element n (Writer w) = Writer $ \rm po pp ->
61 "element \""<>Text.pack (show n)<>"\" "<>w rm (op,SideR) PairBrace
63 anyElem (($ "") -> Writer w) = Writer $ \rm po pp ->
65 "any "<>w rm (op,SideR) PairBrace
67 attribute n (Writer w) = Writer $ \rm po pp ->
69 "attribute \""<>Text.pack (show n)<>"\" "<>w rm (op,SideR) PairBrace
72 comment = writeText "comment"
73 text = writeText "text"
74 none = writeText "empty"
76 int = writeText "xsd:int"
77 nat = writeText "xsd:nat"
78 nat1 = writeText "xsd:nat1"
79 -- anyElem r = Writer $ \_rm _po -> "empty"
81 Writer wl <|> Writer wr = Writer $ \rm po pp ->
83 wl rm (op, SideL) PairParen <> " | " <> wr rm (op, SideR) PairParen
84 where op = infixB SideL 2
85 choice [] = writeText "empty"
87 choice l@(_:_) = Writer $ \rm po pp ->
89 Text.intercalate " | " $
90 (unWriter <$> l) <*> pure rm <*> pure (op, SideL) <*> pure PairParen
91 where op = infixB SideL 2
92 many (Writer w) = Writer $ \rm po pp ->
94 w rm (op, SideL) PairParen <> "*"
96 some (Writer w) = Writer $ \rm po pp ->
98 w rm (op, SideL) PairParen <> "+"
100 option _x (Writer w) = Writer $ \rm po pp ->
102 w rm (op, SideL) PairParen <> "?"
104 optional (Writer w) = Writer $ \rm po pp ->
106 w rm (op, SideL) PairParen <> "?"
109 -- | Get textual rendition of given 'Writer'.
110 runWriter :: Writer a -> Text
111 runWriter (Writer w) = w RuleMode_Body (infixN0, SideL) PairParen
113 -- | Get textual rendition of given 'RuleWriter'.
114 renderWriter :: RuleWriter a -> Text
115 renderWriter = runWriter . unRuleWriter
117 -- | 'Writer' returns a constant rendition.
118 writeText :: Text -> Writer a
119 writeText t = Writer $ \_rm _op _pp -> t
121 -- ** Type 'RuleMode'
123 = RuleMode_Body -- ^ Request to generate the body of the rule.
124 | RuleMode_Ref -- ^ Request to generate a reference to the rule.
127 -- * Type 'RuleWriter'
128 newtype RuleWriter a = RuleWriter { unRuleWriter :: Writer a }
129 deriving (Functor, Applicative)
130 instance Sym_Rule RuleWriter where
131 rule n = ruleWriter (writeText n)
132 deriving instance Sym_RuleWriter RuleWriter
133 type instance Perm RuleWriter = Compose [] RuleWriter
134 instance Sym_Interleaved RuleWriter where
135 interleaved (Compose l) = RuleWriter $ interleaved $ Compose $ unRuleWriter <$> l
136 f <$$> RuleWriter w = Compose $ (RuleWriter <$>) $ getCompose $ f <$$> w
137 f <$?> (a,RuleWriter w) = Compose $ (RuleWriter <$>) $ getCompose $ f <$?> (a,w)
138 f <$*> RuleWriter w = Compose $ (RuleWriter <$>) $ getCompose $ f <$*> w
139 Compose ws <||> RuleWriter w = Compose $ (RuleWriter <$>) $ getCompose $ Compose (unRuleWriter <$> ws) <||> w
140 Compose ws <|?> (a,RuleWriter w) = Compose $ (RuleWriter <$>) $ getCompose $ Compose (unRuleWriter <$> ws) <|?> (a,w)
141 Compose ws <|*> RuleWriter w = Compose $ (RuleWriter <$>) $ getCompose $ Compose (unRuleWriter <$> ws) <|*> w
142 deriving instance Sym_RNC RuleWriter
144 -- ** Class 'Sym_RuleWriter'
145 -- | Symantics for rendering 'Writer' rules.
147 -- * 'ruleWriter' renders a rule, either its body or a reference to it, according to 'RuleMode'.
148 -- * 'argWriter' renders an argument.
149 class Sym_RuleWriter g where
150 ruleWriter :: Writer () -> g a -> RuleWriter a
151 argWriter :: Text -> g a
152 instance Sym_RuleWriter Writer where
153 argWriter = writeText
154 ruleWriter call body =
155 RuleWriter $ Writer $ \rm po pp ->
157 RuleMode_Ref -> unWriter call rm po pp
160 [ unWriter call RuleMode_Ref (infixN0,SideL) pp
162 , unWriter body RuleMode_Ref (infixN0,SideR) pp