1 {-# LANGUAGE OverloadedStrings #-}
2 module Symantic.Parser.Grammar.Write where
4 import Data.Bool (Bool(..))
5 import Control.Monad (Monad(..))
6 import Data.Function (($))
7 import Data.Maybe (Maybe(..), fromMaybe, catMaybes)
8 import Data.Monoid (Monoid(..))
9 import Data.Semigroup (Semigroup(..))
10 import Data.String (IsString(..))
11 import GHC.TypeLits (symbolVal)
12 import qualified Data.Functor as Functor
13 import qualified Data.HashMap.Strict as HM
14 import qualified Data.List as List
15 import qualified Data.Text.Lazy as TL
16 import qualified Data.Text.Lazy.Builder as TLB
18 import Symantic.Univariant.Letable
19 import Symantic.Parser.Grammar.Combinators
20 import Symantic.Parser.Grammar.Fixity
22 -- * Type 'WriteGrammar'
23 newtype WriteGrammar (showName::Bool) a = WriteGrammar { unWriteGrammar ::
24 WriteGrammarInh -> Maybe TLB.Builder }
26 instance IsString (WriteGrammar sN a) where
27 fromString s = WriteGrammar $ \_inh ->
28 if List.null s then Nothing
29 else Just (fromString s)
31 -- ** Type 'WriteGrammarInh'
34 { writeGrammarInh_indent :: TLB.Builder
35 , writeGrammarInh_op :: (Infix, Side)
36 , writeGrammarInh_pair :: Pair
39 emptyWriteGrammarInh :: WriteGrammarInh
40 emptyWriteGrammarInh = WriteGrammarInh
41 { writeGrammarInh_indent = "\n"
42 , writeGrammarInh_op = (infixN0, SideL)
43 , writeGrammarInh_pair = pairParen
46 writeGrammar :: WriteGrammar sN a -> TL.Text
47 writeGrammar (WriteGrammar go) =
48 TLB.toLazyText $ fromMaybe "" $
49 go emptyWriteGrammarInh
51 pairWriteGrammarInh ::
52 Semigroup s => IsString s =>
53 WriteGrammarInh -> Infix -> Maybe s -> Maybe s
54 pairWriteGrammarInh inh op s =
55 if isPairNeeded (writeGrammarInh_op inh) op
56 then Just (fromString o<>" ")<>s<>Just (" "<>fromString c)
58 where (o,c) = writeGrammarInh_pair inh
60 instance CombApplicable (WriteGrammar sN) where
61 pure _ = WriteGrammar $ return Nothing
63 WriteGrammar x <*> WriteGrammar y = WriteGrammar $ \inh ->
65 { writeGrammarInh_op = (op, side)
66 , writeGrammarInh_pair = pairParen
68 case x (inh' SideL) of
69 Nothing -> y (inh' SideR)
71 case y (inh' SideR) of
74 pairWriteGrammarInh inh op $
75 Just $ xt <> ", " <> yt
78 instance CombAlternable (WriteGrammar sN) where
80 try x = WriteGrammar $ \inh ->
81 pairWriteGrammarInh inh op $
82 Just "try " <> unWriteGrammar x inh
85 x <|> y = WriteGrammar $ \inh ->
86 pairWriteGrammarInh inh op $
88 { writeGrammarInh_op = (op, SideL)
89 , writeGrammarInh_pair = pairParen
93 { writeGrammarInh_op = (op, SideR)
94 , writeGrammarInh_pair = pairParen
96 where op = infixB SideL 3
97 instance CombFoldable (WriteGrammar sN) where
98 chainPre f x = WriteGrammar $ \inh ->
99 pairWriteGrammarInh inh op $
101 unWriteGrammar f inh <> Just " " <>
104 chainPost f x = WriteGrammar $ \inh ->
105 pairWriteGrammarInh inh op $
107 unWriteGrammar f inh <> Just " " <>
111 ShowLetName sN letName =>
112 Letable letName (WriteGrammar sN) where
113 shareable name x = WriteGrammar $ \inh ->
114 pairWriteGrammarInh inh op $
116 <> Just (fromString (showLetName @sN name))
117 <> unWriteGrammar x inh
120 ref rec name = WriteGrammar $ \inh ->
121 pairWriteGrammarInh inh op $
122 Just (if rec then "rec " else "ref ") <>
123 Just (fromString (showLetName @sN name))
127 ShowLetName sN letName =>
128 Letsable letName (WriteGrammar sN) where
129 lets defs x = WriteGrammar $ \inh ->
130 pairWriteGrammarInh inh op $
133 (\name (SomeLet val) ->
134 Just (fromString (showLetName @sN name))
135 <> unWriteGrammar val inh)
137 <> unWriteGrammar x inh
140 instance CombLookable (WriteGrammar sN) where
141 look x = WriteGrammar $ \inh ->
142 pairWriteGrammarInh inh op $
143 Just "look " <> unWriteGrammar x inh
145 negLook x = WriteGrammar $ \inh ->
146 pairWriteGrammarInh inh op $
147 Just "negLook " <> unWriteGrammar x inh
150 instance CombMatchable (WriteGrammar sN) where
151 conditional a _ps bs d = WriteGrammar $ \inh ->
152 pairWriteGrammarInh inh op $
153 Just "conditional " <>
154 unWriteGrammar a inh <>
156 Just (mconcat (List.intersperse ", " $
157 catMaybes $ (Functor.<$> bs) $ \x ->
158 unWriteGrammar x inh{writeGrammarInh_op=(infixN 0, SideL)})) <>
163 instance CombSatisfiable tok (WriteGrammar sN) where
164 satisfy _es _f = "satisfy"
165 instance CombSelectable (WriteGrammar sN) where
166 branch lr l r = WriteGrammar $ \inh ->
167 pairWriteGrammarInh inh op $
169 unWriteGrammar lr inh <> Just " " <>
170 unWriteGrammar l inh <> Just " " <>
174 instance CombThrowable (WriteGrammar sN) where
175 throw lbl = WriteGrammar $ \inh ->
176 pairWriteGrammarInh inh op $
177 Just ("throw "<>fromString (symbolVal lbl))