1 {-# LANGUAGE OverloadedStrings #-}
2 module Symantic.Parser.Grammar.Write where
4 import Control.Monad (Monad(..))
5 import Data.Bool (Bool(..))
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 Language.Haskell.TH.HideName
12 import Text.Show (Show(..))
13 import qualified Data.Functor as Functor
14 import qualified Data.HashMap.Strict as HM
15 import qualified Data.List as List
16 import qualified Data.Text.Lazy as TL
17 import qualified Data.Text.Lazy.Builder as TLB
19 import Symantic.ObserveSharing
20 import Symantic.Fixity
21 import Symantic.Parser.Grammar.Combinators
23 -- * Type 'WriteGrammar'
24 newtype WriteGrammar (showName::Bool) a = WriteGrammar { unWriteGrammar ::
25 WriteGrammarInh -> Maybe TLB.Builder }
27 instance IsString (WriteGrammar sN a) where
28 fromString s = WriteGrammar $ \_inh ->
29 if List.null s then Nothing
30 else Just (fromString s)
32 -- ** Type 'WriteGrammarInh'
35 { writeGrammarInh_indent :: TLB.Builder
36 , writeGrammarInh_op :: (Infix, Side)
37 , writeGrammarInh_pair :: Pair
40 emptyWriteGrammarInh :: WriteGrammarInh
41 emptyWriteGrammarInh = WriteGrammarInh
42 { writeGrammarInh_indent = "\n"
43 , writeGrammarInh_op = (infixN0, SideL)
44 , writeGrammarInh_pair = pairParen
47 writeGrammar :: WriteGrammar sN a -> TL.Text
48 writeGrammar (WriteGrammar go) =
49 TLB.toLazyText $ fromMaybe "" $
50 go emptyWriteGrammarInh
52 pairWriteGrammarInh ::
53 Semigroup s => IsString s =>
54 WriteGrammarInh -> Infix -> Maybe s -> Maybe s
55 pairWriteGrammarInh inh op s =
56 if isPairNeeded (writeGrammarInh_op inh) op
57 then Just (fromString o<>" ")<>s<>Just (" "<>fromString c)
59 where (o,c) = writeGrammarInh_pair inh
61 instance CombAlternable (WriteGrammar sN) where
62 alt exn x y = WriteGrammar $ \inh ->
63 pairWriteGrammarInh inh op $
65 { writeGrammarInh_op = (op, SideL)
66 , writeGrammarInh_pair = pairParen
68 Just (" |^"<>fromString (show exn)<>" ") <>
70 { writeGrammarInh_op = (op, SideR)
71 , writeGrammarInh_pair = pairParen
73 where op = infixB SideL 3
74 throw exn = WriteGrammar $ \inh ->
75 pairWriteGrammarInh inh op $
76 Just ("throw "<>fromString (show exn))
79 failure _sf = "failure"
81 try x = WriteGrammar $ \inh ->
82 pairWriteGrammarInh inh op $
83 Just "try " <> unWriteGrammar x inh
86 instance CombApplicable (WriteGrammar sN) where
87 pure _ = WriteGrammar $ return Nothing{-TODO: print?-}
89 WriteGrammar x <*> WriteGrammar y = WriteGrammar $ \inh ->
91 { writeGrammarInh_op = (op, side)
92 , writeGrammarInh_pair = pairParen
94 case x (inh' SideL) of
95 Nothing -> y (inh' SideR)
97 case y (inh' SideR) of
100 pairWriteGrammarInh inh op $
101 Just $ xt <> ", " <> yt
104 instance CombFoldable (WriteGrammar sN) where
105 chainPre f x = WriteGrammar $ \inh ->
106 pairWriteGrammarInh inh op $
108 unWriteGrammar f inh <> Just " " <>
111 chainPost f x = WriteGrammar $ \inh ->
112 pairWriteGrammarInh inh op $
114 unWriteGrammar f inh <> Just " " <>
121 ) => Referenceable letName (WriteGrammar sN) where
122 ref isRec name = WriteGrammar $ \inh ->
123 pairWriteGrammarInh inh op $
124 Just (if isRec then "rec " else "ref ") <>
125 Just (fromString (show (hideableName @sN name)))
132 ) => Letsable letName (WriteGrammar sN) where
133 lets defs x = WriteGrammar $ \inh ->
134 pairWriteGrammarInh inh op $
137 (\name (SomeLet val) ->
138 Just (fromString (show (hideableName @sN name)))
139 <> unWriteGrammar val inh)
141 <> unWriteGrammar x inh
144 instance CombLookable (WriteGrammar sN) where
145 look x = WriteGrammar $ \inh ->
146 pairWriteGrammarInh inh op $
147 Just "look " <> unWriteGrammar x inh
149 negLook x = WriteGrammar $ \inh ->
150 pairWriteGrammarInh inh op $
151 Just "negLook " <> unWriteGrammar x inh
154 instance CombMatchable (WriteGrammar sN) where
155 conditional a bs d = WriteGrammar $ \inh ->
156 pairWriteGrammarInh inh op $
157 Just "conditional " <>
158 unWriteGrammar a inh <>
159 unWriteGrammar d inh <>
161 Just (mconcat (List.intersperse ", " $
162 catMaybes $ (Functor.<$> bs) $ \(p{-TODO: print?-}, b) ->
163 unWriteGrammar b inh{writeGrammarInh_op=(infixN 0, SideL)})) <>
167 instance CombSatisfiable tok (WriteGrammar sN) where
168 satisfyOrFail _fs _f = "satisfy"
169 instance CombSelectable (WriteGrammar sN) where
170 branch lr l r = WriteGrammar $ \inh ->
171 pairWriteGrammarInh inh op $
173 unWriteGrammar lr inh <> Just " " <>
174 unWriteGrammar l inh <> Just " " <>