packages feed

symantic-grammar 0.2.0.20170709 → 0.3.0.20180213

raw patch · 11 files changed

+244/−214 lines, 11 filesdep ~megaparsecdep ~tasty-hunitdep ~textPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: megaparsec, tasty-hunit, text, transformers

API changes (from Hackage documentation)

- Language.Symantic.Grammar.ContextFree: comment_block :: Gram_Comment g => CF g String -> Reg lr g String -> CF g String
- Language.Symantic.Grammar.ContextFree: comment_line :: Gram_Comment g => CF g String -> CF g String
- Language.Symantic.Grammar.ContextFree: instance Language.Symantic.Grammar.Terminal.Gram_Terminal g => Language.Symantic.Grammar.Terminal.Gram_Terminal (Language.Symantic.Grammar.ContextFree.CF g)
- Language.Symantic.Grammar.Regular: instance Language.Symantic.Grammar.Terminal.Gram_Terminal g => Language.Symantic.Grammar.Terminal.Gram_Terminal (Language.Symantic.Grammar.Regular.Reg lr g)
- Language.Symantic.Grammar.Terminal: class Gram_Terminal g
- Language.Symantic.Grammar.Terminal: instance Language.Symantic.Grammar.Terminal.Gram_Terminal Language.Symantic.Grammar.EBNF.EBNF
- Language.Symantic.Grammar.Terminal: instance Language.Symantic.Grammar.Terminal.Gram_Terminal Language.Symantic.Grammar.EBNF.RuleEBNF
- Language.Symantic.Grammar.Terminal: instance Language.Symantic.Grammar.Terminal.Gram_Terminal g => Language.Symantic.Grammar.Terminal.Gram_Terminal (Language.Symantic.Grammar.Terminal.Terminal g)
+ Language.Symantic.Grammar.ContextFree: commentBlock :: Gram_Comment g => CF g String -> Reg lr g String -> CF g String
+ Language.Symantic.Grammar.ContextFree: commentLine :: Gram_Comment g => CF g String -> CF g String
+ Language.Symantic.Grammar.ContextFree: instance Language.Symantic.Grammar.Terminal.Gram_Char g => Language.Symantic.Grammar.Terminal.Gram_Char (Language.Symantic.Grammar.ContextFree.CF g)
+ Language.Symantic.Grammar.ContextFree: instance Language.Symantic.Grammar.Terminal.Gram_String g => Language.Symantic.Grammar.Terminal.Gram_String (Language.Symantic.Grammar.ContextFree.CF g)
+ Language.Symantic.Grammar.Regular: instance Language.Symantic.Grammar.Terminal.Gram_Char g => Language.Symantic.Grammar.Terminal.Gram_Char (Language.Symantic.Grammar.Regular.Reg lr g)
+ Language.Symantic.Grammar.Regular: instance Language.Symantic.Grammar.Terminal.Gram_String g => Language.Symantic.Grammar.Terminal.Gram_String (Language.Symantic.Grammar.Regular.Reg lr g)
+ Language.Symantic.Grammar.Terminal: class Gram_Rule g => Gram_Char g
+ Language.Symantic.Grammar.Terminal: class Functor g => Gram_String g
+ Language.Symantic.Grammar.Terminal: eol :: Gram_Char g => g Char
+ Language.Symantic.Grammar.Terminal: instance Language.Symantic.Grammar.Terminal.Gram_Char Language.Symantic.Grammar.EBNF.EBNF
+ Language.Symantic.Grammar.Terminal: instance Language.Symantic.Grammar.Terminal.Gram_Char Language.Symantic.Grammar.EBNF.RuleEBNF
+ Language.Symantic.Grammar.Terminal: instance Language.Symantic.Grammar.Terminal.Gram_Char g => Language.Symantic.Grammar.Terminal.Gram_Char (Language.Symantic.Grammar.Terminal.Terminal g)
+ Language.Symantic.Grammar.Terminal: instance Language.Symantic.Grammar.Terminal.Gram_String Language.Symantic.Grammar.EBNF.EBNF
+ Language.Symantic.Grammar.Terminal: instance Language.Symantic.Grammar.Terminal.Gram_String Language.Symantic.Grammar.EBNF.RuleEBNF
+ Language.Symantic.Grammar.Terminal: instance Language.Symantic.Grammar.Terminal.Gram_String g => Language.Symantic.Grammar.Terminal.Gram_String (Language.Symantic.Grammar.Terminal.Terminal g)
+ Language.Symantic.Grammar.Terminal: space :: Gram_Char g => g Char
+ Language.Symantic.Grammar.Terminal: text :: Gram_String g => Text -> g Text
+ Language.Symantic.Grammar.Terminal: textLazy :: Gram_String g => Text -> g Text
- Language.Symantic.Grammar.ContextFree: class (Gram_Alt g, Gram_App g) => Gram_AltApp g where option x g = g <+> pure x optional v = Just <$> v <+> pure Nothing manyFoldL e f a = someFoldL e f a <+> pure e someFoldL e f a = f <$> a <*> manyFoldL e f a many = fmap reverse . manyFoldL [] (:) some = fmap reverse . someFoldL [] (:) manySkip = void . many someSkip = void . some inside f begin in_ end next = (f <$ begin <*> in_ <* end) <+> next
+ Language.Symantic.Grammar.ContextFree: class (Gram_Alt g, Gram_App g) => Gram_AltApp g
- Language.Symantic.Grammar.ContextFree: class Applicative g => Gram_App g where between open close g = open *> g <* close
+ Language.Symantic.Grammar.ContextFree: class Applicative g => Gram_App g
- Language.Symantic.Grammar.ContextFree: class (Gram_Terminal g, Gram_Rule g, Gram_Alt g, Gram_App g, Gram_AltApp g, Gram_CF g) => Gram_Comment g where commentable = rule3 "commentable" $ \ space line block -> manySkip $ choice [space, line, block] comment_line prefix = rule "comment_line" $ prefix *> many (any `minus` (void (char '\n') <+> eoi)) comment_block begin end = rule "comment_block" $ begin *> many (any `minus` end) <* cfOf end lexeme = rule1 "lexeme" $ \ g -> g <* commentable (void $ string " " <+> string "\n\ \ ") (void $ comment_line (string "--")) (void $ comment_block (string "{-") (string "-}")) parens = rule1 "parens" $ between (lexeme $ char '(') (lexeme $ char ')') symbol = lexeme . string
+ Language.Symantic.Grammar.ContextFree: class (Gram_Char g, Gram_String g, Gram_Rule g, Gram_Alt g, Gram_App g, Gram_AltApp g, Gram_CF g) => Gram_Comment g
- Language.Symantic.Grammar.EBNF: class Gram_Rule g where rule _n = id rule1 _n g = g rule2 _n g = g rule3 _n g = g rule4 _n g = g
+ Language.Symantic.Grammar.EBNF: class Gram_Rule g
- Language.Symantic.Grammar.Meta: class (Gram_Reader (Source_Input src) g, SourceInj (Span (Source_Input src)) src) => Gram_Source src g where source g = askAfter $ askBefore $ (\ f (beg :: Source_Input src) (end :: Source_Input src) -> f (sourceInj $ Span beg end :: src)) <$> g
+ Language.Symantic.Grammar.Meta: class (Gram_Reader (Source_Input src) g, SourceInj (Span (Source_Input src)) src) => Gram_Source src g
- Language.Symantic.Grammar.Meta: class Gram_State st g where getBefore g = stateBefore ((\ f st -> (st, f st)) <$> g) getAfter g = stateAfter ((\ f st -> (st, f st)) <$> g) put g = stateAfter ((\ (st, a) -> const (st, a)) <$> g)
+ Language.Symantic.Grammar.Meta: class Gram_State st g
- Language.Symantic.Grammar.Operators: class (Gram_Terminal g, Gram_Rule g, Gram_Alt g, Gram_Try g, Gram_App g, Gram_AltApp g, Gram_CF g) => Gram_Op g where operators g prefixG infixG postfixG = (evalOpTree <$>) <$> go g prefixG infixG postfixG where go :: CF g a -> CF g (Unifix, a -> a) -> CF g (Infix, a -> a -> a) -> CF g (Unifix, a -> a) -> CF g (Either Error_Fixity (OpTree a)) go = rule4 "operators" $ \ aG preG inG postG -> (\ pres a posts -> let nod_a = foldr insertUnifix (foldl' (flip insertUnifix) (OpTree0 a) posts) pres in \case { Just (in_, b) -> insertInfix nod_a in_ b Nothing -> Right nod_a }) <$> many (try preG) <*> aG <*> many (try postG) <*> option Nothing (curry Just <$> try inG <*> go aG preG inG postG) infixrG = rule2 "infixr" $ \ g opG -> (\ a -> \case { Just (op, b) -> a `op` b Nothing -> a }) <$> g <*> option Nothing (try $ curry Just <$> opG <*> infixrG g opG) infixlG = rule2 "infixl" $ \ g opG -> ($ id) <$> go g opG where go :: CF g a -> CF g (a -> a -> a) -> CF g ((a -> a) -> a) go g opG = (\ a -> \case { Just (op, kb) -> \ k -> kb (k a `op`) Nothing -> ($ a) }) <$> g <*> option Nothing (try $ curry Just <$> opG <*> go g opG)
+ Language.Symantic.Grammar.Operators: class (Gram_Char g, Gram_String g, Gram_Rule g, Gram_Alt g, Gram_Try g, Gram_App g, Gram_AltApp g, Gram_CF g) => Gram_Op g
- Language.Symantic.Grammar.Regular: class Gram_Alt g where choice = foldr (<+>) empty
+ Language.Symantic.Grammar.Regular: class Gram_Alt g
- Language.Symantic.Grammar.Regular: class (Functor g, Gram_Alt g) => Gram_RegL g where manyL g' = reverse <$> go g' where go g = flip (:) <$> go g <*. g <+> empty someL g = (\ cs c -> cs ++ [c]) <$> manyL g <*. g
+ Language.Symantic.Grammar.Regular: class (Functor g, Gram_Alt g) => Gram_RegL g
- Language.Symantic.Grammar.Regular: class (Functor g, Gram_Alt g) => Gram_RegR g where manyR g = (:) <$> g .*> manyR g <+> empty someR g = (:) <$> g .*> manyR g
+ Language.Symantic.Grammar.Regular: class (Functor g, Gram_Alt g) => Gram_RegR g
- Language.Symantic.Grammar.Regular: type RegL = Reg SideL
+ Language.Symantic.Grammar.Regular: type RegL = Reg 'SideL
- Language.Symantic.Grammar.Regular: type RegR = Reg SideR
+ Language.Symantic.Grammar.Regular: type RegR = Reg 'SideR
- Language.Symantic.Grammar.Terminal: any :: Gram_Terminal g => g Char
+ Language.Symantic.Grammar.Terminal: any :: Gram_Char g => g Char
- Language.Symantic.Grammar.Terminal: but :: Gram_Terminal g => Terminal g Char -> Terminal g Char -> Terminal g Char
+ Language.Symantic.Grammar.Terminal: but :: Gram_Char g => Terminal g Char -> Terminal g Char -> Terminal g Char
- Language.Symantic.Grammar.Terminal: char :: Gram_Terminal g => Char -> g Char
+ Language.Symantic.Grammar.Terminal: char :: Gram_Char g => Char -> g Char
- Language.Symantic.Grammar.Terminal: eoi :: Gram_Terminal g => g ()
+ Language.Symantic.Grammar.Terminal: eoi :: Gram_Char g => g ()
- Language.Symantic.Grammar.Terminal: range :: Gram_Terminal g => (Char, Char) -> g Char
+ Language.Symantic.Grammar.Terminal: range :: Gram_Char g => (Char, Char) -> g Char
- Language.Symantic.Grammar.Terminal: string :: Gram_Terminal g => String -> g String
+ Language.Symantic.Grammar.Terminal: string :: Gram_String g => String -> g String
- Language.Symantic.Grammar.Terminal: unicat :: Gram_Terminal g => Unicat -> g Char
+ Language.Symantic.Grammar.Terminal: unicat :: Gram_Char g => Unicat -> g Char

Files

Language/Symantic/Grammar/ContextFree.hs view
@@ -17,7 +17,7 @@ -- * Type 'CF' -- | Context-free grammar. newtype CF g a = CF { unCF :: g a }- deriving (IsString, Functor, Gram_Terminal, Applicative, Gram_App)+ deriving (IsString, Functor, Gram_Char, Gram_String, Applicative, Gram_App) deriving instance Gram_Error err g => Gram_Error err (CF g) deriving instance Gram_Reader st g => Gram_Reader st (CF g) deriving instance Gram_State st g => Gram_State st (CF g)@@ -111,7 +111,8 @@ -- * Class 'Gram_Comment' -- | Symantics for handling comments after each 'lexeme'. class- ( Gram_Terminal g+ ( Gram_Char g+ , Gram_String g  , Gram_Rule g  , Gram_Alt g  , Gram_App g@@ -119,22 +120,22 @@  , Gram_CF g  ) => Gram_Comment g where 	commentable :: g () -> g () -> g () -> g ()-	commentable = rule3 "commentable" $ \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" $+	commentable = rule3 "Commentable" $ \sp line block ->+		manySkip $ choice [sp, line, block]+	commentLine :: CF g String -> CF g String+	commentLine prefix = rule "CommentLine" $+		prefix *> many (any `minus` (void eol <+> eoi))+	commentBlock :: CF g String -> Reg lr g String -> CF g String+	commentBlock begin end = rule "CommentBlock" $ 		begin *> many (any `minus` end) <* cfOf end 	lexeme :: CF g a -> CF g a-	lexeme = rule1 "lexeme" $ \g ->+	lexeme = rule1 "Lexeme" $ \g -> 		g <* commentable-		 (void $ string " " <+> string "\n ")-		 (void $ comment_line (string "--"))-		 (void $ comment_block (string "{-") (string "-}"))+		 (void $ space <+> (eol *> space))+		 (void $ commentLine (string "--"))+		 (void $ commentBlock (string "{-") (string "-}")) 	parens :: CF g a -> CF g a-	parens = rule1 "parens" $+	parens = rule1 "Parens" $ 		between 		 (lexeme $ char '(') 		 (lexeme $ char ')')@@ -147,8 +148,8 @@ gram_comment :: forall g. (Gram_Comment g, Gram_RuleEBNF g) => [CF g ()] gram_comment =  [ void $ commentable (void $ argEBNF "space") (void $ argEBNF "line") (void $ argEBNF "block")- , void $ comment_line (argEBNF "prefix")- , void $ comment_block (argEBNF "begin") (argEBNF "end" :: RegL g String)+ , void $ commentLine (argEBNF "prefix")+ , void $ commentBlock (argEBNF "begin") (argEBNF "end" :: RegL g String)  , void $ lexeme (argEBNF "g")  , void $ parens (argEBNF "g")  , void $ inside id (argEBNF "begin") (argEBNF "in") (argEBNF "end") (argEBNF "next")
Language/Symantic/Grammar/EBNF.hs view
@@ -1,10 +1,8 @@ module Language.Symantic.Grammar.EBNF where  import Control.Applicative (Applicative(..))-import Control.Monad-import Data.Semigroup hiding (option)+import Data.Semigroup import Data.Text (Text)-import Prelude hiding (any) import qualified Data.Text as Text  import Language.Symantic.Grammar.Meta
Language/Symantic/Grammar/Fixity.hs view
@@ -1,9 +1,8 @@ module Language.Symantic.Grammar.Fixity where  import Data.Bool as Bool-import Data.Semigroup hiding (option)+import Data.Semigroup import Data.String (IsString(..))-import Prelude hiding (any)  -- * Type 'Fixity' data Fixity
Language/Symantic/Grammar/Operators.hs view
@@ -4,8 +4,7 @@  import Control.Applicative (Applicative(..)) import Control.Monad (void)-import Data.Foldable hiding (any)-import Prelude hiding (any)+import Data.Foldable  import Language.Symantic.Grammar.Fixity import Language.Symantic.Grammar.EBNF@@ -16,7 +15,8 @@ -- * Class 'Gram_Op' -- | Symantics for operators. class- ( Gram_Terminal g+ ( Gram_Char g+ , Gram_String g  , Gram_Rule g  , Gram_Alt g  , Gram_Try g
Language/Symantic/Grammar/Regular.hs view
@@ -13,7 +13,7 @@ -- * Type 'Reg' -- | Left or right regular grammar. newtype Reg (lr::Side) g a = Reg { unReg :: g a }- deriving (IsString, Functor, Gram_Terminal)+ deriving (IsString, Functor, Gram_Char, Gram_String) deriving instance Gram_Alt g => Gram_Alt (Reg lr g) deriving instance Gram_Try g => Gram_Try (Reg lr g) deriving instance Gram_Rule g => Gram_Rule (Reg lr g)
Language/Symantic/Grammar/Terminal.hs view
@@ -2,14 +2,13 @@ -- | Symantics for terminal grammars. module Language.Symantic.Grammar.Terminal where -import Control.Monad import Data.Semigroup (Semigroup(..)) import Data.String (IsString(..))-import Prelude hiding (any) import qualified Data.Bool as Bool import qualified Data.Char as Char import qualified Data.List as List import qualified Data.Text as Text+import qualified Data.Text.Lazy as TL  import Language.Symantic.Grammar.Fixity import Language.Symantic.Grammar.EBNF@@ -18,51 +17,42 @@ -- | Terminal grammar. newtype Terminal g a  =      Terminal { unTerminal :: g a }- deriving (Functor, Gram_Terminal)+ deriving (Functor, Gram_Char, Gram_String) deriving instance Gram_Rule g => Gram_Rule (Terminal g) --- ** Class 'Gram_Terminal'+-- ** Class 'Gram_Char' -- | Symantics for terminal grammars.-class Gram_Terminal g where+class Gram_Rule g => Gram_Char g where 	any    :: g Char 	but    :: Terminal g Char -> Terminal g Char -> Terminal g Char 	eoi    :: g ()+	eol    :: g Char+	space  :: g Char 	char   :: Char -> g Char-	string :: String -> g String 	unicat :: Unicat -> g Char 	range  :: (Char, Char) -> g Char-	-- string = foldr (\c -> (<*>) ((:) <$> char c)) (pure "")-	-- string [] = pure []-	-- string (c:cs) = (:) <$> char c <*> string cs-deriving instance Gram_Terminal RuleEBNF-instance Gram_Terminal EBNF where+	eol   = rule "NewLine" $ char '\n'+	space = rule "Space" $ char ' '+deriving instance Gram_Char RuleEBNF+instance Gram_Char EBNF where 	any  = ebnf_const "_" 	Terminal (EBNF f) `but` Terminal (EBNF g) = 		Terminal $ EBNF $ \bo po -> parenInfix po op $ 			f bo (op, SideL) <> " - " <> g bo (op, SideR) 		where op = infixL 6-	eoi  = ebnf_const "eoi"-	char = ebnf_const . escape+	eoi   = ebnf_const "eoi"+	eol   = ebnf_const "↵"+	space = ebnf_const "␣"+	char  = ebnf_const . escape 		where 		escape c | Char.isPrint c && c /= '"' = Text.concat $ ["\"", Text.singleton c, "\""] 		escape c = Text.concat ["U+", Text.pack $ show $ Char.ord c]-	string s =-		case List.break (\c -> Bool.not (Char.isPrint c) || c == '"') s of-		 (ps, "")   -> raw ps-		 ("", [c])  -> "" <$ char c-		 (ps, [c])  -> "" <$ raw ps <* char c-		 ("", c:rs) -> "" <$ char c <* string rs-		 (ps, c:rs) -> "" <$ raw ps <* char c <* string rs-		where-		raw cs = ebnf_const $ Text.concat $ ["\"", Text.pack cs, "\""] 	unicat = ebnf_const . Text.pack . show 	range (l, h) = ebnf_const $ Text.concat 	 [ runEBNF $ char l 	 , "…" 	 , runEBNF $ char h 	 ]-instance IsString (EBNF String) where-	fromString = string  -- *** Type 'Unicat' -- | Unicode category.@@ -109,3 +99,29 @@ 		 , Char.OtherSymbol 		 ] 	 Unicat cat -> [cat]++-- ** Class 'Gram_String'+class Functor g => Gram_String g where+	string   :: String -> g String+	{-+	string = foldr (\c -> (<*>) ((:) <$> char c)) (pure "")+	string [] = pure []+	string (c:cs) = (:) <$> char c <*> string cs+	-}+	text     :: Text.Text -> g Text.Text+	textLazy :: TL.Text -> g TL.Text+	text t     = Text.pack <$> string (Text.unpack t)+	textLazy t = TL.pack   <$> string (TL.unpack t)+deriving instance Gram_String RuleEBNF+instance Gram_String EBNF where+	string s =+		case List.break (\c -> Bool.not (Char.isPrint c) || c == '"') s of+		 (ps, "")   -> raw ps+		 ("", [c])  -> "" <$ char c+		 (ps, [c])  -> "" <$ raw ps <* char c+		 ("", c:rs) -> "" <$ char c <* string rs+		 (ps, c:rs) -> "" <$ raw ps <* char c <* string rs+		where+		raw cs = ebnf_const $ Text.concat $ ["\"", Text.pack cs, "\""]+instance IsString (EBNF String) where+	fromString = string
− Language/Symantic/Grammar/Test.hs
@@ -1,113 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Test where--import Test.Tasty-import Test.Tasty.HUnit--import Control.Applicative (Applicative(..))-import Control.Monad-import Data.Semigroup ((<>))-import Data.String (IsString(..))-import Prelude hiding (any, (^), exp)-import qualified Control.Applicative as Gram_AltApp-import qualified Data.Char as Char-import qualified Data.Text as Text-import qualified Text.Megaparsec as P--import Language.Symantic.Grammar---- * Type 'ParsecT'-type ParsecC e s = (P.Token s ~ Char, P.Stream s, P.ErrorComponent e)-instance ParsecC e s => IsString (P.ParsecT e s m [Char]) where-	fromString = P.string-instance ParsecC e s => Gram_Rule (P.ParsecT e s m) where-	rule = P.label . Text.unpack-instance ParsecC e s => Gram_Terminal (P.ParsecT e s m) where-	any          = P.anyChar-	eoi          = P.eof-	char         = P.char-	string       = P.string-	unicat cat   = P.satisfy $ (`elem` cats) . Char.generalCategory-		where cats = unicode_categories cat-	range (l, h) = P.satisfy $ \c -> l <= c && c <= h-	but (Terminal f) (Terminal p) = Terminal $ P.notFollowedBy (P.try p) *> f-instance ParsecC e s => Gram_Alt (P.ParsecT e s m) where-	empty  = Gram_AltApp.empty-	(<+>)  = (Gram_AltApp.<|>)-	choice = P.choice-instance ParsecC e s => Gram_Try (P.ParsecT e s m) where-	try = P.try-instance ParsecC e s => Gram_RegR (P.ParsecT e s m) where-	Terminal f .*> Reg x = Reg $ f <*> x-instance ParsecC e s => Gram_RegL (P.ParsecT e s m) where-	Reg f <*. Terminal x = Reg $ f <*> x-instance ParsecC e s => Gram_App (P.ParsecT e s m)-instance ParsecC e s => Gram_AltApp (P.ParsecT e s m)-instance ParsecC e s => Gram_CF (P.ParsecT e s m) where-	CF f <& Reg p      = CF $ P.lookAhead f <*> p-	Reg f &> CF p      = CF $ P.lookAhead f <*> p-	CF f `minus` Reg p = CF $ P.notFollowedBy (P.try p) *> f-instance ParsecC e s => Gram_Comment (P.ParsecT e s m)--elide :: Text.Text -> String-elide s | Text.length s > 42 = take 42 (Text.unpack s) <> ['…']-elide s = Text.unpack s--tests :: TestTree-tests = testGroup "Grammar"- [ testGroup "Terminal" $-	let (==>) inp exp =-		testCase (elide exp) $-		runEBNF (unTerminal (void inp)) @?= exp-		; infix 1 ==> in-	 [ string "" ==> "\"\""-	 , string "abé\"to" ==> "\"abé\", U+34, \"to\""-	 , string "\"" ==> "U+34"-	 , range ('a', 'z') ==> "\"a\"…\"z\""-	 , unicat Unicat_Letter ==> "Unicat_Letter"-	 , unicat (Unicat Char.LowercaseLetter) ==> "Unicat LowercaseLetter"-	 ]- , testGroup "Reg" $-	let (==>) inp exp =-		testCase (elide exp) $-		runEBNF (unReg (void inp)) @?= exp-		; infix 1 ==> in-	 [ (<>) <$> string "0" .*> someR (char '1') ==> "\"0\", {\"1\"}-"-	 , (<>) <$> someL (char '1') <*. string "0" ==> "{\"1\"}-, \"0\""-	 ]- , testGroup "CF" $-	let (==>) inp exp =-		testCase (elide exp) $-		runEBNF (unCF (void inp)) @?= exp-		; infix 1 ==> in-	 [ (<>) <$> string "0" <*> string "1" ==> "\"0\", \"1\""-	 , (<>) <$> string "0" <* string "X" <*> string "1" ==> "\"0\", \"X\", \"1\""-	 , (<>) <$> (string "0" <+> string "1") <*> string "2" ==> "(\"0\" | \"1\"), \"2\""-	 , (<>) <$> string "0" <*> (string "1" <+> string "2") ==> "\"0\", (\"1\" | \"2\")"-	 , string "0" <+> string "1" <+> string "2" ==> "\"0\" | \"1\" | \"2\""-	 , choice [string "0", string "1", string "2"] ==> "\"0\" | \"1\" | \"2\""-	 , (<>) <$> choice-		 [ (<>) <$> string "0" <*> string "1"-		 , string "2" <+> string "3"-		 , string "4"-		 ] <*> string "5" ==> "(\"0\", \"1\" | \"2\" | \"3\" | \"4\"), \"5\""-	 , concat <$> many (string "0") ==> "{\"0\"}"-	 , () <$ char 'a' <* char 'b' <* char 'c' ==> "\"a\", \"b\", \"c\""-	 ,let g0 = (<>) <$> string "0" .*> someR (char '1') in-		(<>) <$> string "0" <& g0 ==> "\"0\" & \"0\", {\"1\"}-"-	 ,let g0 = (<>) <$> string "0" .*> someR (char '1') in-		let g1 = (<>) <$> someL (char '1') <*. string "0" in-		string "0" `minus` g0 `minus` g1 ==>-		"\"0\" - \"0\", {\"1\"}- - {\"1\"}-, \"0\""-	 , (<>)-		 <$> many (string "0" <+> string "1")-		 <*> some (string "2") ==> "{\"0\" | \"1\"}, {\"2\"}-"-	 ]- ]--main :: IO ()-main =-	defaultMain $-	testGroup "Language.Symantic"-	 [tests]
+ stack.yaml view
@@ -0,0 +1,3 @@+resolver: lts-10.5+packages:+- '.'
symantic-grammar.cabal view
@@ -1,50 +1,36 @@-author: Julien Moutinho <julm+symantic@autogeree.net>+name: symantic-grammar+-- PVP:  +-+------- breaking API changes+--       | | +----- non-breaking API additions+--       | | | +--- code changes with no API change+version: 0.3.0.20180213+category: Language+synopsis: Library for symantic grammars.+description: This library defines an embedded DSL for regular or context-free grammars,+             in the <http://okmij.org/ftp/tagless-final/ Tagless-Final> way (aka. the /symantic/ way).+             .+             See @Test.hs@ or source code of <https://hackage.haskell.org/package/symantic symantic>+             and <https://hackage.haskell.org/package/symantic-lib symantic-lib> for examples of use.+extra-doc-files:+license: GPL-3+license-file: COPYING+stability: experimental+author:      Julien Moutinho <julm+symantic@autogeree.net>+maintainer:  Julien Moutinho <julm+symantic@autogeree.net> bug-reports: Julien Moutinho <julm+symantic@autogeree.net>+-- homepage:+ build-type: Simple cabal-version: >= 1.24-category: Language-description:-  This library defines an embedded DSL for regular or context-free grammars,-  in the <http://okmij.org/ftp/tagless-final/ Tagless-Final> way (aka. the /symantic/ way).-  .-  See @Test.hs@ or source code of <https://hackage.haskell.org/package/symantic symantic>-  and <https://hackage.haskell.org/package/symantic-lib symantic-lib> for examples of use.+tested-with: GHC==8.2.2 extra-source-files:+  stack.yaml extra-tmp-files:--- homepage: -license: GPL-3-license-file: COPYING-maintainer: Julien Moutinho <julm+symantic@autogeree.net>-name: symantic-grammar-stability: experimental-synopsis: Library for symantic grammars.-tested-with: GHC==8.0.2--- PVP:  +-+------- breaking API changes---       | | +----- non-breaking API additions---       | | | +--- code changes with no API change-version: 0.2.0.20170709  Source-Repository head   location: git://git.autogeree.net/symantic   type:     git  Library-  default-extensions:-    DataKinds-    FlexibleContexts-    FlexibleInstances-    GeneralizedNewtypeDeriving-    KindSignatures-    LambdaCase-    MultiParamTypeClasses-    OverloadedStrings-    ScopedTypeVariables-    StandaloneDeriving-  ghc-options: -Wall-               -fwarn-incomplete-patterns-               -fno-warn-tabs-               -fprint-explicit-kinds-  default-language: Haskell2010   exposed-modules:     Language.Symantic.Grammar     Language.Symantic.Grammar.BinTree@@ -57,12 +43,35 @@     Language.Symantic.Grammar.Terminal     Language.Symantic.Grammar.Source     Language.Symantic.Grammar.Error+  default-language: Haskell2010+  default-extensions:+    DataKinds+    FlexibleContexts+    FlexibleInstances+    GeneralizedNewtypeDeriving+    KindSignatures+    LambdaCase+    MultiParamTypeClasses+    OverloadedStrings+    ScopedTypeVariables+    StandaloneDeriving+  ghc-options:+    -Wall+    -Wincomplete-uni-patterns+    -Wincomplete-record-updates+    -fno-warn-tabs+    -fhide-source-paths   build-depends:-    base >= 4.6 && < 5-    , text+      base >= 4.6 && < 5+    , text >= 1.2  Test-Suite symantic-grammar-test   type: exitcode-stdio-1.0+  hs-source-dirs: test+  main-is: Main.hs+  other-modules:+    HUnit+  default-language: Haskell2010   default-extensions:     FlexibleContexts     FlexibleInstances@@ -70,18 +79,17 @@     OverloadedStrings     ScopedTypeVariables     TypeFamilies-  default-language: Haskell2010-  ghc-options: -Wall-               -fno-warn-tabs-               -main-is Test-  hs-source-dirs: Language/Symantic-  main-is: Grammar/Test.hs-  other-modules:+  ghc-options:+    -Wall+    -Wincomplete-uni-patterns+    -Wincomplete-record-updates+    -fno-warn-tabs+    -fhide-source-paths   build-depends:-    base >= 4.6 && < 5-    , megaparsec-    , symantic-grammar-    , tasty >= 0.11-    , tasty-hunit-    , text-    , transformers+      symantic-grammar+    , base         >= 4.6 && < 5+    , megaparsec   >= 6.3+    , tasty        >= 0.11+    , tasty-hunit  >= 0.9+    , text         >= 1.2+    , transformers >= 0.5
+ test/HUnit.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE ConstraintKinds #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module HUnit where++import Test.Tasty+import Test.Tasty.HUnit++import Control.Applicative (Applicative(..))+import Control.Monad+import Data.Semigroup ((<>))+import Data.String (IsString(..))+import qualified Control.Applicative as Applicative+import qualified Data.Char as Char+import qualified Data.Text as Text+import qualified Text.Megaparsec as P+import qualified Text.Megaparsec.Char as P++import Language.Symantic.Grammar++-- * Type 'ParsecT'+type ParsecC e s = (P.Token s ~ Char, P.Stream s, Ord e)+instance (ParsecC e s, Gram_String (P.ParsecT e s m)) => IsString (P.ParsecT e s m String) where+	fromString = string+instance ParsecC e s => Gram_Rule (P.ParsecT e s m) where+	rule = P.label . Text.unpack+instance ParsecC e s => Gram_Char (P.ParsecT e s m) where+	any          = P.anyChar+	eoi          = P.eof+	char         = P.char+	unicat cat   = P.satisfy $ (`elem` cats) . Char.generalCategory+		where cats = unicode_categories cat+	range (l, h) = P.satisfy $ \c -> l <= c && c <= h+	but (Terminal f) (Terminal p) = Terminal $ P.notFollowedBy (P.try p) *> f+instance ParsecC e String => Gram_String (P.ParsecT e String m) where+	string = P.string+instance ParsecC e s => Gram_Alt (P.ParsecT e s m) where+	empty  = Applicative.empty+	(<+>)  = (Applicative.<|>)+	choice = P.choice+instance ParsecC e s => Gram_Try (P.ParsecT e s m) where+	try = P.try+instance ParsecC e s => Gram_RegR (P.ParsecT e s m) where+	Terminal f .*> Reg x = Reg $ f <*> x+instance ParsecC e s => Gram_RegL (P.ParsecT e s m) where+	Reg f <*. Terminal x = Reg $ f <*> x+instance ParsecC e s => Gram_App (P.ParsecT e s m)+instance ParsecC e s => Gram_AltApp (P.ParsecT e s m)+instance ParsecC e s => Gram_CF (P.ParsecT e s m) where+	CF f <& Reg p      = CF $ P.lookAhead f <*> p+	Reg f &> CF p      = CF $ P.lookAhead f <*> p+	CF f `minus` Reg p = CF $ P.notFollowedBy (P.try p) *> f+instance ParsecC e String => Gram_Comment (P.ParsecT e String m)++elide :: Text.Text -> String+elide s | Text.length s > 42 = take 42 (Text.unpack s) <> ['…']+elide s = Text.unpack s++hunits :: TestTree+hunits = testGroup "Grammar"+ [ testGroup "Terminal" $+	let (==>) input expected =+		testCase (elide expected) $+		runEBNF (unTerminal (void input)) @?= expected+		; infix 1 ==> in+	 [ string "" ==> "\"\""+	 , string "abé\"to" ==> "\"abé\", U+34, \"to\""+	 , string "\"" ==> "U+34"+	 , range ('a', 'z') ==> "\"a\"…\"z\""+	 , unicat Unicat_Letter ==> "Unicat_Letter"+	 , unicat (Unicat Char.LowercaseLetter) ==> "Unicat LowercaseLetter"+	 ]+ , testGroup "Reg" $+	let (==>) input expected =+		testCase (elide expected) $+		runEBNF (unReg (void input)) @?= expected+		; infix 1 ==> in+	 [ (<>) <$> string "0" .*> someR (char '1') ==> "\"0\", {\"1\"}-"+	 , (<>) <$> someL (char '1') <*. string "0" ==> "{\"1\"}-, \"0\""+	 ]+ , testGroup "CF" $+	let (==>) input expected =+		testCase (elide expected) $+		runEBNF (unCF (void input)) @?= expected+		; infix 1 ==> in+	 [ (<>) <$> string "0" <*> string "1" ==> "\"0\", \"1\""+	 , (<>) <$> string "0" <* string "X" <*> string "1" ==> "\"0\", \"X\", \"1\""+	 , (<>) <$> (string "0" <+> string "1") <*> string "2" ==> "(\"0\" | \"1\"), \"2\""+	 , (<>) <$> string "0" <*> (string "1" <+> string "2") ==> "\"0\", (\"1\" | \"2\")"+	 , string "0" <+> string "1" <+> string "2" ==> "\"0\" | \"1\" | \"2\""+	 , choice [string "0", string "1", string "2"] ==> "\"0\" | \"1\" | \"2\""+	 , (<>) <$> choice+		 [ (<>) <$> string "0" <*> string "1"+		 , string "2" <+> string "3"+		 , string "4"+		 ] <*> string "5" ==> "(\"0\", \"1\" | \"2\" | \"3\" | \"4\"), \"5\""+	 , concat <$> many (string "0") ==> "{\"0\"}"+	 , () <$ char 'a' <* char 'b' <* char 'c' ==> "\"a\", \"b\", \"c\""+	 ,let g0 = (<>) <$> string "0" .*> someR (char '1') in+		(<>) <$> string "0" <& g0 ==> "\"0\" & \"0\", {\"1\"}-"+	 ,let g0 = (<>) <$> string "0" .*> someR (char '1') in+		let g1 = (<>) <$> someL (char '1') <*. string "0" in+		string "0" `minus` g0 `minus` g1 ==>+		"\"0\" - \"0\", {\"1\"}- - {\"1\"}-, \"0\""+	 , (<>)+		 <$> many (string "0" <+> string "1")+		 <*> some (string "2") ==> "{\"0\" | \"1\"}, {\"2\"}-"+	 ]+ ]
+ test/Main.hs view
@@ -0,0 +1,10 @@+module Main where++import Test.Tasty+import HUnit++main :: IO ()+main =+	defaultMain $+	testGroup "Language.Symantic"+	 [hunits]