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.List as List
13 import qualified Data.Text.Lazy as TL
14 import qualified Data.Text.Lazy.Builder as TLB
16 import Symantic.Univariant.Letable
17 import Symantic.Parser.Grammar.Combinators
18 import Symantic.Parser.Grammar.Fixity
20 -- * Type 'WriteGrammar'
21 newtype WriteGrammar (showName::Bool) a = WriteGrammar { unWriteGrammar :: WriteGrammarInh -> Maybe TLB.Builder }
23 instance IsString (WriteGrammar sN a) where
24 fromString s = WriteGrammar $ \_inh ->
25 if List.null s then Nothing
26 else Just (fromString s)
28 -- ** Type 'WriteGrammarInh'
31 { writeGrammarInh_indent :: TLB.Builder
32 , writeGrammarInh_op :: (Infix, Side)
33 , writeGrammarInh_pair :: Pair
36 emptyWriteGrammarInh :: WriteGrammarInh
37 emptyWriteGrammarInh = WriteGrammarInh
38 { writeGrammarInh_indent = "\n"
39 , writeGrammarInh_op = (infixN0, SideL)
40 , writeGrammarInh_pair = pairParen
43 writeGrammar :: WriteGrammar sN a -> TL.Text
44 writeGrammar (WriteGrammar r) = TLB.toLazyText $ fromMaybe "" $ r emptyWriteGrammarInh
46 pairWriteGrammarInh ::
47 Semigroup s => IsString s =>
48 WriteGrammarInh -> Infix -> Maybe s -> Maybe s
49 pairWriteGrammarInh inh op s =
50 if isPairNeeded (writeGrammarInh_op inh) op
51 then Just (fromString o<>" ")<>s<>Just (" "<>fromString c)
53 where (o,c) = writeGrammarInh_pair inh
56 ShowLetName sN letName =>
57 Letable letName (WriteGrammar sN) where
58 def name x = WriteGrammar $ \inh ->
59 pairWriteGrammarInh inh op $
61 <> Just (fromString (showLetName @sN name))
62 <> unWriteGrammar x inh
65 ref rec name = WriteGrammar $ \inh ->
66 pairWriteGrammarInh inh op $
67 Just (if rec then "rec " else "ref ") <>
68 Just (fromString (showLetName @sN name))
71 instance Applicable (WriteGrammar sN) where
72 pure _ = WriteGrammar $ return Nothing
74 WriteGrammar x <*> WriteGrammar y = WriteGrammar $ \inh ->
76 { writeGrammarInh_op = (op, side)
77 , writeGrammarInh_pair = pairParen
79 case x (inh' SideL) of
80 Nothing -> y (inh' SideR)
82 case y (inh' SideR) of
85 pairWriteGrammarInh inh op $
86 Just $ xt <> ", " <> yt
89 instance Alternable (WriteGrammar sN) where
91 try x = WriteGrammar $ \inh ->
92 pairWriteGrammarInh inh op $
93 Just "try " <> unWriteGrammar x inh
96 x <|> y = WriteGrammar $ \inh ->
97 pairWriteGrammarInh inh op $
99 { writeGrammarInh_op = (op, SideL)
100 , writeGrammarInh_pair = pairParen
104 { writeGrammarInh_op = (op, SideR)
105 , writeGrammarInh_pair = pairParen
107 where op = infixB SideL 3
108 instance Satisfiable tok (WriteGrammar sN) where
109 satisfy _es _f = "satisfy"
110 instance Selectable (WriteGrammar sN) where
111 branch lr l r = WriteGrammar $ \inh ->
112 pairWriteGrammarInh inh op $
114 unWriteGrammar lr inh <> Just " " <>
115 unWriteGrammar l inh <> Just " " <>
119 instance Matchable (WriteGrammar sN) where
120 conditional a _ps bs d = WriteGrammar $ \inh ->
121 pairWriteGrammarInh inh op $
122 Just "conditional " <>
123 unWriteGrammar a inh <>
125 Just (mconcat (List.intersperse ", " $
126 catMaybes $ (Pre.<$> bs) $ \x ->
127 unWriteGrammar x inh{writeGrammarInh_op=(infixN 0, SideL)})) <>
132 instance Lookable (WriteGrammar sN) where
133 look x = WriteGrammar $ \inh ->
134 pairWriteGrammarInh inh op $
135 Just "look " <> unWriteGrammar x inh
137 negLook x = WriteGrammar $ \inh ->
138 pairWriteGrammarInh inh op $
139 Just "negLook " <> unWriteGrammar x inh
142 instance Foldable (WriteGrammar sN) where
143 chainPre f x = WriteGrammar $ \inh ->
144 pairWriteGrammarInh inh op $
146 unWriteGrammar f inh <> Just " " <>
149 chainPost f x = WriteGrammar $ \inh ->
150 pairWriteGrammarInh inh op $
152 unWriteGrammar f inh <> Just " " <>