packages feed

regexchar-0.9.0.7: src/Grecce/Assert/RegExOptsChar.hs

{-# LANGUAGE FlexibleContexts #-}
{-
	Copyright (C) 2010 Dr. Alistair Ward

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
-}
{- |
 [@AUTHOR@]	Dr. Alistair Ward

 [@DESCRIPTION@]

	* Reads lines from the specified file.

	* Each line describes a 'Test'.

	* Each input-data string should match the /regex/ in the specified way.

	* Permits comparison with "Text.Regex.Posix.String".
-}

module Grecce.Assert.RegExOptsChar(
-- * Types
-- ** Type-synonyms
--	Test,
--	TestDataAndResult,
--	TestFilter,
-- * Functions
	findFailures,
	findFailuresPosix,
	readTests
-- ** Predicates
--	isMatch
) where

import			Control.Applicative((<$>))
import			Text.Regex.Posix()
import qualified	Control.Arrow
import qualified	RegExChar.ExtendedRegExChar	as ExtendedRegExChar
import qualified	RegExChar.RegExOptsChar		as RegExOptsChar	--CAVEAT: beware of the similar name.
import qualified	RegExDot.CompilationOptions	as CompilationOptions
import qualified	RegExDot.ExecutionOptions	as ExecutionOptions
import qualified	Text.Regex.Base.RegexLike	as RegexLike
import qualified	Text.Regex.Posix.Wrap

-- | Composed input data & list of captured 'RegExOptsChar.MatchSpan'.
type TestDataAndResult	= (ExtendedRegExChar.InputData, [RegExOptsChar.MatchSpan])

-- | Composed of the 'String' from which an unspecified type of regex is read, & a list of input data & results, to which it should respectively be applied & compared.
type Test		= (String {-regex-source-}, [TestDataAndResult])

-- | Filters a list of 'Test's, & returns a sub-set.
type TestFilter		= [Test] -> [Test]

-- | 'True' if the specified 'ExtendedRegExChar.InputData', is a member of the set defined by the polymorphic 'Text.Regex.Base.RegexLike.RegexLike' parameter.
isMatch :: RegexLike.RegexLike r ExtendedRegExChar.InputData => r -> TestDataAndResult -> Bool
isMatch regex (inputData, matchSpanList)	= RegexLike.matchOnce regex inputData == Just (RegExOptsChar.toZeroIndexedArray matchSpanList)

-- | Returns those 'Test's, which 'RegExOptsChar.RegExOptsChar' fails.
findFailures :: CompilationOptions.CompilationOptions -> ExecutionOptions.ExecutionOptions -> TestFilter
findFailures compilationOptions executionOptions	= filter (not . uncurry all . Control.Arrow.first (isMatch . RegexLike.makeRegexOpts compilationOptions executionOptions))

-- | Returns those 'Test's, which 'Text.Regex.Posix.Wrap.Regex' fails.
findFailuresPosix :: TestFilter
findFailuresPosix	= filter (not . uncurry all . Control.Arrow.first ((isMatch :: Text.Regex.Posix.Wrap.Regex -> TestDataAndResult -> Bool) . RegexLike.makeRegex))

{- |
	* Read 'Test's from file, ignoring blank lines & comments.

	* To facilitate parsing, each line in the file has the format of @show Test@.
-}
readTests :: String -> IO [Test]
readTests fileName	= map (
	\line	-> case reads line of
		[(test, _)]	-> test
		_		-> error $ "Grecce.Assert.RegExOptsChar.readTests:\tfailed to read 'Test' from '" ++ line ++ "'"
 ) . filter (
	(/= '#') . head	--Remove comments.
 ) . filter (
	not . null	--Remove blank lines.
 ) . lines <$> readFile fileName