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 qualified Data.Functor as Pre
12 import qualified Data.HashMap.Strict as HM
13 import qualified Data.List as List
14 import qualified Data.Text.Lazy as TL
15 import qualified Data.Text.Lazy.Builder as TLB
17 import Symantic.Univariant.Letable
18 import Symantic.Parser.Grammar.Combinators
19 import Symantic.Parser.Grammar.Fixity
21 -- * Type 'WriteGrammar'
22 newtype WriteGrammar (showName::Bool) a = WriteGrammar { unWriteGrammar ::
23 WriteGrammarInh -> Maybe TLB.Builder }
25 instance IsString (WriteGrammar sN a) where
26 fromString s = WriteGrammar $ \_inh ->
27 if List.null s then Nothing
28 else Just (fromString s)
30 -- ** Type 'WriteGrammarInh'
33 { writeGrammarInh_indent :: TLB.Builder
34 , writeGrammarInh_op :: (Infix, Side)
35 , writeGrammarInh_pair :: Pair
38 emptyWriteGrammarInh :: WriteGrammarInh
39 emptyWriteGrammarInh = WriteGrammarInh
40 { writeGrammarInh_indent = "\n"
41 , writeGrammarInh_op = (infixN0, SideL)
42 , writeGrammarInh_pair = pairParen
45 writeGrammar :: WriteGrammar sN a -> TL.Text
46 writeGrammar (WriteGrammar go) =
47 TLB.toLazyText $ fromMaybe "" $
48 go emptyWriteGrammarInh
50 pairWriteGrammarInh ::
51 Semigroup s => IsString s =>
52 WriteGrammarInh -> Infix -> Maybe s -> Maybe s
53 pairWriteGrammarInh inh op s =
54 if isPairNeeded (writeGrammarInh_op inh) op
55 then Just (fromString o<>" ")<>s<>Just (" "<>fromString c)
57 where (o,c) = writeGrammarInh_pair inh
60 ShowLetName sN letName =>
61 Letable letName (WriteGrammar sN) where
62 shareable name x = WriteGrammar $ \inh ->
63 pairWriteGrammarInh inh op $
65 <> Just (fromString (showLetName @sN name))
66 <> unWriteGrammar x inh
69 ref rec name = WriteGrammar $ \inh ->
70 pairWriteGrammarInh inh op $
71 Just (if rec then "rec " else "ref ") <>
72 Just (fromString (showLetName @sN name))
76 ShowLetName sN letName =>
77 Letsable letName (WriteGrammar sN) where
78 lets defs x = WriteGrammar $ \inh ->
79 pairWriteGrammarInh inh op $
82 (\name (SomeLet val) ->
83 Just (fromString (showLetName @sN name))
84 <> unWriteGrammar val inh)
86 <> unWriteGrammar x inh
89 instance Applicable (WriteGrammar sN) where
90 pure _ = WriteGrammar $ return Nothing
92 WriteGrammar x <*> WriteGrammar y = WriteGrammar $ \inh ->
94 { writeGrammarInh_op = (op, side)
95 , writeGrammarInh_pair = pairParen
97 case x (inh' SideL) of
98 Nothing -> y (inh' SideR)
100 case y (inh' SideR) of
103 pairWriteGrammarInh inh op $
104 Just $ xt <> ", " <> yt
107 instance Alternable (WriteGrammar sN) where
109 try x = WriteGrammar $ \inh ->
110 pairWriteGrammarInh inh op $
111 Just "try " <> unWriteGrammar x inh
114 x <|> y = WriteGrammar $ \inh ->
115 pairWriteGrammarInh inh op $
117 { writeGrammarInh_op = (op, SideL)
118 , writeGrammarInh_pair = pairParen
122 { writeGrammarInh_op = (op, SideR)
123 , writeGrammarInh_pair = pairParen
125 where op = infixB SideL 3
126 instance Satisfiable tok (WriteGrammar sN) where
127 satisfy _es _f = "satisfy"
128 instance Selectable (WriteGrammar sN) where
129 branch lr l r = WriteGrammar $ \inh ->
130 pairWriteGrammarInh inh op $
132 unWriteGrammar lr inh <> Just " " <>
133 unWriteGrammar l inh <> Just " " <>
137 instance Matchable (WriteGrammar sN) where
138 conditional a _ps bs d = WriteGrammar $ \inh ->
139 pairWriteGrammarInh inh op $
140 Just "conditional " <>
141 unWriteGrammar a inh <>
143 Just (mconcat (List.intersperse ", " $
144 catMaybes $ (Pre.<$> bs) $ \x ->
145 unWriteGrammar x inh{writeGrammarInh_op=(infixN 0, SideL)})) <>
150 instance Lookable (WriteGrammar sN) where
151 look x = WriteGrammar $ \inh ->
152 pairWriteGrammarInh inh op $
153 Just "look " <> unWriteGrammar x inh
155 negLook x = WriteGrammar $ \inh ->
156 pairWriteGrammarInh inh op $
157 Just "negLook " <> unWriteGrammar x inh
160 instance Foldable (WriteGrammar sN) where
161 chainPre f x = WriteGrammar $ \inh ->
162 pairWriteGrammarInh inh op $
164 unWriteGrammar f inh <> Just " " <>
167 chainPost f x = WriteGrammar $ \inh ->
168 pairWriteGrammarInh inh op $
170 unWriteGrammar f inh <> Just " " <>