1 {-# OPTIONS_GHC -fno-warn-orphans #-}
2 -- | Symantics for terminal grammars.
3 module Language.Symantic.Grammar.Terminal where
6 import Data.Semigroup (Semigroup(..))
7 import Data.String (IsString(..))
8 import Prelude hiding (any)
9 import qualified Data.Bool as Bool
10 import qualified Data.Char as Char
11 import qualified Data.List as List
12 import qualified Data.Text as Text
14 import Language.Symantic.Grammar.Fixity
15 import Language.Symantic.Grammar.EBNF
18 -- | Terminal grammar.
20 = Terminal { unTerminal :: g a }
21 deriving (Functor, Gram_Terminal)
22 deriving instance Gram_Rule g => Gram_Rule (Terminal g)
24 -- ** Class 'Gram_Terminal'
25 -- | Symantics for terminal grammars.
26 class Gram_Terminal g where
28 but :: Terminal g Char -> Terminal g Char -> Terminal g Char
30 char :: Char -> g Char
31 string :: String -> g String
32 unicat :: Unicat -> g Char
33 range :: (Char, Char) -> g Char
34 -- string = foldr (\c -> (<*>) ((:) <$> char c)) (pure "")
35 -- string [] = pure []
36 -- string (c:cs) = (:) <$> char c <*> string cs
37 deriving instance Gram_Terminal RuleEBNF
38 instance Gram_Terminal EBNF where
40 Terminal (EBNF f) `but` Terminal (EBNF g) =
41 Terminal $ EBNF $ \bo po -> parenInfix po op $
42 f bo (op, SideL) <> " - " <> g bo (op, SideR)
44 eoi = ebnf_const "eoi"
45 char = ebnf_const . escape
47 escape c | Char.isPrint c && c /= '"' = Text.concat $ ["\"", Text.singleton c, "\""]
48 escape c = Text.concat ["U+", Text.pack $ show $ Char.ord c]
50 case List.break (\c -> Bool.not (Char.isPrint c) || c == '"') s of
52 ("", [c]) -> "" <$ char c
53 (ps, [c]) -> "" <$ raw ps <* char c
54 ("", c:rs) -> "" <$ char c <* string rs
55 (ps, c:rs) -> "" <$ raw ps <* char c <* string rs
57 raw cs = ebnf_const $ Text.concat $ ["\"", Text.pack cs, "\""]
58 unicat = ebnf_const . Text.pack . show
59 range (l, h) = ebnf_const $ Text.concat
64 instance IsString (EBNF String) where
68 -- | Unicode category.
75 | Unicat Char.GeneralCategory
78 unicode_categories :: Unicat -> [Char.GeneralCategory]
79 unicode_categories c =
82 [ Char.UppercaseLetter
83 , Char.LowercaseLetter
84 , Char.TitlecaseLetter
90 , Char.SpacingCombiningMark
99 [ Char.ConnectorPunctuation
100 , Char.DashPunctuation
101 , Char.OpenPunctuation
102 , Char.ClosePunctuation
103 , Char.OtherPunctuation
107 , Char.CurrencySymbol
108 , Char.ModifierSymbol