module Test.ParseNistKATs
( parseCategories
, Properties, Record, NistTest, TypedTest, TestCategory
) where
import Data.Char (isSpace)
import Data.Maybe (listToMaybe)
import Control.Arrow (first, second)
type Properties = [(String, String)]
type Record = (String, String)
type NistTest = [Record]
type TypedTest = (String, [NistTest])
type TestCategory = (Properties, [NistTest])
parseCategories :: String -> String -> [(Properties, [NistTest])]
parseCategories delim file =
getCategories delim . elimWhite . elimComments . lines $ file
elimComments = filter ((/= Just '#') . listToMaybe)
elimWhite = map (filter (/= '\r')) . filter (notNull . filter (not . isSpace))
getCategories :: String -> [String] -> [(Properties, [NistTest])]
getCategories _ [] = []
getCategories delim ls =
let (tt, rest) = getCategory delim ls
in tt : getCategories delim rest
getCategory delim ls =
let (props,rest1) = break ((/= Just '[') . listToMaybe) ls
(tests,rest2) = break ((== Just '[') . listToMaybe) rest1
in ((map parseProp props, parseTests delim tests), rest2)
parseProp = first trim . second trim . second (drop 1) . break (== '=') . filter (`notElem` "[]")
parseTests :: String -> [String] -> [NistTest]
parseTests delim = filter notNull . chunk ((== delim) . fst) . map parseRecord
parseRecord = second (drop 1) . break (== '=') . filter (not . isSpace)
notNull = not . null
trim :: String -> String
trim = dropWhile isSpace . (reverse . dropWhile isSpace . reverse)
chunk :: (a -> Bool) -> [a] -> [[a]]
chunk f xs = snd (go xs)
where
go [] = ([],[])
go (a:as) = if f a
then let (t,ts) = go as in ([], (a:t):ts)
else let (t, ts) = go as
in (a:t, ts)