1 {-# LANGUAGE AllowAmbiguousTypes #-}
2 {-# LANGUAGE ConstraintKinds #-}
3 {-# LANGUAGE DeriveFunctor #-}
4 {-# LANGUAGE ExistentialQuantification #-}
5 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
6 {-# LANGUAGE PolyKinds #-}
7 {-# LANGUAGE UndecidableInstances #-}
8 module Language.Symantic.Compiling.Grammar where
10 import Control.Arrow (left)
11 import Control.Monad (void)
12 import Data.Proxy (Proxy(..))
13 import Data.Semigroup (Semigroup(..))
14 import Prelude hiding (mod, not, any)
15 import qualified Data.Char as Char
16 import qualified Data.Function as Fun
17 import qualified Data.Map.Strict as Map
18 import qualified Data.Text as Text
20 import Language.Symantic.Grammar
21 import Language.Symantic.Typing
22 import Language.Symantic.Compiling.Module
24 -- * Class 'Gram_Name'
36 ) => Gram_Name g where
37 g_mod_path :: CF g PathMod
38 g_mod_path = rule "mod_path" $
43 g_mod_name :: CF g NameMod
44 g_mod_name = rule "mod_name" $
45 (NameMod . Text.pack <$>) $
49 <*. (any `but` g_term_idname_tail)
51 identG = (:) <$> headG <*> many (cf_of_Terminal g_term_idname_tail)
52 headG = unicat $ Unicat Char.UppercaseLetter
54 g_term_mod_name :: CF g (Mod NameTe)
55 g_term_mod_name = rule "term_mod_name" $
58 parens g_term_mod_opname
59 g_term_name :: CF g NameTe
60 g_term_name = rule "term_name" $
65 g_term_mod_idname :: CF g (Mod NameTe)
66 g_term_mod_idname = rule "term_mod_idname" $
68 <$> option [] (try $ g_mod_path <* char '.')
70 g_term_idname :: CF g NameTe
71 g_term_idname = rule "term_idname" $
72 (NameTe . Text.pack <$>) $
76 <*. (any `but` g_term_idname_tail)
78 identG = (:) <$> headG <*> many (cf_of_Terminal g_term_idname_tail)
79 headG = unicat $ Unicat_Letter
80 g_term_idname_tail :: Terminal g Char
81 g_term_idname_tail = rule "term_idname_tail" $
82 unicat Unicat_Letter <+>
84 g_term_keywords :: Reg rl g String
85 g_term_keywords = rule "term_keywords" $
86 choice $ string <$> ["in", "let"]
88 g_term_mod_opname :: CF g (Mod NameTe)
89 g_term_mod_opname = rule "term_mod_opname" $
91 <$> option [] (try $ g_mod_path <* char '.')
93 g_term_opname :: CF g NameTe
94 g_term_opname = rule "term_opname" $
95 (NameTe . Text.pack <$>) $
99 <*. (any `but` g_term_opname_ok)
101 symG = some $ cf_of_Terminal g_term_opname_ok
102 g_term_opname_ok :: Terminal g Char
103 g_term_opname_ok = rule "term_opname_ok" $
110 koG = choice (char <$> ['(', ')', '`', '\'', ',', '[', ']'])
111 g_term_keysyms :: Reg rl g String
112 g_term_keysyms = rule "term_keysyms" $
113 choice $ string <$> ["\\", "->", "=", "@"]
115 deriving instance Gram_Name g => Gram_Name (CF g)
116 instance Gram_Name EBNF
117 instance Gram_Name RuleEBNF
119 -- * Class 'Gram_Term_Type'
130 ) => Gram_Term_Type src g where
131 g_term_abst_decl :: CF g (NameTe, AST_Type src)
132 g_term_abst_decl = rule "term_abst_decl" $
135 <* (symbol "::" <+> symbol ":")
136 -- NOTE: "::" is Haskell compatibility and ":" is another common notation.
139 deriving instance Gram_Term_Type src g => Gram_Term_Type src (CF g)
140 instance Gram_Source src EBNF => Gram_Term_Type src EBNF
141 instance Gram_Source src RuleEBNF => Gram_Term_Type src RuleEBNF
143 -- ** Type 'Error_Term_Gram'
145 = Error_Term_Gram_Fixity Error_Fixity
146 | Error_Term_Gram_Term_incomplete
147 | Error_Term_Gram_Type_applied_to_nothing
148 | Error_Term_Gram_not_applicable
149 | Error_Term_Gram_application
150 | Error_Term_Gram_application_mismatch
151 | Error_Term_Gram_Module Error_Module
154 -- * Class 'Gram_Term'
157 , Gram_Error Error_Term_Gram g
167 , Gram_Term_Type src g
168 , Gram_Term_Atoms src ss g
169 , Gram_State (Imports, Modules src ss) g
170 ) => Gram_Term src ss g where
171 g_term :: CF g (AST_Term src ss)
172 g_term = rule "term" $
178 g_term_operators :: CF g (AST_Term src ss)
179 g_term_operators = rule "term_operators" $
181 left Error_Term_Gram_Fixity <$>
184 g_ops :: CF g (Either Error_Fixity (AST_Term src ss))
185 g_ops = operators g_term_atom g_prefix g_infix g_postfix
186 g_prefix :: CF g (Unifix, AST_Term src ss -> AST_Term src ss)
187 g_infix :: CF g (Infix, AST_Term src ss -> AST_Term src ss -> AST_Term src ss)
188 g_postfix :: CF g (Unifix, AST_Term src ss -> AST_Term src ss)
189 g_prefix = g_catch $ g_source $ g_get_after $ op_prefix <$> g_prefix_op
190 g_infix = g_catch $ g_source $ g_get_after $ op_infix <$> g_infix_op
191 g_postfix = g_catch $ g_source $ g_get_after $ op_postfix <$> g_postfix_op
194 -> (Imports, Modules src ss)
196 -> Either Error_Term_Gram
197 (Infix, AST_Term src ss -> AST_Term src ss -> AST_Term src ss)
198 op_infix name (imps, mods) src = do
199 t <- Error_Term_Gram_Module `left`
200 lookupDefTerm FixitySing_Infix imps name mods
201 Right $ (token_fixity t,) $ \a b ->
202 (BinTree0 (token_term t src) `BinTree2` a) `BinTree2` b
203 op_prefix, op_postfix
205 -> (Imports, Modules src ss)
207 -> Either Error_Term_Gram
209 , AST_Term src ss -> AST_Term src ss )
210 op_prefix name (imps, mods) src = do
211 t <- Error_Term_Gram_Module `left`
212 lookupDefTerm FixitySing_Prefix imps name mods
213 Right $ (token_fixity t,) $ \a ->
214 BinTree0 (token_term t src) `BinTree2` a
215 op_postfix name (imps, mods) src = do
216 t <- Error_Term_Gram_Module `left`
217 lookupDefTerm FixitySing_Postfix imps name mods
218 Right $ (token_fixity t,) $ \a ->
219 BinTree0 (token_term t src) `BinTree2` a
220 g_postfix_op :: CF g (Mod NameTe)
221 g_postfix_op = rule "term_op_postfix" $
223 g_backquote *> g_term_mod_idname <+> -- <* (cf_of_Terminal $ Gram.Term (pure ' ') `but` g_backquote)
225 g_infix_op :: CF g (Mod NameTe)
226 g_infix_op = rule "term_op_infix" $
228 between g_backquote g_backquote g_term_mod_idname <+>
229 try (Fun.const <$> g_term_mod_opname <*> (string " " <+> string "\n")) <+>
231 g_prefix_op :: CF g (Mod NameTe)
232 g_prefix_op = rule "term_op_prefix" $
234 g_term_mod_idname <* g_backquote <+>
236 g_backquote :: Gram_Terminal g' => g' Char
237 g_backquote = char '`'
239 g_term_atom :: CF g (AST_Term src ss)
240 g_term_atom = rule "term_atom" $
244 (\typ src -> BinTree0 $ inj_EToken src $ Token_Term_Type typ)
245 <$ char '@' <*> g_type) :) $
247 (try <$> g_term_atomsR @_ @_ @ss) <>
249 g_catch $ g_source $ g_get_after $
250 (\m (imps, mods) src ->
251 case lookupDefTerm FixitySing_Infix imps m mods of
252 Right t -> Right $ BinTree0 $ token_term t src
255 [] `Mod` n -> Right $ BinTree0 $ Token_Term_Var src n
256 _ -> Left $ Error_Term_Gram_Module err
257 ) <$> g_term_mod_name
260 g_term_group :: CF g (AST_Term src ss)
261 g_term_group = rule "term_group" $ parens g_term
262 g_term_abst :: CF g (AST_Term src ss)
263 g_term_abst = rule "term_abst" $
267 BinTree0 . Token_Term_Abst src x ty_x) te xs) <$>) $
268 g_term_abst_args_body
269 (symbol "\\" *> some g_term_abst_decl <* symbol "->")
271 g_term_abst_args_body
272 :: CF g [(NameTe, AST_Type src)]
273 -> CF g (AST_Term src ss)
274 -> CF g ([(NameTe, AST_Type src)], AST_Term src ss)
275 -- g_term_abst_args_body args body = (,) <$> args <*> body
276 g_term_abst_args_body cf_args cf_body =
278 (\a b (imps::Imports, mods::Modules src ss) -> ((imps, mods), (a, b)))
279 <$> (g_state_after $ (<$> cf_args) $ \args (imps::Imports, Modules mods) ->
280 ((imps, Modules $ Map.alter (setArgs args) [] mods), args))
284 Nothing -> Just $ moduleEmpty {module_infix = insArg mempty args}
285 Just mod -> Just $ mod
286 { module_prefix = delArg (module_prefix mod) args
287 , module_infix = insArg (module_infix mod) args
288 , module_postfix = delArg (module_postfix mod) args
290 delArg :: ModuleFixy src ss Unifix -> [(NameTe, _a)] -> ModuleFixy src ss Unifix
291 delArg = foldr $ \(n, _) -> Map.delete n
292 insArg :: ModuleFixy src ss Infix -> [(NameTe, _a)] -> ModuleFixy src ss Infix
293 insArg = foldr $ \(n, _) ->
294 Map.insert n Tokenizer
295 { token_term = \src -> Token_Term_Var src n
296 , token_fixity = infixN5
298 g_term_let :: CF g (AST_Term src ss)
299 g_term_let = rule "term_let" $
301 (\name args bound body src ->
303 Token_Term_Let src name
304 (foldr (\(x, ty_x) ->
305 BinTree0 . Token_Term_Abst src x ty_x) bound args) body)
308 <*> many g_term_abst_decl
316 , Gram_Term_Atoms src ss (CF g)
317 ) => Gram_Term src ss (CF g)
319 ( Gram_Term_Atoms src ss EBNF
320 , Gram_Source src EBNF
321 ) => Gram_Term src ss EBNF
323 ( Gram_Term_Atoms src ss RuleEBNF
324 , Gram_Source src RuleEBNF
325 ) => Gram_Term src ss RuleEBNF
327 -- ** Class 'Gram_Term_Atoms'
328 type Gram_Term_Atoms src ss g = Gram_Term_AtomsR src ss ss g
330 -- *** Class 'Gram_Term_AtomsR'
331 class Gram_Term_AtomsR src (ss::[*]) (rs::[*]) g where
332 g_term_atomsR :: [CF g (AST_Term src ss)]
333 instance Gram_Term_AtomsR src ss '[] g where
336 ( Gram_Term_AtomsFor src ss g t
337 , Gram_Term_AtomsR src ss rs g
338 ) => Gram_Term_AtomsR src ss (Proxy t ': rs) g where
340 g_term_atomsFor @_ @_ @_ @t <>
341 g_term_atomsR @_ @_ @rs
343 -- *** Class 'Gram_Term_AtomsFor'
344 class Gram_Term_AtomsFor src ss g t where
345 g_term_atomsFor :: [CF g (AST_Term src ss)]
350 ( Gram_Term () '[Proxy (->), Proxy Integer] g
354 , voiD g_term_operators
358 , void (g_term_abst_decl::CF g (NameTe, AST_Type ()))
360 , void g_term_mod_name
363 , void $ cf_of_Terminal g_term_idname_tail
364 , void $ cf_of_Reg g_term_keywords
365 , void g_term_mod_opname
367 , void $ cf_of_Terminal g_term_opname_ok
368 , void $ cf_of_Reg g_term_keysyms
370 voiD :: CF g (AST_Term () '[Proxy (->), Proxy Integer]) -> CF g ()