{-# LANGUAGE CPP #-}
{-
	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@]

	* A type of /zero-width assertion/:
	the 'Bow'-predicate is 'True' if no input-data has yet been consumed; the 'Stern'-predicate is 'True' if no input-data remains to be consumed.

	* Whilst at the top-level of the regex, the /absence/ of an anchor is equivalent to a non-capturing @.*?@,
	tempting one to implement them using this property,
	it doesn't apply to those anchors encountered at either end of a sub-expression.
	So in all cases, an anchor constrains the permissible consumption of input-data,
	but at the top level it also prevents the regex drifting away from either end of the input-data.
-}

module RegExDot.Anchor(
-- * Types
-- ** Data-types
	Anchor(..),
-- ** Type-synonyms
	AnchorSpecification,
-- * Constants
	bowToken,
	sternToken,
	tokens,
	unanchored
) where

#ifdef HAVE_DEEPSEQ
import	Control.DeepSeq(NFData, rnf)
#else
import	Control.Parallel.Strategies(NFData, rnf)
#endif

-- | Defines the types on /anchor/ by which a /regex/ can be moored to a part of the input-data.
data Anchor =
	Bow	-- ^ Matches only if no input data has yet been consumed. Can only exist at the start of the entire regex, or (in theory) the start of any /alternative/.
	| Stern	-- ^ Matches only if no input data remains to be consumed. Can only exist at the end of the entire regex, or (in theory) the end of any /alternative/.
	deriving (
		Eq
--		Read,	--See specialisation below.
--		Show	--See specialisation below.
	)

instance Show Anchor	where
	showsPrec _ Bow		= showChar bowToken
	showsPrec _ Stern	= showChar sternToken

instance Read Anchor	where
	readsPrec _ []		= []	--No parse.
	readsPrec _ (' ' : s)	= reads s	--Consume white-space.
	readsPrec _ ('\t' : s)	= reads s	--Consume white-space.
	readsPrec _ (c : s)	= case c `lookup` [(bowToken, Bow), (sternToken, Stern)] of
		Just anchor	-> [(anchor, s)]
		_		-> []	--No parse.

instance NFData Anchor	where
	rnf _	= ()

-- | The conventional token used to denote a 'Bow'-anchor, when in 'String'-form.
bowToken :: Char
bowToken	= '^'

-- | The conventional token used to denote a 'Stern'-anchor, when in 'String'-form.
sternToken :: Char
sternToken	= '$'

-- | The set of 'Char' to which a specific meaning is attributed, when reading from 'String'.
tokens :: String
tokens	= [bowToken, sternToken]

-- | A specification for the anchors required around the expression
type AnchorSpecification	= (Maybe Anchor, Maybe Anchor)

-- | The specification for an unanchored expression.
unanchored :: AnchorSpecification
unanchored	= (Nothing, Nothing)