81ec673ac5ab1493568d9ef7798b752ab8ee0e61Felix Gabriel ManceCopyright : (c) Andy Gimblett and Markus Roggenbach and Uni Bremen 2004
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel ManceLicense : GPLv2 or higher, see LICENSE.txt
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel ManceMaintainer : a.m.gimblett@swan.ac.uk
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel ManceStability : provisional
5d801400993c9671010d244646936d8fd435638cChristian MaederPortability : portable
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel ManceTest case wrapper for CspCASL specs and fragments.
5d801400993c9671010d244646936d8fd435638cChristian MaederThis is a standalone `main' wrapper for CspCASL-related tests
5d801400993c9671010d244646936d8fd435638cChristian Maederperformed locally to the CspCASL codebase. It's probably only of
5d801400993c9671010d244646936d8fd435638cChristian Maederinterest to the CspCASL maintainers.
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance testwrap [options] targets
feab1106bbee4f2ea2fd48bca7106dd041e4211dFelix Gabriel Mance -t Don't parse any .cspcasl files; useful for just running tests.
668c9c725a11c0f77057152148570af853a1bc0dFelix Gabriel Mance -c Don't run any tests; useful for just parsing .cspcasl files.
668c9c725a11c0f77057152148570af853a1bc0dFelix Gabriel Mance Obviously, specifying both of these options stops this program from
863fa65ac095659c6da1cde7fe7b839f1e7f60f9Felix Gabriel Mance doing anything useful.
668c9c725a11c0f77057152148570af853a1bc0dFelix Gabriel Mance targets - a list of targets, where each target can be:
668c9c725a11c0f77057152148570af853a1bc0dFelix Gabriel Mance - a .cspcasl file; parse the file as a Core-CspCASL specification,
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance unparse the parse tree, and print out the result of the unparse.
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance In case of parse error, report the error.
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance - a .testcase file; execute the test and report the outcome. A
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance testcase file specifies one test case, whose source is contained
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance in another file, and whose output we will check against expected
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance contents. See below for the file format.
0ec1551231bc5dfdcb3f2bd68fec7457fade7bfdFelix Gabriel Mance - a .testcases file; execute the tests and report their outcomes.
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance A testcases file specifies multiple test cases, with source
852bd6145634dc2832b61c44678fe539bc1682d5Christian Maeder integrated with each test case, and outputs we will check
968930c7674ae3b63d308bf4fa651400aa263054Christian Maeder against expected contents. See below for the file format.
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance - a directory; find all .cspcasl, .testcase and .testcases files
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance in the directory (recursively) and operate on them as described
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel MancePostive and negative tests:
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance A positive test is one where we expect the parse to succeed; here
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance the expected output is the result of unparsing the resultant parse
68de80eb2800338cbd16512106fcadab79325d8bChristian Maeder tree. The test can fail with a parse error, or with unexpected
68de80eb2800338cbd16512106fcadab79325d8bChristian Maeder A negative test is one where we expect the parse to fail; here the
68de80eb2800338cbd16512106fcadab79325d8bChristian Maeder expected output is the error message produced. The test can fail
68de80eb2800338cbd16512106fcadab79325d8bChristian Maeder with a successful parse, or with unexpected output.
fc7bd98aabe1bc26058660085e8c77d60a97bcecChristian MaederFormat of .testcase files:
68de80eb2800338cbd16512106fcadab79325d8bChristian Maeder A .testcase file contains a single test case. The first line is the
fc7bd98aabe1bc26058660085e8c77d60a97bcecChristian Maeder path to the file containing the source to be parsed/tested, relative
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance to the .testcase file; it also acts as the name of the test case.
68de80eb2800338cbd16512106fcadab79325d8bChristian Maeder The second line identifies the test sense ("++" is positive, "--" is
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance negative). The third line is the name of the parser to be used. The
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance remaining lines contain the expected output of the test.
852bd6145634dc2832b61c44678fe539bc1682d5Christian MaederFormat of .testcases files:
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance A .testcases file contains multiple test cases including their
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance source. Individual test cases are separated by lines containing
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance twenty '-' characters and nothing else. The format of an individual
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance test case is similar but not identical to the format of a standalone
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance test case (above). The first line is the name of the test (used for
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance reporting). The second line identifies the test sense ("++" is
668c9c725a11c0f77057152148570af853a1bc0dFelix Gabriel Mance positive, "--" is negative). The third line is the name of the
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance parser to be used. This is followed by the expected outcome of the
544989bc1f6ed4bc0813334ffd934db0fb0010eaFelix Gabriel Mance test and the source (input) of the test, in that order, both of
544989bc1f6ed4bc0813334ffd934db0fb0010eaFelix Gabriel Mance which may span multiple lines; they are separated by a line
544989bc1f6ed4bc0813334ffd934db0fb0010eaFelix Gabriel Mance containing ten '-' characters and nothing else.
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maedermodule Main where
f8c3d045dda224e92bf6bcb6288e1ee75ab54d1eChristian Maederimport System.FilePath (combine, dropFileName)
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Manceimport Common.AnnoState (emptyAnnos)
852bd6145634dc2832b61c44678fe539bc1682d5Christian Maederimport CspCASL.Parse_CspCASL (cspBasicExt)
ea3f858eb531d981df3ed00beeadd99cf025adecChristian Maederimport CspCASL.Parse_CspCASL_Process (csp_casl_process)
668c9c725a11c0f77057152148570af853a1bc0dFelix Gabriel Mancemain = do args <- getArgs
75aaf82c430ad2a5cf159962b1c5c09255010fb4Felix Gabriel Mance dirs <- filterM doesDirectoryExist args
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance dir_contents <- liftM concat (mapM listFilesR dirs)
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance files <- filterM doesFileExist (sort $ nub (args ++ dir_contents))
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance doIf ("-t" `notElem` args) (parseCspCASLs (filter isCspCASL files))
1b1144abf7f95a4b23405b8d5604813cfe7b036aFelix Gabriel Mance doIf ("-c" `notElem` args) (performTests (filter isTest files))
19e01e1a7e319063434bd86c8ecbc5f241ef9993Felix Gabriel Mance where isCspCASL = (".cspcasl" `isSuffixOf`)
1b1144abf7f95a4b23405b8d5604813cfe7b036aFelix Gabriel Mance isTest f = isSuffixOf ".testcase" f || isSuffixOf ".testcases" f
5a3ae0a9224276de25e709ef8788c1b9716cd206Christian Maeder doIf c f = if c then f else putStr ""
668c9c725a11c0f77057152148570af853a1bc0dFelix Gabriel Mance{- | Given a list of paths to .cspcasl files, parse each in turn,
668c9c725a11c0f77057152148570af853a1bc0dFelix Gabriel Manceprinting results as you go. -}
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel ManceparseCspCASLs :: [FilePath] -> IO ()
8af00c8930672188ae80c8829428859160d329d0Felix Gabriel ManceparseCspCASLs [] = putStr ""
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel ManceparseCspCASLs (f : fs) = do putStrLn dash20
1b90322eaf59ded3de24fc891bd67bbd73ec2bfaFelix Gabriel Mance prettyCspCASLFromFile f
1b90322eaf59ded3de24fc891bd67bbd73ec2bfaFelix Gabriel Mance parseCspCASLs fs
1b90322eaf59ded3de24fc891bd67bbd73ec2bfaFelix Gabriel Mance-- | Parse one .cspcasl file; print error or pretty print parse tree.
1b90322eaf59ded3de24fc891bd67bbd73ec2bfaFelix Gabriel ManceprettyCspCASLFromFile :: FilePath -> IO ()
1b90322eaf59ded3de24fc891bd67bbd73ec2bfaFelix Gabriel ManceprettyCspCASLFromFile fname
1b90322eaf59ded3de24fc891bd67bbd73ec2bfaFelix Gabriel Mance = do putStrLn ("Parsing " ++ fname)
1b90322eaf59ded3de24fc891bd67bbd73ec2bfaFelix Gabriel Mance input <- readFile fname
8af00c8930672188ae80c8829428859160d329d0Felix Gabriel Mance case runParser cspBasicExt (emptyAnnos ()) fname input of
8af00c8930672188ae80c8829428859160d329d0Felix Gabriel Mance Left err -> do putStr "parse error at "
8af00c8930672188ae80c8829428859160d329d0Felix Gabriel Mance Right x -> do putStrLn $ showDoc x ""
8af00c8930672188ae80c8829428859160d329d0Felix Gabriel Mance{- | Test sense: do we expect parse success or failure? What is the
8af00c8930672188ae80c8829428859160d329d0Felix Gabriel Mancenature of the expected output? -}
8af00c8930672188ae80c8829428859160d329d0Felix Gabriel Mancedata TestSense = Positive | Negative
9cb6af1a7632f12b60f592ce5eb2ac51e6bd33bbFelix Gabriel Mance deriving (Eq, Ord)
8af00c8930672188ae80c8829428859160d329d0Felix Gabriel Manceinstance Show TestSense where
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance show Positive = "++"
968930c7674ae3b63d308bf4fa651400aa263054Christian Maeder show Negative = "--"
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance-- | Test case details: where is source, what is it, which parser, etc.
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mancedata TestCase = TestCase {
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance -- | @name@ - test name
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance name :: String,
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance -- | @parser@ - name of parser to apply
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance parser :: String,
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance -- | @sense@ - sense of test (positive or negative)
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance sense :: TestSense,
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance -- | @src@ - source to be parsed
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance src :: String,
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance -- | @expected@ - expected output of test
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance expected :: String
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance} deriving (Eq, Ord)
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Manceinstance Show TestCase where
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance show a = name a ++ " (" ++ show (sense a) ++ parser a ++ ")"
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance-- | Given a list of paths of test case files, read & perform them.
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel ManceperformTests :: [FilePath] -> IO ()
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel ManceperformTests tcs = do putStrLn "Performing tests"
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance tests <- liftM concat (mapM readTestFile tcs)
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance-- | Turn a .testcase or .testcases file into list of test cases therein.
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel MancereadTestFile :: FilePath -> IO [TestCase]
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance | ".testcase" `isSuffixOf` f = readTestCaseFile f
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance | ".testcases" `isSuffixOf` f = readTestCasesFile f
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance | otherwise = return []
968930c7674ae3b63d308bf4fa651400aa263054Christian Maeder-- | Turn a .testcase file into the test case therein.
a921ae1da1302f673204e7b63cdce01439a9bd5eFelix Gabriel MancereadTestCaseFile :: FilePath -> IO [TestCase]
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel MancereadTestCaseFile f =
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance do hdl <- openFile f ReadMode
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance contents <- hGetContents hdl
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance let (a, b, c, d) = testCaseParts contents
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance hdl_s <- openFile (combine (dropFileName f) a) ReadMode
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance e <- hGetContents hdl_s
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance return [TestCase { name = a, parser = b, sense = c, expected = d, src = e }]
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance-- | Turn a .testcases file into the test cases therein.
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel MancereadTestCasesFile :: FilePath -> IO [TestCase]
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel MancereadTestCasesFile f =
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance do hdl <- openFile f ReadMode
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance s <- hGetContents hdl
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance let tests = map (interpretTestCasesOne . strip) (split dash20 s)
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance-- | Turn test case string from a .testcases file into its test case.
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel ManceinterpretTestCasesOne :: String -> TestCase
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel ManceinterpretTestCasesOne s
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance | length parts == 2 = TestCase { name = a, parser = b, sense = c,
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance expected = d, src = e }
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance | otherwise = error s
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance where parts = map strip (split dash10 s)
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance (a, b, c, d) = testCaseParts (head parts)
8af00c8930672188ae80c8829428859160d329d0Felix Gabriel Mance e = parts !! 1
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance-- | Turn test case string into its constituent parts (except source).
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel MancetestCaseParts :: String -> (String, String, TestSense, String)
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel MancetestCaseParts s = (head ls,
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance head (tail ls),
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance interpretSense (head (tail (tail ls))),
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance unlines (tail (tail (tail ls))))
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance where ls = lines s
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance-- | Interpret a test case sense (++ or --, positive or negative)
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel ManceinterpretSense :: String -> TestSense
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel ManceinterpretSense s = case s of
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance "++" -> Positive
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance "--" -> Negative
ffa6044b04fa0e31242141ff56a5d80c4233b676Felix Gabriel Mance _ -> error ("Bad test sense " ++ s)
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Mance{- | Given a list of test cases, perform the tests in turn, printing
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel Manceresults as you go. -}
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel MancedoTests :: [TestCase] -> IO ()
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel MancedoTests [] = putStr ""
c77c0efe19dc6556ac872828bfb4cfc5fbca5ac5Felix Gabriel MancedoTests (tc : ts) = do -- putStrLn dash20
c298a419605037f5352b5ad0f67b3e06db094051Felix Gabriel Mance let output = parseTestCase tc
083b2687afdb676237f926bdb643b24027291d05Felix Gabriel Mance putStr (show tc ++ " ")
511be329b2e8f55d0c6b18bd92571a1776b15932Felix Gabriel Mance printOutcome tc output
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder{- | Perform a test and report its outcome. There are six
511be329b2e8f55d0c6b18bd92571a1776b15932Felix Gabriel Mancepossibilities: 1) positive test succeeds; 2) postive test
e26bfed39ffa184453272125a4adf147206eac74Christian Maederfail/non-parse (parse fails); 3) positive test error (unparse not
e26bfed39ffa184453272125a4adf147206eac74Christian Maederas expected); 4) negative test succeeds; 5) negative test
e26bfed39ffa184453272125a4adf147206eac74Christian Maederfail/parse (parse succeeds); 6) negative test error (error not as
863fa65ac095659c6da1cde7fe7b839f1e7f60f9Felix Gabriel ManceprintOutcome :: TestCase -> Either ParseError (String, String) -> IO ()
0c3badd7ad83eb89f64ef5ed1122c4fa856fb45dFelix Gabriel ManceprintOutcome tc out =
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder case (sense tc, out) of
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder (Positive, Right (o, tree)) ->
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder if strip o == strip (expected tc)
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder then testPass -- case 1
863fa65ac095659c6da1cde7fe7b839f1e7f60f9Felix Gabriel Mance else do testFail "unparse" (expected tc) o -- case 3
863fa65ac095659c6da1cde7fe7b839f1e7f60f9Felix Gabriel Mance putStrLn ("-> tree:\n" ++ tree)
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder (Positive, Left err) ->
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder testFail "parse failure" "" (show err) -- case 2
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder (Negative, Right (o, _)) ->
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder testFail "parse success" (expected tc) o -- case 5
863fa65ac095659c6da1cde7fe7b839f1e7f60f9Felix Gabriel Mance (Negative, Left err) ->
d850dba73b02f345f64a3546d0f0299c292f88d6Felix Gabriel Mance if strip (show err) == strip (expected tc)
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder then testPass -- case 4
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder else testFail "error" (expected tc) (show err) -- case 6
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder-- Report on a test pass
d850dba73b02f345f64a3546d0f0299c292f88d6Felix Gabriel MancetestPass :: IO ()
d850dba73b02f345f64a3546d0f0299c292f88d6Felix Gabriel MancetestPass = putStrLn "passed"
d850dba73b02f345f64a3546d0f0299c292f88d6Felix Gabriel Mance-- Report on a test failure
863fa65ac095659c6da1cde7fe7b839f1e7f60f9Felix Gabriel MancetestFail :: String -> String -> String -> IO ()
d850dba73b02f345f64a3546d0f0299c292f88d6Felix Gabriel MancetestFail nature expect got =
511be329b2e8f55d0c6b18bd92571a1776b15932Felix Gabriel Mance do putStrLn ("failed - unexpected " ++ nature)
6504b297e21d071d8fada2f732cabb6d8f7d38a2Felix Gabriel Mance if expect /= ""
6504b297e21d071d8fada2f732cabb6d8f7d38a2Felix Gabriel Mance then putStrLn ("-> expected:\n" ++ strip expect)
6504b297e21d071d8fada2f732cabb6d8f7d38a2Felix Gabriel Mance else putStr ""
6504b297e21d071d8fada2f732cabb6d8f7d38a2Felix Gabriel Mance putStrLn "-> got:"
f8c3d045dda224e92bf6bcb6288e1ee75ab54d1eChristian Maeder putStrLn $ strip got
f8c3d045dda224e92bf6bcb6288e1ee75ab54d1eChristian Maeder-- | Run a test case through its parser.
f8c3d045dda224e92bf6bcb6288e1ee75ab54d1eChristian MaederparseTestCase :: TestCase -> Either ParseError (String, String)
f8c3d045dda224e92bf6bcb6288e1ee75ab54d1eChristian MaederparseTestCase t =
4b7c9b9fec53befb553f2c9b11e30a4fe2235e03Felix Gabriel Mance case parser t of
44985cbd4eb61dbc348617ebdd44a774e51dac07Christian Maeder "CoreCspCASL" -> case runWithEof cspBasicExt of
1075744775ba70c9ef6cdd06523204751f544ed5Christian Maeder Left err -> Left err
1075744775ba70c9ef6cdd06523204751f544ed5Christian Maeder Right x -> Right (showDoc x "", show x)
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder "Process" -> case runWithEof csp_casl_process of
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder Left err -> Left err
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder Right x -> Right (showDoc x "", show x)
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder _ -> error "Parser name"
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder where runWithEof p = runParser p' (emptyAnnos ()) (name t) (src t)
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder where p' = do n <- p
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder{- The above implemenation is horrible. There must be a nice way to
e26bfed39ffa184453272125a4adf147206eac74Christian Maederabstract the parser out from the code to run it and collect/unparse
e26bfed39ffa184453272125a4adf147206eac74Christian Maederthe result. Alas, I don't know it, or don't know that I know it. -}
e26bfed39ffa184453272125a4adf147206eac74Christian Maederdash20, dash10 :: String
e26bfed39ffa184453272125a4adf147206eac74Christian Maederdash10 = "----------"
f8c3d045dda224e92bf6bcb6288e1ee75ab54d1eChristian Maederdash20 = dash10 ++ dash10
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder-- Utility functions which really should be in the standard library!
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder{- | Recursive file lister adapted from
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian MaederlistFilesR :: FilePath -> IO [FilePath]
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian MaederlistFilesR path =
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder do allfiles <- getDirectoryContents path
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder nodots <- filterM (return . isDODD) (map (combine path) allfiles)
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maeder dirs <- filterM doesDirectoryExist nodots
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maeder subdirfiles <- liftM concat $ mapM listFilesR dirs
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maeder files <- filterM doesFileExist nodots
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maeder return $ files ++ subdirfiles
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maeder isDODD f = not $ ("/." `isSuffixOf` f) || ("/.." `isSuffixOf` f)
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maeder{- | A function inspired by python's string.split(). A list is split
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maederon a separator which is itself a list (not a single element). -}
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maedersplit :: Eq a => [a] -> [a] -> [[a]]
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maedersplit tok = unfoldr (sp1 tok)
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maeder where sp1 _ [] = Nothing
6856a07e36551ed6fadd7c01e7152a3a28878a6fChristian Maeder sp1 t s = case find (t `isSuffixOf`) (inits s) of
f8c3d045dda224e92bf6bcb6288e1ee75ab54d1eChristian Maeder Nothing -> Just (s, [])
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder Just p -> Just (take (length p - length t) p,
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder drop (length p) s)
e26bfed39ffa184453272125a4adf147206eac74Christian Maeder-- | String strip in style of python string.strip()
e26bfed39ffa184453272125a4adf147206eac74Christian Maederstrip :: String -> String
44985cbd4eb61dbc348617ebdd44a774e51dac07Christian Maederstrip s = dropWhile ws $ reverse $ dropWhile ws $ reverse s
863fa65ac095659c6da1cde7fe7b839f1e7f60f9Felix Gabriel Mance where ws = (`elem` " \n\t\r")