import Data.Semigroup (Semigroup(..))
import Data.String (IsString(..))
import Prelude hiding (any)
+import qualified Data.List as L
import Language.Symantic.Grammar.Meta
import Language.Symantic.Grammar.Fixity
f bo (op, SideL) <> " - " <> g bo (op, SideR)
where op = infixL 6
-cf_of_Terminal :: Terminal g a -> CF g a
-cf_of_Terminal (Terminal g) = CF g
-
-cf_of_Reg :: Reg lr g a -> CF g a
-cf_of_Reg (Reg g) = CF g
+class ContextFreeOf gram where
+ cfOf :: gram g a -> CF g a
+instance ContextFreeOf Terminal where
+ cfOf (Terminal g) = CF g
+instance ContextFreeOf (Reg lr) where
+ cfOf (Reg g) = CF g
-- ** Class 'Gram_CF'
-- | Symantics for context-free grammars.
option x g = g <+> pure x
optional :: g a -> g (Maybe a)
optional v = Just <$> v <+> pure Nothing
+ manyFoldL :: b -> (a -> b -> b) -> g a -> g b
+ manyFoldL e f a = someFoldL e f a <+> pure e
+ someFoldL :: b -> (a -> b -> b) -> g a -> g b
+ someFoldL e f a = f <$> a <*> manyFoldL e f a
many :: g a -> g [a]
- many a = some a <+> pure []
+ many = fmap L.reverse . manyFoldL [] (:)
some :: g a -> g [a]
- some a = (:) <$> a <*> many a
- skipMany :: g a -> g ()
- skipMany = void . many
+ some = fmap L.reverse . someFoldL [] (:)
+ manySkip :: g a -> g ()
+ manySkip = void . many
+ someSkip :: g a -> g ()
+ someSkip = void . some
--manyTill :: g a -> g end -> g [a]
--manyTill g end = go where go = ([] <$ end) <|> ((:) <$> g <*> go)
inside
(f <$ begin <*> in_ <* end) <+> next
deriving instance Gram_AltApp RuleEBNF
instance Gram_AltApp EBNF where
- many (EBNF g) = EBNF $ \rm _po -> "{" <> g rm (op, SideL) <> "}" where op = infixN0
- some (EBNF g) = EBNF $ \rm _po -> "{" <> g rm (op, SideL) <> "}-" where op = infixN0
+ manyFoldL _ _ (EBNF g) = EBNF $ \rm _po -> "{" <> g rm (op, SideL) <> "}" where op = infixN0
+ someFoldL _ _ (EBNF g) = EBNF $ \rm _po -> "{" <> g rm (op, SideL) <> "}-" where op = infixN0
option _x (EBNF g) = EBNF $ \rm _po ->
"[" <> g rm (op, SideL) <> "]" where op = infixN0
) => Gram_Comment g where
commentable :: g () -> g () -> g () -> g ()
commentable = rule3 "commentable" $ \space line block ->
- skipMany $ choice [space, line, block]
+ manySkip $ choice [space, line, block]
comment_line :: CF g String -> CF g String
comment_line prefix = rule "comment_line" $
prefix *> many (any `minus` (void (char '\n') <+> eoi))
comment_block :: CF g String -> Reg lr g String -> CF g String
comment_block begin end = rule "comment_block" $
- begin *> many (any `minus` end) <* cf_of_Reg end
+ begin *> many (any `minus` end) <* cfOf end
lexeme :: CF g a -> CF g a
lexeme = rule1 "lexeme" $ \g ->
g <* commentable