gll 0.4.0.11 → 0.4.0.12
raw patch · 6 files changed
+391/−18 lines, 6 files
Files
- changelog.txt +6/−0
- gll.cabal +2/−1
- src/GLL/Combinators/BinaryInterface.hs +2/−2
- src/GLL/Combinators/Interface.hs +52/−14
- src/GLL/Combinators/Test/BinaryInterface.hs +328/−0
- src/GLL/Combinators/Test/Interface.hs +1/−1
changelog.txt view
@@ -62,3 +62,9 @@ 0.4.0.10 -> 0.4.0.11 + integer literals are now by default considered as natural numbers only, the 'signed_int_lits' flag of 'LexerSettings' can be used to turn on signed integers, restoring the behaviour of previous versions++0.4.0.11 -> 0.4.0.12+ + export 'grammarOf'+ + let 'parse' throw errors by default+ + changed priorities of operator tables to doubles + + removed need to specify associativity of prefix operators in operator table
gll.cabal view
@@ -3,7 +3,7 @@ -- The name of the package. name: gll-version: 0.4.0.11+version: 0.4.0.12 synopsis: GLL parser with simple combinator interface license: BSD3 license-file: LICENSE@@ -53,6 +53,7 @@ , GLL.Combinators.BinaryInterface , GLL.Combinators , GLL.Combinators.Test.Interface+ , GLL.Combinators.Test.BinaryInterface , GLL.Combinators.Options , GLL.Combinators.Memoisation , GLL.Combinators.Lexer
src/GLL/Combinators/BinaryInterface.hs view
@@ -27,9 +27,9 @@ -- ** Parseable token types Token(..), Parseable(..), SubsumesToken(..), unlexTokens, unlexToken, -- * Running a parser - parse, printParseData, evaluatorWithParseData,+ grammarOf, parse, printParseData, evaluatorWithParseData, -- ** Running a parser with options- parseWithOptions, parseWithParseOptions, printParseDataWithOptions, evaluatorWithParseDataAndOptions,printGrammarData,+ parseWithOptions, parseWithParseOptions, printEvalDataWithOptions, printParseDataWithOptions, evaluatorWithParseDataAndOptions,printGrammarData, -- *** Possible options CombinatorOptions, CombinatorOption, GLL.Combinators.Options.maximumErrors, throwErrors,
src/GLL/Combinators/Interface.hs view
@@ -200,9 +200,9 @@ -- ** Parseable token types Token(..), Parseable(..), SubsumesToken(..), unlexTokens, unlexToken, -- * Running a parser - parse, printParseData, evaluatorWithParseData,+ grammarOf, parse, printParseData, evaluatorWithParseData, -- ** Running a parser with options- parseWithOptions, parseWithParseOptions, printParseDataWithOptions, evaluatorWithParseDataAndOptions, printGrammarData,+ parseWithOptions, parseWithParseOptions, printEvalDataWithOptions, printParseDataWithOptions, evaluatorWithParseDataAndOptions, printGrammarData, -- *** Possible options CombinatorOptions, CombinatorOption, GLL.Combinators.Options.maximumErrors, throwErrors, @@ -228,7 +228,7 @@ multipleSepBy2, within, parens, braces, brackets, angles, foldr_multiple, foldr_multipleSepBy, -- *** Operator expressions- fromOpTable, OpTable, Assoc(..), Fixity(..),+ fromOpTable, opTableFromList, OpTable, Assoc(..), Fixity(..), -- *** Disambiguation (<:=), (<::=),(<<<**>), (<**>>>), (<<**>), (<<<**), (**>>>), (<**>>), longest_match,shortest_match,@@ -319,6 +319,41 @@ putStrLn $ "semantic phase: " ++ show (diffUTCTime endTime startTime')-} putStrLn $ "total time: " ++ show (diffUTCTime endTime startTime) +-- | Variant of 'printParseData' which can be controlled by 'ParseOption's+printEvalDataWithOptions :: (Parseable t, IsSymbExpr s, Show a) => ParseOptions -> CombinatorOptions -> s t a -> [t] -> IO ()+printEvalDataWithOptions popts opts p' input = + let SymbExpr (Nt start,vpa2,vpa3) = mkRule ("__Start" <:=> OO [id <$$> p'])+ rules = vpa2 M.empty+ grammar = (start, [ p | (_, alts) <- M.assocs rules, p <- alts ])+ parse_res = GLL.parseWithOptions (popts ++ [packedNodesOnly,strictBinarisation]) grammar input+ arr = mkInput input + (_,m) = A.bounds arr+ in do let (_,prods) = grammar+ nt_set = S.fromList [ x | Prod x _ <- prods ]+ putStrLn $ "#production: " ++ show (length prods)+ putStrLn $ "#nonterminals: " ++ show (length nt_set)+ putStrLn $ "largest nonterminal: " ++ show ( + foldr (\x -> max (Data.Text.length x)) 0 nt_set)++ startTime <- getCurrentTime+ putStrLn $ "#tokens: " ++ (show m)+ putStrLn $ "#successes: " ++ (show $ res_successes parse_res)+ endTime <- getCurrentTime+ putStrLn $ "recognition time: " ++ show (diffUTCTime endTime startTime)+ startTime' <- getCurrentTime+ putStrLn $ "#descriptors " ++ (show $ nr_descriptors parse_res)+ putStrLn $ "#EPNs " ++ (show $ nr_packed_node_attempts parse_res) + endTime <- getCurrentTime+ putStrLn $ "parse-data time: " ++ show (diffUTCTime endTime startTime')+ startTime' <- getCurrentTime+ as <- vpa3 (runOptions opts) emptyAncestors (sppf_result parse_res) arr 0 m+ putStrLn $ "ambiguous?: " ++ show (length as > 1)+ when (not (null as)) (writeFile "/tmp/derivation" (show (head as)))+ endTime <- getCurrentTime+ putStrLn $ "semantic phase: " ++ show (diffUTCTime endTime startTime')+ putStrLn $ "total time: " ++ show (diffUTCTime endTime startTime)++ -- | Print some information evaluatorWithParseData :: (Parseable t, IsSymbExpr s, Show a) => s t a -> [t] -> [a] evaluatorWithParseData = evaluatorWithParseDataAndOptions [] [] @@ -358,9 +393,9 @@ putStrLn $ "total time: " ++ show (diffUTCTime endTime startTime) return as --- | The grammar of a given parser.-grammar :: (Show t, Parseable t, IsSymbExpr s) => s t a -> Grammar t-grammar p = (\(f,_,_) -> f) (parse' defaultPOpts defaultOptions p [])+-- | The grammar of a given symbol expression.+grammarOf :: (Show t, Parseable t, IsSymbExpr s) => s t a -> Grammar t+grammarOf p = (\(f,_,_) -> f) (parse' defaultPOpts defaultOptions p []) -- | Print some information about the grammar constructed by a 'IsSymbExpr'. -- useful for debugging purposes@@ -370,14 +405,14 @@ putStrLn $ "nonterminals: " ++ show (length nt_set) putStrLn $ "largest nonterminal: " ++ show ( foldr (\x -> max (Data.Text.length x)) 0 nt_set)- where (_,prods) = grammar p+ where (_,prods) = grammarOf p nt_set = S.fromList [ x | Prod x _ <- prods ] -- | -- Runs a parser given a string of 'Parseable's and returns a list of -- semantic results, corresponding to all finitely many derivations. parse :: (Show t, Parseable t, IsSymbExpr s) => s t a -> [t] -> [a]-parse = parseWithOptions [] +parse = parseWithOptions [throwErrors] -- | -- Run the parser with some 'CombinatorOptions'.@@ -848,20 +883,23 @@ -- | A table mapping operator keywords to a 'Fixity' and 'Assoc' -- It provides a convenient way to build an expression grammar (see 'fromOpTable'). -type OpTable e = IM.IntMap [(String, Fixity e, Assoc)] +type OpTable e = M.Map Double [(String, Fixity e)] +data Fixity e = Prefix (String -> e -> e) | Infix (e -> String -> e -> e) Assoc data Assoc = LAssoc | RAssoc | NA-data Fixity e = Prefix (String -> e -> e) | Infix (e -> String -> e -> e) +opTableFromList :: [(Double, [(String, Fixity e)])] -> OpTable e +opTableFromList = M.fromList+ fromOpTable :: (SubsumesToken t, Parseable t, IsSymbExpr s) => String -> OpTable e -> s t e -> BNF t e fromOpTable nt ops rec = chooses_prec (nt ++ "-infix-prefix-exprs") $ [ mkNterm ix row- | (ix, row) <- zip [1..] (IM.elems ops)+ | (ix, row) <- zip [1..] (M.elems ops) ] where mkNterm ix ops = chooses (ntName ix) $ - [ mkAlt op fix assoc | (op, fix, assoc) <- ops ]- where mkAlt op fix assoc = case fix of+ [ mkAlt op fix | (op, fix) <- ops ]+ where mkAlt op fix = case fix of Prefix f -> f <$$> keyword op <**> rec - Infix f -> case assoc of + Infix f assoc -> case assoc of LAssoc -> f <$$> rec <**> keyword op <**>>> rec RAssoc -> f <$$> rec <**> keyword op <<<**> rec _ -> f <$$> rec <**> keyword op <**> rec
+ src/GLL/Combinators/Test/BinaryInterface.hs view
@@ -0,0 +1,328 @@+{-| This model contains unit-tests for 'GLL.Combinators.Interface'.++= Included examples++ * Elementary parsers+ * Sequencing+ * Alternatives+ * Simple binding+ * Binding with alternatives+ * Recursion (non-left)++ * Higher-order patterns:++ * Optional+ * Kleene-closure / positive closure+ * Seperator+ * Inline choice++ * Ambiguities:++ * "aaa"+ * longambig+ * aho_s+ * EEE++ * Left recursion+ * Hidden left-recursion+-}+module GLL.Combinators.Test.BinaryInterface where++import Control.Monad+import Data.Char (ord)+import Data.List (sort, nub)+import Data.IORef++import GLL.Combinators.BinaryInterface+import GLL.Parseable.Char ()++-- | Defines and executes multiple1 unit-tests +main = do+ count <- newIORef 1+ let test mref name p arg_pairs = do+ i <- readIORef count+ modifyIORef count succ+ subcount <- newIORef 'a'+ putStrLn (">> testing " ++ show i ++ " (" ++ name ++ ")")+ forM_ arg_pairs $ \(str,res) -> do+ case mref of -- empty memtable between parses+ Nothing -> return ()+ Just ref -> memClear ref + j <- readIORef subcount+ modifyIORef subcount succ+ let parse_res = parseWithParseOptions [noSelectTest] [useMemoisation] p str+ norm = take 100 . sort . nub+ norm_p_res = norm parse_res+ b = norm_p_res == norm res+ putStrLn (" >> " ++ [j,')',' '] ++ show b)+ unless b (putStrLn (" >> " ++ show norm_p_res))++ -- Elementary parsers+ test Nothing "eps1" (satisfy 0) [("", [0])]+ test Nothing "eps2" (satisfy 0) [("", [0]), ("111", [])]+ test Nothing "single" (char 'a') [("a", ['a'])+ ,("abc", [])]+ test Nothing "semfun1" (1 <$$ char 'a') [("a", [1])]++ -- Elementary combinators+ test Nothing "<**>" ((\b -> ['1',b]) <$$ char 'a' <**> char 'b')+ [("ab", ["1b"])+ ,("b", [])]+ + -- Alternation+ test Nothing "<||>" (ord <$$ char 'a' <**> char 'b' <||> ord <$$> char 'c')+ [("a", []), ("ab", [98]), ("c", [99]), ("cab", [])]++ -- Simple binding+ let pX = "X" <:=> ord <$$> char 'a' <** char 'b'+ test Nothing "<:=>" pX [("ab",[97]),("a",[])]++ -- Simple binding+ let pX = "X" <::=> ord <$$> char 'a' <** char 'b'+ test Nothing "<::=>" pX [("ab",[97]),("a",[])]++ let pX = "X" <:=> flip (:) <$$> pY <**> char 'a'+ pY = "Y" <:=> (\x y -> [x,y]) <$$> char 'b' <**> char 'c'+ test Nothing "<::=> 2" pX [("bca", ["abc"]), ("cba", [])]++ -- Binding with alternatives+ let pX = "X" <::=> pY <** char 'c'+ pY = "Y" <::=> char 'a' <||> char 'b'+ test Nothing "<::=> <||>" pX [("ac", "a"), ("bc", "b")]++ -- (Right) Recursion+ let pX = "X" <::=> (+1) <$$ char 'a' <**> pX <||> satisfy 0 + test Nothing "rec1" pX [("", [0]), ("aa",[2]), (replicate 42 'a', [42]), ("bbb", [])]++ -- EBNF+ let pX = "X" <::=> id <$$ char 'a' <** char 'b' <**> optional (char 'z')+ test Nothing "optional" pX [("abz", [Just 'z']), ("abab", []), ("ab", [Nothing])]++ let pX = "X" <::=> (char 'a' <||> char 'b')+ test Nothing "<||> optional" (pX <** optional (char 'z'))+ [("az", "a"), ("bz", "b"), ("z", []), ("b", "b"), ("a", "a")]++ let pX = "X" <::=> (1 <$$ optional (char 'a') <||> 2 <$$ optional (char 'b'))+ test Nothing "optional-ambig" (pX <** optional (char 'z'))+ [("az", [1]), ("bz", [2]), ("z", [1,2]), ("b", [2]), ("a", [1])]++ let pX = "X" <::=> id <$$ char 'a' <**> (char 'b' <||> char 'c')+ test Nothing "inline choice (1)" pX+ [("ab", "b"), ("ac", "c"), ("a", []), ("b", [])]++ let pX = "X" <::=> length <$$> multiple (char '1')+ test Nothing "multiple" pX [("", [0]), ("11", [2]), (replicate 12 '1', [12])]++ let pX = "X" <::=> length <$$> multiple1 (char '1')+ test Nothing "multiple1" pX [("", []), ("11", [2]), (replicate 12 '1', [12])]++ let pX = "X" <::=> 1 <$$ multiple (char 'a') <||> 2 <$$ multiple (char 'b')+ test Nothing "(multiple <||> multiple) <**> optional" (pX <** optional (char 'z'))+ [("az", [1]), ("bz", [2]), ("z", [1,2])+ ,("", [1,2]), ("b", [2]), ("a", [1])]++ let pX = "X" <::=> pY <** optional (char 'z')+ where pY = "Y" <::=> length <$$> multiple (char 'a')+ <||> length <$$> multiple1 (char 'b') <** char 'e'+ test Nothing "multiple & multiple1 & optional" + pX [("aaaz", [3]), ("bbbez", [3]), ("ez", []), ("z", [0])+ ,("aa", [2]), ("bbe", [2]) + ]++ -- multiple with nullable argument+ let pX = 1 <$$ char '1' <||> satisfy 0+ test Nothing "multiple (nullable arg)" + (multiple pX) [("11", [[1,1]]), ("",[[]]), ("e", [])]++ -- Simple ambiguities+ let pX = (++) <$$> pA <**> pB+ pA = "a" <$$ char 'a' <||> "aa" <$$ char 'a' <** char 'a'+ pB = "b" <$$ char 'a' <||> "bb" <$$ char 'a' <** char 'a' + test Nothing "aaa" pX [("aaa", ["aab", "abb"])+ ,("aa", ["ab"])]++ let pX = (\x y -> [x,y]) <$$ char 'a' <**> pL <**> pL <** char 'e'+ pL = 1 <$$ char 'b'+ <||> 2 <$$ char 'b' <** char 'c'+ <||> 3 <$$ char 'c' <** char 'd'+ <||> 4 <$$ char 'd'+ test Nothing "longambig" pX [("abcde", [[1,3],[2,4]]), ("abcdd", [])]++ let pX = "X" <::=> (1 <$$ multiple1 (char 'a') <||> 2 <$$ multiple (char 'b'))+ pY = "Y" <::=> (+) <$$> pX <**> pY+ <||> satisfy 0+ test Nothing "multiple1 & multiple & recursion + ambiguities" pY+ [("ab", [3]),("aa", [1,2]), (replicate 10 'a', [1..10])]++ let pX = "X" <::=> 1 <$$ char 'a' <||> satisfy 0+ pY = "Y" <::=> (+) <$$> pX <**> pY+ -- shouldn't this be 1 + infinite 0's?+ test Nothing "no parse infinite rec?" pY + [("a", [])]++ let pS = "S" <::=> ((\x y -> x+y+1) <$$ char '1' <**> pS <**> pS) <||> satisfy 0 + test Nothing "aho_S" pS [("", [0]), ("1", [1]), (replicate 5 '1', [5])]+++ let pS = "S" <::=> ((\x y -> '1':x++y) <$$ char '1' <**> pS <**> pS) <||> satisfy "0"+ test Nothing "aho_S" pS [("", ["0"]), ("1", ["100"]), ("11", ["10100", "11000"])+ ,(replicate 5 '1', aho_S_5)]++ let pE = "E" <::=> (\x y z -> x+y+z) <$$> pE <**> pE <**> pE + <||> 1 <$$ char '1'+ <||> satisfy 0+ test Nothing "EEE" pE [("", [0]), ("1", [1]), ("11", [2])+ ,(replicate 5 '1', [5]), ("112", [])]++ let pE = "E" <::=> (\x y z -> x++y++z) <$$> pE <**> pE <**> pE + <||> "1" <$$ char '1'+ <||> satisfy "0"+ test Nothing "EEE ambig" pE [("", ["0"]), ("1", ["1"])+ ,("11", ["110", "011", "101"]), ("111", _EEE_3)]++ let pX = "X" <::=> maybe 0 (const 1) <$$> optional (char 'z') + <||> (+1) <$$> pX <** char '1'+ test Nothing "simple left-recursion" pX [("", [0]), ("z11", [3]), ("z", [1])+ ,(replicate 100 '1', [100])]++ let pX = "X" <::=> satisfy 0 + <||> (+1) <$$ pB <**> pX <** char '1'+ pB = maybe 0 (const 0) <$$> optional (char 'z')+ test Nothing "hidden left-recursion" pX + [("", [0]), ("zz11", [2]), ("z11", [2]), ("11", [2])+ ,(replicate 100 '1', [100])]++ let pX = "X" <::=> (+) <$$> pY <**> pA+ pA = 1 <$$ char 'a' <** char 'b' <||> satisfy 0+ pY = "Y" <::=> satisfy 0 <||> pX + test Nothing "hidden left-recursion + infinite derivations" pX+ [("", [0]), ("ab", [1]), ("ababab", [3])]++ putStrLn "Tests that use memoisation"++ let tab = newMemoTable+ pX = "X" <::=> (1 <$$ multiple1 (char 'a') <||> 2 <$$ multiple (char 'b'))+ pY = memo tab ("Y" <::=> (+) <$$> pX <**> pY+ <||> satisfy 0)+ test (Just tab) "multiple1 & multiple & recursion + ambiguities" pY+ [("ab", [3]),("aa", [1,2]), (replicate 10 'a', [1..10])]++ let tab = newMemoTable + pX = "X" <::=> 1 <$$ char 'a' <||> satisfy 0+ pY = memo tab ("Y" <::=> (+) <$$> pX <**> pY)+ -- shouldn't this be 1 + infinite 0's?+ test (Just tab) "no parse infinite rec?" pY + [("a", [])]++ -- Higher ambiguities+ let tab = newMemoTable+ pE = memo tab ("E" <::=> (\x y z -> x+y+z) <$$> pE <**> pE <**> pE + <||> 1 <$$ char '1'+ <||> satisfy 0)+ test (Just tab) "EEE" pE [("", [0]), ("1", [1]), ("11", [2])+ ,(replicate 5 '1', [5]), ("112", [])]++ let tab = newMemoTable+ pX = "X" <::=> (+) <$$> pY <**> pA+ pA = 1 <$$ char 'a' <** char 'b' <||> satisfy 0+ pY = memo tab ("Y" <::=> satisfy 0 <||> pX)+ test (Just tab) "hidden left-recursion + infinite derivations" pX+ [("", [0]), ("ab", [1]), ("ababab", [3])]++ putStrLn "Testing ambiguity reduction combinators"+ let pX = (++) <$$> pA <**>>> pB+ pA = "a" <$$ char 'a' <||> "aa" <$$ char 'a' <** char 'a'+ pB = "b" <$$ char 'a' <||> "bb" <$$ char 'a' <** char 'a' + test Nothing "A<A" pX [("aaa", ["aab"]),("aa", ["ab"])]++ let pX = (++) <$$> pA <<<**> pB+ pA = "a" <$$ char 'a' <||> "aa" <$$ char 'a' <** char 'a'+ pB = "b" <$$ char 'a' <||> "bb" <$$ char 'a' <** char 'a' + test Nothing "A>A" pX [("aaa", ["abb"]),("aa", ["ab"])] ++ let pX = "X" <:=> multiple pY+ where pY = 1 <$$ char '1' <||> 2 <$$ char '1' <** char '1'+ test Nothing "multiple" pX + [("", [[]]), ("1", [[1]]), ("11", [[1,1],[2]]), ("111", [[1,1,1], [2,1], [1,2]])]++ let pX = "X" <:=> some pY+ where pY = 1 <$$ char '1' <||> 2 <$$ char '1' <** char '1'+ test Nothing "some" pX + [("", [[]]), ("1", [[1]]), ("11", [[2]]), ("111", [[2,1]])]++{-+ -- a combinatar `fewest` (variant of multiple) should behave as follows+ let pX = "X" <:=> fewest pY+ where pY = 1 <$$ char '1' <||> 2 <$$ char '1' <** char '1'+ test Nothing "some" pX + [("", [[]]), ("1", [[1]]), ("11", [[2]]), ("111", [[2,1], [1,2]])]+-}++ let pX = "X" <:=> many pY+ where pY = 1 <$$ char '1' <||> 2 <$$ char '1' <** char '1'+ test Nothing "many" pX + [("", [[]]), ("1", [[1]]), ("11", [[1,1]]), ("111", [[1,1,1]])]+ + let pX = "X" <:=> "1" <$$ char '1' <||> multipleSepBy (char '1') (char ';')+ test Nothing "multipleSepBy" pX+ [("", [""]), ("1", ["1", "1"]), ("1;1", ["11"])]++ -- pX matches epsilon, therefore leading to infinitely many derivations+ let pX :: BNF Char Int + pX = "X" <::=> 1 <$$ char '1' <||> sum <$$> multipleSepBy pX (char ';')+ test Nothing "multipleSepBy2" pX+ [("", [0]), ("1", [1,1]), ("1;1", [2]), (";1", [1]), (";1;1", [2])]++ let pX = "X" <:=> length <$$> multiple (char '1')+ test Nothing "multiple1" pX+ [("", [0]), ("11", [2]), (replicate 10 '1', [10])]++ let pX = "X" <:=> length <$$> multiple (char '1') <** char 'z'+ test Nothing "multiple2" pX+ [("", []), ("11z", [2]), (replicate 10 '1' ++ "z", [10])]++ let pX = "X" <:=> length <$$> multiple pEps <** char 'z'+ where pEps = satisfy () <||> () <$$ char '1'+ test Nothing "multiple & epsilon" pX+ [("", []), ("z", [0])]++ let pX :: BNF Char Int + pX = "X" <::=> 1 <$$ char '1' <||> sum <$$> multipleSepBy pX (char ';')+ test Nothing "multipleSepBy and multiple" (multiple pX)+ -- why not ("", [[0]]) ??+ [("", [[]]), ("1", [[1],[1]]), ("1;1", [[1,0,1],[1,1],[2]])+ ,(";1;1", [[0,1,0,1],[0,1,1], [0,2], [1,0,1], [1,1], [2]])]+{-+ let pX :: BNF Char Int + pX = "X" <::=> 1 <$$ char '1' <||> sum <$$> multipleSepBy pX (char ';')+ test Nothing "manySepBy and multiple" (many pX)+ -- why not ("", [[0]]) ??+ [("", [[]]), ("1", [[1],[1]]), ("1;1", [[1,0,1]])]-}++ let pX :: BNF Char Int -> BNF Char Int+ pX p = mkNt p "X" <::=> p <||> (+) <$$> pX (p) <**> p+ test Nothing "sequence" (pX ("hash" <:=> 1 <$$ char '1'))+ [("1", [1]), ("11",[2]),("111", [3])+ ,("", []), ("21",[]), ("1(1)1", [])]++ {- tests fails to terminate as the grammar is infinitely big+ let pX :: BNF Char Int -> BNF Char Int+ pX p = mkNt p "X" <::=> p + <||> (+) <$$> pX (within (char '(') p (char ')')) <**> p+ test Nothing "growing sequence (left-recursive)" (pX ("hash" <:=> 1 <$$ char '1'))+ [("1", [1]), ("(1)1",[2]),("((1))(1)1", [3])+ ,("", []), ("11",[]), ("1(1)1", [])]+ -}+ {-let pX :: BNF Char Int -> BNF Char Int+ pX p = mkNt p "X" <::=> p + <||> (+) <$$> p <**> pX (within (char '(') p (char ')'))+ test Nothing "growing sequence (right-recursive)" + (pX ("hash" <:=> 1 <$$ char '1'))+ [("1", [1]),("1(1)",[2]),("1(1)((1))", [3]),("1(1)((1))(((1)))",[4])+ ,("", []), ("11",[]), ("1(1)1", []), ("1(1)(1)", [])]-}+ where+ aho_S_5 = ["10101010100","10101011000","10101100100","10101101000","10101110000","10110010100","10110011000","10110100100","10110101000","10110110000","10111000100","10111001000","10111010000","10111100000","11001010100","11001011000","11001100100","11001101000","11001110000","11010010100","11010011000","11010100100","11010101000","11010110000","11011000100","11011001000","11011010000","11011100000","11100010100","11100011000","11100100100","11100101000","11100110000","11101000100","11101001000","11101010000","11101100000","11110000100","11110001000","11110010000","11110100000","11111000000"]++ _EEE_3 = ["00111","01011","01101","01110","10011","10101","10110","11001","11010","111","11100"]++
src/GLL/Combinators/Test/Interface.hs view
@@ -33,7 +33,7 @@ import Data.List (sort, nub) import Data.IORef -import GLL.Combinators.BinaryInterface+import GLL.Combinators.Interface import GLL.Parseable.Char () -- | Defines and executes multiple1 unit-tests