module Main
where
import Control.Arrow
import System
import Text.Regex.XMLSchema.String
import Text.Regex.XMLSchema.String.Regex
import Test.HUnit
-- ------------------------------------------------------------
parseTests :: Test
parseTests
= TestLabel "parse tests" $
TestList $
map parseTest $ tests
where
parseTest (re, rep)
= TestCase $
assertEqual (show re ++ " must be parsed as " ++ show rep)
rep
(show . parseRegex $ re)
tests = [ ("", "()")
, (".", ".")
, (".*", "(.*)")
, ("\\a", "\\a")
, ("\\A", "\\A")
, ("(())", "()")
, ("(a*)*", "(a*)")
, ("(a*)+", "(a*)")
, ("(a+)*", "(a*)")
, ("(a+)+", "(a+)")
, ("(a?){2,}", "(a*)")
, ("((a?){2,}){0,}", "(a*)")
, ("((a?){2,}){3,}", "(a*)")
, ("(a{0,}){2,}", "(a*)")
, ("(a{2,}){3,}", "(a{6,})")
, ("[9-0]", "{empty char range}")
, ("[0-9]", "[0-9]")
, ("[0-99-0]", "[0-9]")
, ("[abc]", "[a-c]")
, ("[\0-\1114111]", "\\a")
, ("[\0-\1114111]|[0-9]", "\\a")
, ("[\0-\1114110]", "[�-]" )
, ("a|b|c|d", "[a-d]" )
, ("(a|b)|c", "[a-c]" )
, ("a|(b|c)", "[a-c]" )
, ("abc", "(a(bc))" ) -- seq is right ass
, ("a*{^}b*", "((a*){^}(b*))" ) -- extension: exor
, ("a*{^}b*{^}c*", "((a*){^}((b*){^}(c*)))")
, ("a*{&}b*", "((a*){&}(b*))" ) -- extension: intersection
, ("a*{&}b*{&}c*", "((a*){&}((b*){&}(c*)))")
, ("a*{\\}b*", "((a*){\\}(b*))" ) -- extension: set difference
, ("a*{\\}b*{\\}c*", "(((a*){\\}(b*)){\\}(c*))" )
, ("(a|b)*{\\}(.*aa.*)", "(([ab]*){\\}((.*)(a(a(.*)))))" )
, ("({1}a+)", "({1}(a+))" ) -- extension: labeled subexpressions
, ("({1}({2}({3}a)))", "({1}({2}({3}a)))" )
, ("({1}do){|}({2}[a-z]+)", "(({1}(do)){|}({2}([a-z]+)))" ) -- deterministic choice of submatches
]
simpleMatchTests :: Test
simpleMatchTests
= TestLabel "simple match tests" $
TestList $
concatMap matchTest $ tests
where
matchTest (re, ok, er)
= map (matchOK re) ok
++
map (matchErr re) er
matchOK re s = TestCase $ assertBool (show s ++ " must match " ++ show re) (match re s)
matchErr re s = TestCase $ assertBool (show s ++ " must not match " ++ show re) (not (match re s))
tests = [ ( ""
, [""]
, ["a"]
)
, ( "a"
, ["a"]
, ["", "b", "ab"]
)
, ( "()"
, [""]
, ["a"]
)
, ( "ab"
, ["ab"]
, ["", "b", "abc"]
)
, ( "."
, [".","a","\0","\1114111"]
, ["\n","\r","",".."]
)
, ( "\\a"
, [".","a","\n","\r","\0","\1114111"]
, ["",".."]
)
, ( "\\A"
, ["",".","a","\n","\r","\0","\1114111",".."]
, []
)
, ( "a*"
, ["", "a", "aa"]
, ["b", "ab", "aab"]
)
, ( "a+"
, ["a", "aa", "aaa"]
, ["", "b", "ab"]
)
, ( "a?"
, ["", "a"]
, ["b", "ab"]
)
, ( "a{2}"
, ["aa"]
, ["", "a", "aaa"]
)
, ( "a{2,}"
, ["aa","aaa"]
, ["", "a", "aaab"]
)
, ( "a{2,4}"
, ["aa", "aaa", "aaaa"]
, ["", "a", "aaaaa", "ab"]
)
, ( "a|b"
, ["a", "b"]
, ["", "c", "ab", "abc"]
)
, ( "[0-9]"
, ["0", "5", "9"]
, ["", "a", "00"]
)
, ( "[^0-9]"
, ["a"]
, ["", "0", "9", "00"])
, ( "\32"
, [" "]
, []
)
, ( "[\0-\1114111]"
, ["\0","\1114111","a"]
, ["","aaa"]
)
, ( "[^\0-\1114111]"
, []
, ["","aaa","\0","\1114111","a"]
)
, ( ".*a.*|.*b.*|.*c.*"
, ["a", "abc", "acdc"]
, ["", "dddd"]
)
, ( ".*a.*{&}.*b.*{&}.*c.*"
, ["abc", "abcd", "abcabcd"]
, ["", "a", "bc", "acdc", "dddd"]
)
, ( ".*a.*{&}.*b.*{&}.*c.*{&}.{3}" -- all permutations of "abc"
, ["abc", "acb", "bac", "bca", "cab", "cba"]
, ["", "a", "bc", "acd", "aaaa", "aba"]
)
, ( ".*a.*{&}.*b.*{&}.*c.*" -- all words containing at least 1 a, 1 b and 1 c
, ["abc", "acb", "bac", "bca", "cab", "cba", "abcd", "abcabc"]
, ["", "a", "bc", "acd", "aaaa"]
)
, ( ".*a.*{^}.*b.*" -- all words containing at least 1 a or 1 b but not both a's and b's
, ["a", "b", "ac", "bc", "aaaa", "bbb", "aacc", "ccbb", "acdc"]
, ["", "ab", "abc", "dddd"]
)
, ( "/[*](.*{\\}(.*[*]/.*))[*]/" -- single line C comment of form /*...*/, but without any */ in the comment body
-- this is the way to specify none greedy expessions
-- if multy line comment are required, substitute .* by \A, so newlines are allowed
, ["/**/","/***/","/*x*/","/*///*/"]
, ["", "/", "/*", "/*/", "/**/*/", "/*xxx*/xxx*/"]
)
]
-- ------------------------------------------------------------
simpleSplitTests :: Test
simpleSplitTests
= TestLabel "simple split tests" $
TestList $
map splitTest $ tests
where
splitTest (re, inp, tok)
= TestCase $
assertEqual ("split " ++ show re ++ show inp ++ " = (" ++ show tok ++ ", ... )")
tok
(fst (split re inp))
tests = [ ("", "a", "" )
, ("a*b", "abc", "ab" )
, ("a*", "bc", "" )
, ("a+", "bc", "" )
, ("a{2}", "aaa", "aa" )
, ("a{2,}", "aaa", "aaa" )
, ("a|b", "ab", "a" )
, ("a|b*", "bbba", "bbb" )
, ("abc", "abcd", "abc" )
]
-- ------------------------------------------------------------
simpleTokenTests :: Test
simpleTokenTests
= TestLabel "simple token tests" $
TestList $
map tokenTest $ tests
where
tokenTest (re, inp, toks)
= TestCase $
assertEqual ("tokenize " ++ show re ++ " " ++ show inp ++ " = " ++ show toks)
toks
(tokenize re inp)
tests = [ ("", "", [] )
, ("a", "aba", ["a", "a"] )
, ("a", "b", [] )
, ("a", "ba", ["a"] )
, ("a*", "a", ["a"] )
, ("a*", "ba", ["","a"] )
, ("a*", "aba", ["a", "a"] )
, ("a*", "abba", ["a", "", "a"] )
, ("a+", "abba", ["a", "a"] )
, ("a*b", "abba", ["ab", "b"] )
, (".*", "a\n\nb", ["a", "", "b"] )
, (".*", "a\n\nb\n", ["a", "", "b"] )
, ("\\w+", "a\n\nb\n", ["a", "b"] )
, ("\\w|ab", "aaa\n\nabc\n", ["a", "a", "a", "ab", "c"] )
, ("\\w|ab", "aaa abc", ["a", "a", "a", "ab", "c"] )
]
-- ------------------------------------------------------------
allTests :: Test
allTests
= TestList
[ parseTests
, simpleMatchTests
, simpleSplitTests
, simpleTokenTests
]
main :: IO ()
main
= do
c <- runTestTT allTests
putStrLn $ show c
let errs = errors c
fails = failures c
System.exitWith (codeGet errs fails)
codeGet :: Int -> Int -> ExitCode
codeGet errs fails
| fails > 0 = ExitFailure 2
| errs > 0 = ExitFailure 1
| otherwise = ExitSuccess
-- ------------------------------------------------------------
deltaTrc :: Regex -> String -> [(String, Regex)]
deltaTrc re "" = [("", re)]
deltaTrc re s@(c:cs) = (s, re)
:
( if isZero re'
then [("",re')]
else deltaTrc re' cs
)
where
re' = delta1 re c
matchTrc :: String -> String -> (Bool, [(String, Regex)])
matchTrc re = ( parseRegex >>> deltaTrc$ re )
>>>
( (last >>> snd >>> nullable) &&& id )
trcMatch :: String -> String -> IO()
trcMatch re = putStrLn . showTrc . matchTrc re
where
showTrc =
( (show >>> (++ "\n"))
***
(concatMap ( ((++ "\t") *** (show >>> (++"\n")))
>>> uncurry (++)
)
)
)
>>>
uncurry (flip (++))
-- ------------------------------------------------------------