packages feed

regexdot 0.11.0.1 → 0.11.1.0

raw patch · 8 files changed

+103/−80 lines, 8 filesdep ~toolshedPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: toolshed

API changes (from Hackage documentation)

- RegExDot.RegEx: instance (ShortcutExpander m, ShortcutExpander m, Eq m, Read m) => Read (ExtendedRegEx m)
- RegExDot.RegEx: instance (ShortcutExpander m, ShortcutExpander m, Eq m, Read m) => Read (Pattern m)
+ RegExDot.Anchor: type AnchorSpecification = (Maybe Anchor, Maybe Anchor)
+ RegExDot.Anchor: unanchored :: AnchorSpecification
+ RegExDot.RegEx: instance (Eq m, ShortcutExpander m, Read m, ShortcutExpander m) => Read (ExtendedRegEx m)
+ RegExDot.RegEx: instance (Eq m, ShortcutExpander m, Read m, ShortcutExpander m) => Read (Pattern m)
- RegExDot.DSL: (<~>) :: (Maybe Anchor, Maybe Anchor) -> Concatenation a -> ExtendedRegEx a
+ RegExDot.DSL: (<~>) :: AnchorSpecification -> Concatenation a -> ExtendedRegEx a
- RegExDot.RegEx: (+~) :: (Eq m, NFData m, Show m) => InputData m -> RegExOpts (ExtendedRegEx m) -> Result m
+ RegExDot.RegEx: (+~) :: (Eq m, NFData m) => InputData m -> RegExOpts (ExtendedRegEx m) -> Result m
- RegExDot.RegEx: (/~) :: (Eq m, NFData m, Show m) => InputData m -> RegExOpts (ExtendedRegEx m) -> Bool
+ RegExDot.RegEx: (/~) :: (Eq m, NFData m) => InputData m -> RegExOpts (ExtendedRegEx m) -> Bool
- RegExDot.RegEx: (=~) :: (Eq m, NFData m, Show m) => InputData m -> RegExOpts (ExtendedRegEx m) -> Bool
+ RegExDot.RegEx: (=~) :: (Eq m, NFData m) => InputData m -> RegExOpts (ExtendedRegEx m) -> Bool

Files

changelog view
@@ -35,3 +35,8 @@ 	* Replaced "System" with "System.Environment" and "System.Exit". 0.11.0.1 	* Added class 'Eq' to the context of 'RegExDot.RegEx.safeReciprocal', for migration to 'ghc-7.4'.+0.11.1.0+	* Removed comments referring to deleted module "ToolShed.Unsafe", from "RegExDot.RegEx".+	* Removed 'Show' from the context of functions in "RegExDot.RegEx"+	* Exported a new constant 'RegExDot.Anchor.unanchored'.+	* Refactored 'RegExDot.ConsumptionProfile.withinConsumptionBounds'.
makefile view
@@ -19,37 +19,37 @@  install: build haddock 	@[ -z "$$CABAL_INSTALL_OPTIONS" ] || echo "INFO: CABAL_INSTALL_OPTIONS='$$CABAL_INSTALL_OPTIONS'"-	runhaskell Setup.hs $@ $$CABAL_INSTALL_OPTIONS+	runhaskell Setup $@ $$CABAL_INSTALL_OPTIONS  prof: 	CABAL_CONFIGURE_OPTIONS="--enable-library-profiling $$CABAL_CONFIGURE_OPTIONS" make install  copy: build 	@[ -z "$$CABAL_COPY_OPTIONS" ] || echo "INFO: CABAL_COPY_OPTIONS='$$CABAL_COPY_OPTIONS'"-	runhaskell Setup.hs $@ $$CABAL_COPY_OPTIONS+	runhaskell Setup $@ $$CABAL_COPY_OPTIONS  build: configure 	@[ -z "$$CABAL_BUILD_OPTIONS" ] || echo "INFO: CABAL_BUILD_OPTIONS='$$CABAL_BUILD_OPTIONS'"-	runhaskell Setup.hs $@ $$CABAL_BUILD_OPTIONS+	runhaskell Setup $@ $$CABAL_BUILD_OPTIONS  configure: regexdot.cabal Setup.hs 	@[ -z "$$CABAL_CONFIGURE_OPTIONS" ] || echo "INFO: CABAL_CONFIGURE_OPTIONS='$$CABAL_CONFIGURE_OPTIONS'"-	runhaskell Setup.hs $@ $$CABAL_CONFIGURE_OPTIONS	#--user+	runhaskell Setup $@ $$CABAL_CONFIGURE_OPTIONS	#--user  haddock: configure-	PATH=~/.cabal/bin:$$PATH runhaskell Setup.hs $@ --hyperlink-source	#Amend path to find 'HsColour', as required for 'hyperlink-source'.+	PATH=~/.cabal/bin:$$PATH runhaskell Setup $@ --hyperlink-source	#Amend path to find 'HsColour', as required for 'hyperlink-source'.  hlint: 	@$@ -i 'Use &&' src/ -i 'Use ||' -sdist: configure-	runhaskell Setup.hs $@+sdist:+	runhaskell Setup $@  check: sdist 	cabal upload --check --verbose=3 dist/*.tar.gz;  clean:-	runhaskell Setup.hs $@+	runhaskell Setup $@ 	find src -type f \( -name '*.hc' -o -name '*.hcr' -o -name '*.hi' -o -name '*.o' \) -delete  help:
regexdot.cabal view
@@ -1,6 +1,6 @@ --Package-properties Name:			regexdot-Version:		0.11.0.1+Version:		0.11.1.0 Cabal-Version:		>= 1.6 Copyright:		(C) 2010 Dr. Alistair Ward License:		GPL@@ -11,7 +11,7 @@ Build-Type:		Simple Description:		Provides a portable, POSIX, extended regex-engine, designed to process a list of /arbitrary/ objects. Category:		Search, Regex-Tested-With:		GHC == 6.10, GHC == 6.12, GHC == 7.0+Tested-With:		GHC == 6.10, GHC == 6.12, GHC == 7.0, GHC == 7.4 Homepage:		http://functionalley.eu Maintainer:		regexdot <at> functionalley <dot> eu Bug-reports:		regexdot <at> functionalley <dot> eu@@ -58,7 +58,7 @@     Build-depends:         base == 4.*,         parsec == 3.*,-        toolshed == 0.13.*+        toolshed >= 0.13      GHC-options:	-Wall -O2 
src/RegExDot/Anchor.hs view
@@ -34,10 +34,13 @@ -- * Types -- ** Data-types 	Anchor(..),+-- ** Type-synonyms+	AnchorSpecification, -- * Constants 	bowToken, 	sternToken,-	tokens+	tokens,+	unanchored ) where  #ifdef HAVE_DEEPSEQ@@ -82,4 +85,11 @@ -- | 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) 
src/RegExDot/ConsumptionProfile.hs view
@@ -43,7 +43,9 @@ ) where  import			Control.Applicative((<$>), (<*>))+import			Control.Arrow((***)) import qualified	Data.List+import qualified	Data.Maybe import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds import qualified	ToolShed.SelfValidate @@ -90,11 +92,7 @@ 	:: ConsumptionBounds.DataLength	-- ^ The actual quantity of data consumed. 	-> ConsumptionProfile		-- ^ The bounds within which data-consumption is required to fall. 	-> Bool-withinConsumptionBounds dataLength MkConsumptionProfile {-	consumptionBounds	= (minConsumption, maxConsumption)-} = dataLength >= minConsumption && case maxConsumption of-	Nothing	-> True-	Just m	-> dataLength <= m+withinConsumptionBounds dataLength	= uncurry (&&) . ((dataLength >=) *** Data.Maybe.maybe True (dataLength <=)) . consumptionBounds  -- | Both minimum & maximum set to zero; which can be used as the initial value when accumulating the sum of a list. zero :: ConsumptionProfile
src/RegExDot/DSL.hs view
@@ -107,9 +107,9 @@ 	* Accounts for the unusual requirement to place an 'Anchor.Stern' at the start of the 'RegEx.Concatenation', or an 'Anchor.Bow' at the end. -} (<~>)-	:: (Maybe Anchor.Anchor, Maybe Anchor.Anchor)	-- ^ A specification for the anchors required around the expression.-	-> RegEx.Concatenation a			-- ^ The bare list of repeatable patterns to anchor.-	-> RegEx.ExtendedRegEx a			-- ^ The completed regex.+	:: Anchor.AnchorSpecification	-- ^ A specification for the anchors required around the expression.+	-> RegEx.Concatenation a	-- ^ The bare list of repeatable patterns to anchor.+	-> RegEx.ExtendedRegEx a	-- ^ The completed regex. (bow, stern) <~> concatenation = RegEx.MkExtendedRegEx { 	RegEx.bowAnchor		= bow, 	RegEx.concatenation	= concatenation,
src/RegExDot/RegEx.hs view
@@ -21,7 +21,7 @@  [@DESCRIPTION@]  	* This implementation of extended /regex/es, generalises the familiar concept of pattern-matching of character-strings, to matching lists composed from an arbitrary data-type.-	The polymorphic data, from which the input data-list is composed, need only support @Eq@ & @Show@.+	The polymorphic data, from which the input data-list is composed, need only support @Eq@.  	* Because of the unknown stringified form of the underlying polymorphic data, 	the /regex/ must be described by a comparatively verbose bracketed & comma-separated list, rather than the traditional /String/ containing Meta-characters.@@ -241,7 +241,12 @@ 	-> Alternatives m transformAlternatives f	= MkAlternatives . f . deconstructAlternatives -instance (ShortcutExpander m, Meta.ShortcutExpander m, Eq m, Read m) => Read (Alternatives m)	where+instance (+	ShortcutExpander	m,+	Meta.ShortcutExpander	m,+	Eq			m,+	Read			m+ ) => Read (Alternatives m)	where 	readsPrec _ (' ' : s)	= reads s	--Consume white-space. 	readsPrec _ ('\t' : s)	= reads s	--Consume white-space. 	readsPrec _ s		= case reads s of@@ -274,7 +279,7 @@ 	* 'True' if there's no possibility, that the specified input datum, can be consumed by any of the specified 'MetaDataList'.  	* Because data may not be consumed, perhaps because of unsuitable 'ConsumptionBounds.ConsumptionBounds', the converse doesn't hold,-	ie @not isUnconsumableByAnyOf@ /doesn't/ imply that the input datum can be consumed, just that it hasn't been proven that it can't.+	i.e. @not isUnconsumableByAnyOf@ /doesn't/ imply that the input datum can be consumed, just that it hasn't been proven that it can't. -} isUnconsumableByAnyOf :: Eq m 	=> m			-- ^ The input datum.@@ -292,7 +297,12 @@ 	| CaptureGroup (Alternatives m)	-- ^ A sub-expression containing a selection of recursively defined alternatives, thus forming a tree-structure. 	deriving Eq -instance (ShortcutExpander m, Meta.ShortcutExpander m, Eq m, Read m) => Read (Pattern m)	where+instance (+	Eq			m,+	Meta.ShortcutExpander	m,+	Read			m,+	ShortcutExpander	m+ ) => Read (Pattern m)	where 	readsPrec _ (' ' : s)	= reads s	--Consume white-space. 	readsPrec _ ('\t' : s)	= reads s	--Consume white-space. 	readsPrec _ ('(' : s)	= case {-Alternatives.-} reads s of@@ -361,7 +371,7 @@ {- | 	* Represents a black hole, which will greedily consume all data. -	* CAVEAT: nullary, ie a constant.+	* CAVEAT: nullary, i.e. a constant. -} (.*) :: RepeatablePattern m (.*)	= Repeatable.zeroOrMore anyDatum@@ -408,7 +418,12 @@ 	-> Transformation m transformExtendedRegEx f extendedRegEx	= extendedRegEx { concatenation	= f $ concatenation extendedRegEx } -instance (ShortcutExpander m, Meta.ShortcutExpander m, Eq m, Read m) => Read (ExtendedRegEx m)	where+instance (+	Eq			m,+	Meta.ShortcutExpander	m,+	Read			m,+	ShortcutExpander	m+ ) => Read (ExtendedRegEx m)	where 	readsPrec _ []			= [] 	readsPrec _ (' ' : s)		= reads s	--Consume white-space. 	readsPrec _ ('\t' : s)		= reads s	--Consume white-space.@@ -419,7 +434,7 @@ 			| otherwise					-> error $ ToolShed.SelfValidate.getFirstError extendedRegEx	--Parsed OK, but invalid. 		_							-> []								--No parse. 		where---			singleton :: (ShortcutExpander m, Meta.ShortcutExpander m, Eq m, Read m) => [(ExtendedRegEx m, String)]+--			singleton :: (Eq m, Meta.ShortcutExpander m, Read m, ShortcutExpander m) => [(ExtendedRegEx m, String)] 			singleton = [ 				( 					MkExtendedRegEx {@@ -432,7 +447,7 @@ 					(maybeBowAnchor, s1)		<- readsMaybeAnchor s, 					(concatenation', s2)		<- reads s1, 					(maybeSternAnchor, remainder)	<- readsMaybeAnchor s2-			 ] where+			 ] {-list-comprehension-} where 				readsMaybeAnchor :: ReadS (Maybe Anchor.Anchor) 				readsMaybeAnchor s'	= return {-to List-monad-} $ case reads s' of 					[pair]	-> Control.Arrow.first Just pair@@ -490,7 +505,7 @@ hasSternAnchor :: ExtendedRegEx m -> Bool hasSternAnchor	= (== Just Anchor.Stern) . sternAnchor --- | True if there's at least one 'RepeatablePattern' in the 'Concatenation', ie that it's non-null.+-- | True if there's at least one 'RepeatablePattern' in the 'Concatenation', i.e. that it's non-null. isDefined :: ExtendedRegEx m -> Bool isDefined	= not . null . concatenation @@ -498,7 +513,7 @@ mkNullMatchFromExtendedRegEx :: ConsumptionBounds.DataLength -> ExtendedRegEx m -> MatchList m mkNullMatchFromExtendedRegEx offset	= mkNullMatchFromConcatenation offset . concatenation --- | The set of distinct (ie unique) 'Meta.Meta', in the specified 'ExtendedRegEx'.+-- | The set of distinct (i.e. unique) 'Meta.Meta', in the specified 'ExtendedRegEx'. getDistinctMetaDataFromExtendedRegEx :: Eq m => ExtendedRegEx m -> MetaDataList m getDistinctMetaDataFromExtendedRegEx	= getDistinctMetaDataFromConcatenation . concatenation @@ -581,7 +596,7 @@ 	* One could waste a lot of time trying to consume 'InputData' from the head of a high-'Consumer.starHeight' 'ExtendedRegEx', 	only to find that there's a low-'Consumer.starHeight' tail that can't ever match the 'InputData'; checks this first before delegating. -}-findMatch :: (Eq m, NFData m, Show m)+findMatch :: (Eq m, NFData m) 	=> RegExOpts.RegExOpts (ExtendedRegEx m)	-- ^ The match-options parameterised by the regex against which to match the input data. 	-> InputData m					-- ^ The input data within which to locate a match. 	-> Maybe (MatchList m)@@ -613,7 +628,7 @@ 			concatenation	= lowStarHeightTail, 			sternAnchor	= Nothing 		} --Check for mismatch with the corresponding tail of 'InputData'.-	]		= {-Unsafe.printShow "Tail-mismatch:\t"-} Nothing+	]		= Nothing 	| otherwise	= findMatchSlave originalConcatenation ( 		Consumer.accumulateConsumptionProfiles originalConcatenation 	) (@@ -632,21 +647,18 @@  Whilst the only strictly necessary parameters are the lists 'Concatenation' & 'InputData', many ancillary lists derived from them, are also passed by parameter.  These are proportionally reduced on recursion, to avoid the requirement to regenerate them each time they're required. -}-		findMatchSlave :: (-			Eq m,-			NFData m,-			Show m-		 )	=> Concatenation m					--The list of 'RepeatablePattern's from which the regex is constructed.+		findMatchSlave :: (Eq m, NFData m)+			=> Concatenation m					--The list of 'RepeatablePattern's from which the regex is constructed. 			-> ConsumptionProfile.AccumulatedConsumptionProfiles	--The capacity-bounds for the consumption of 'InputData', that the 'Concatenation' extending right from any given 'RepeatablePattern', can consume. 			-> [MetaDataList m]					--The set of distinct 'Meta.Meta'-data, in the 'Concatenation extending right from any given 'RepeatablePattern'. 			-> InputData m						--The input data, which will be fed to the 'Concatenation'. 			-> ConsumptionBounds.DataLength				--The length of the previously specified 'InputData'. 			-> [InputData m]					--The set of distinct input data, extending right from any given point. 			-> Maybe (MatchList m)-		findMatchSlave [] _ _ [] _ _	= {-Unsafe.printShow "Dead heat:\t" $-} Just []	--Simultaneous exhaustion of the 'Concatenation' of 'RepeatablePattern's & the 'InputData' => success.-		findMatchSlave [] _ _ _ _ _	= {-Unsafe.printShow "Excess data:\t"-} Nothing+		findMatchSlave [] _ _ [] _ _	= Just []	--Simultaneous exhaustion of the 'Concatenation' of 'RepeatablePattern's & the 'InputData' => success.+		findMatchSlave [] _ _ _ _ _	= Nothing 		findMatchSlave concatenation'@(repeatablePatternHead : concatenationTail) (accumulatedConsumptionProfileHead : accumulatedConsumptionProfilesTail) (distinctMetaDataHead : distinctMetaDataTail) inputData inputDataLength distinctInputData@(distinctInputDataHead : _)-			| not $ inputDataLength `ConsumptionProfile.withinConsumptionBounds` accumulatedConsumptionProfileHead	= {-Unsafe.printShow "outside ConsumptionBounds:\t"-} Nothing+			| not $ inputDataLength `ConsumptionProfile.withinConsumptionBounds` accumulatedConsumptionProfileHead	= Nothing 			| null inputData	= Just $ mkNullMatchFromConcatenation inputDataOffset concatenation'	--Build a 'Match', of null 'InputData'. 			| and [ 				ExecutionOptions.bypassInputDataForLiberalConsumer executionOptions,			--We may be able to establish success, without evaluating 'inputData' any further than required to determine its length.@@ -657,34 +669,32 @@ 				ExecutionOptions.checkForUnconsumableData executionOptions, 				not $ ConsumptionProfile.canConsumeAnything accumulatedConsumptionProfileHead,	--Otherwise the subsequent test will always fail. 				(`isUnconsumableByAnyOf` distinctMetaDataHead) `any` distinctInputDataHead	--Occasionally failure is both inevitable & obvious.-			] = {-Unsafe.printShow ("Unconsumable data=" ++ show inputData ++ ":\t")-} Nothing+			] = Nothing 			| otherwise	= {-#SCC "findMatchSlave" #-} let 				tailConsumptionProfile :: ConsumptionProfile.ConsumptionProfile 				tailConsumptionProfile@( 					ConsumptionProfile.MkConsumptionProfile { 						ConsumptionProfile.consumptionBounds	= (minConsumptionConcatenationTail, maybeMaxConsumptionConcatenationTail) 					}-				 ) = {-Unsafe.printShow "tailConsumptionProfile:\t" $-} head accumulatedConsumptionProfilesTail	--Extract the aggregate consumption-profile, of the tail of the 'Concatenation'.+				 ) = head accumulatedConsumptionProfilesTail	--Extract the aggregate consumption-profile, of the tail of the 'Concatenation'.  				maxDataAvailable :: ConsumptionBounds.DataLength 				maxDataAvailable	= inputDataLength - minConsumptionConcatenationTail	--The maximum data available to match 'repeatablePatternHead'. 			in if maxDataAvailable < 0-				then {-Unsafe.printShow ("Excess Concatenation=" ++ show concatenation' ++ ":\t")-} Nothing+				then Nothing 				else {-inputData is sufficient for concatenationTail-} let 					Repeatable.MkRepeatable { 						Repeatable.base			= base, 						Repeatable.repetitionBounds	= (fewest, most), 						Repeatable.isGreedy		= isGreedy-					} = {-Unsafe.printShow "repeatablePatternHead:\t"-} repeatablePatternHead	--Completely deconstruct the 'Repeatable' at the head of the 'Concatenation'.+					} = repeatablePatternHead	--Completely deconstruct the 'Repeatable' at the head of the 'Concatenation'. {-  Find the maximum sequence of inputData, preceding the first of the mandatory requirements of 'concatenationTail'.  This enables one to more tightly constrain the maximum number of repetitions of a 'RepeatablePattern',  which consequently reduces the subsequent requirement to back-track. -} --					maximumDataBeforePegs :: Maybe (InputData m)-					maximumDataBeforePegs	= {-#SCC "maximumDataBeforePegs" #-} reverse (-						{-Unsafe.printShow "minimumRequirement:\t" $-} extractMinimumRequirementFromConcatenation concatenationTail-					 ) `maximumDataAfterPegs` reverse inputData	where+					maximumDataBeforePegs	= {-#SCC "maximumDataBeforePegs" #-} reverse (extractMinimumRequirementFromConcatenation concatenationTail) `maximumDataAfterPegs` reverse inputData	where {-  Extract those 'RepeatablePattern's which must match at least once.  Singleton 'Alternatives' are flattened by replication, & non-singleton 'Alternatives' removed, allowing a reduction of the list's base-type to just 'Repeatable.Repeatable' 'Meta.Meta'.@@ -730,12 +740,12 @@  Once the repetition-range has been narrowed, iterate from the appropriate end of the range (depending on 'isGreedy'), extract the corresponding length from inputData, & check for a match. -} --							maybeMatchList :: [Maybe (MatchList m)]-							maybeMatchList	= {-#SCC "maybeMatchList" #-} dropWhile Data.Maybe.isNothing . {-Unsafe.printShow "maybeMatchList:\t" .-} map (+							maybeMatchList	= {-#SCC "maybeMatchList" #-} dropWhile Data.Maybe.isNothing . map ( 								\(consumedInputData, unconsumedInputData)	-> let 									consumedInputDataLength :: ConsumptionBounds.DataLength-									consumedInputDataLength	= {-Unsafe.printShow "consumedInputDataLength:\t" $-} length consumedInputData+									consumedInputDataLength	= length consumedInputData 								in (-									Tree.Leaf (repeatablePatternHead, inputDataOffset, {-Unsafe.printShow "consumedInputData:\t"-} consumedInputData) :+									Tree.Leaf (repeatablePatternHead, inputDataOffset, consumedInputData) : 								) <$> {-apply to Maybe Functor-} findMatchSlave concatenationTail accumulatedConsumptionProfilesTail distinctMetaDataTail unconsumedInputData ( 									inputDataLength - consumedInputDataLength 								) (@@ -743,12 +753,12 @@ 								) --Recurse, to check whether the 'unconsumedInputData' tail also matches. 							 ) $ let 								fewestData, mostData, mostData' :: Repeatable.Repetitions-								fewestData	= {-#SCC "fewestData" #-} {-Unsafe.printShow "fewestData:\t" $-} case maybeMaxConsumptionConcatenationTail of+								fewestData	= {-#SCC "fewestData" #-} case maybeMaxConsumptionConcatenationTail of 									Just m	-> (inputDataLength - m) {- :: ConsumptionBounds.DataLength-} `max` fewest {- :: Repeatable.Repetitions-}	--CAVEAT: conceptually different types. 									_	-> fewest  --								mostData	= length . takeWhile (~= meta) $ (`take` inputData) maxData	--As slow as it is concise.-								mostData	= {-#SCC "mostData" #-} {-Unsafe.printShow "mostData:\t" $-} maxData - measureUnmatchableTail inputData maxData	where+								mostData	= {-#SCC "mostData" #-} maxData - measureUnmatchableTail inputData maxData	where 									maxData :: ConsumptionBounds.DataLength 									maxData	= case most of 										Just cap	-> cap {- :: Repeatable.Repetitions-} `min` maxDataAvailable {- :: ConsumptionBounds.DataLength-}	--CAVEAT: conceptually different types.@@ -772,8 +782,8 @@ 										isGreedy,		--Otherwise, since the search proceeds from 'fewest' to 'most', the optimal solution is located before backtracking. 										mostData > fewestData	--Otherwise, there's no unbridled greed to moderate. 									] = case maximumDataBeforePegs of-										Just maximumDataBeforePegs'	-> {-Unsafe.printShow ("Reducing mostData=" ++ show mostData ++ " ->\t") $-} mostData `min` length maximumDataBeforePegs'	--Cap upper bound.-										_				-> {-Unsafe.printShow "Peg match-failure:\t" $-} negate 1	--Guaranteed to be < 'fewestData'.+										Just maximumDataBeforePegs'	-> mostData `min` length maximumDataBeforePegs'	--Cap upper bound.+										_				-> negate 1	--Guaranteed to be < 'fewestData'. 									| otherwise {-no requirement for this optimisation-}	= mostData 							 in ( 								succ {-fence-post-} mostData' - fewestData	--CAVEAT: possibly <= 0.@@ -788,7 +798,7 @@ 							not isGreedy, 							fewest <= 0,	--Zero repetitions permissible. 							Data.Maybe.isJust tailMatch-						] {-Unsafe.printShow "Trying zero alternatives:\t"-}	-> zeroRepetitions	--Zero repetitions is the optimal solution, rendering the choice of Alternative irrelevant.+						] -> zeroRepetitions	--Zero repetitions is the optimal solution, rendering the choice of Alternative irrelevant. 						| and [ 							ExecutionOptions.catchIncompatibleAnchors executionOptions, 							fewest > 1,			--Multiple repetitions.@@ -802,7 +812,7 @@  Either way, if the user requires data-capture, then for POSIX-compliance we must perform an exhaustive search of the O(Alternatives ^ Repetitions) permutations for the optimal solution; though the search may be narrowed as we proceed. -} --							matchPairList :: [(Match m, MatchList m)]-							matchPairList	= {-#SCC "matchPairList" #-} Data.Maybe.catMaybes . {-Unsafe.printShow "matchPairList:\t" .-}+							matchPairList	= {-#SCC "matchPairList" #-} Data.Maybe.catMaybes . #if MIN_VERSION_parallel(3,0,0) 							 concat . Control.Parallel.Strategies.parMap Control.Parallel.Strategies.rseq	--Particularly effective when 'not ExecutionOptions.requireMatchList'. #else@@ -850,7 +860,7 @@ 												sternAnchor	= Just Anchor.Stern 											 } 												then maybeMatchPairList-												else {-Unsafe.printShow ("Bypassing " ++ show (length maybeMatchPairList) ++ " repetitions; ")-} []	--Abandon further repetitions of 'Alternatives'.+												else []	--Abandon further repetitions of 'Alternatives'. 											_ {-Alternative is OK, or there's no subsequent attempt to bypass-}		-> maybeMatchPairList 										else {-optimisation not required-} maybeMatchPairList 								) . map (@@ -921,15 +931,15 @@ 													concatenationFromAlternative {-expand 1st repetition-} ++ replicate remainingRepetitions {-potentially zero-} singletonRepeatable	--Enumerate all remaining repetitions of ANY Alternative; a different Alternative can match for each repetition. 												) 									in {-#SCC "collater" #-} collater <$> {-apply to Maybe Functor-} findMatchSlave (-										{-Unsafe.printShow ("Expanded Alternatives for repetitions=" ++ show repetitions ++ ":\t") $-} expandedConcatenationPrefix ++ concatenationTail+										expandedConcatenationPrefix ++ concatenationTail 									) ( 										ConsumptionProfile.accumulateFrom tailConsumptionProfile {-initial value-} consumptionProfileExpandedConcatenationPrefix ++ tail accumulatedConsumptionProfilesTail 									) (-										{-Unsafe.printShow "MetaDataList:\t" $-} accumulateDistinctMetaDataFrom (head distinctMetaDataTail) {-initial value-} expandedConcatenationPrefix ++ tail distinctMetaDataTail+										accumulateDistinctMetaDataFrom (head distinctMetaDataTail) {-initial value-} expandedConcatenationPrefix ++ tail distinctMetaDataTail 									) inputData inputDataLength distinctInputData	--Recurse to get 'Maybe (MatchList a)'.-								) {-. Unsafe.printShow ("Range for " ++ show concatenationFromAlternative ++ ":\t")-} $ if Repeatable.isPrecise repeatablePatternHead	--These are frequently generated by the previous recursion, as a trial expansion of an Alternative.+								) $ if Repeatable.isPrecise repeatablePatternHead	--These are frequently generated by the previous recursion, as a trial expansion of an Alternative. 									then if ExecutionOptions.validateMinConsumptionOfAlternatives executionOptions && maxDataAvailable < fewest * minConsumptionAlternatives-										then {-Unsafe.printShow "Insufficient data:\t"-} []	--Failure is inevitable.+										then []	--Failure is inevitable. 										else [fewest] 									else {-imprecise range-} let {-@@ -939,7 +949,7 @@  The range can be narrowed more aggressively, for the special case of a singleton 'Alternative', as used in a capture-group. -} 										fewestAlternatives, mostAlternatives, mostAlternatives' :: Repeatable.Repetitions-										fewestAlternatives	= {-#SCC "fewestAlternatives" #-} {-Unsafe.printShow "fewestAlternatives:\t" $-} 1 {-zero is handled later-} `max` if any Data.Maybe.isNothing [maybeMaxConsumptionConcatenationTail, maybeMaxConsumptionAlternatives]+										fewestAlternatives	= {-#SCC "fewestAlternatives" #-} 1 {-zero is handled later-} `max` if any Data.Maybe.isNothing [maybeMaxConsumptionConcatenationTail, maybeMaxConsumptionAlternatives] 											then fewest 											else {-no unlimited capacities-} let 												minDataAvailable, maxConsumptionAlternatives :: ConsumptionBounds.DataLength@@ -956,11 +966,11 @@ 													minDataAvailable'	= minDataAvailable - Data.Maybe.fromJust maybeMaxConsumptionConcatenationFromAlternative	--CAVEAT: potentially negative. 												in if maxConsumptionAlternatives == 0						--Denominator. 													then {-no Alternative can consume anything-} if minDataAvailable' <= 0	--Numerator.-														then {-zero unconsumable data-} {-Unsafe.printShow "0/0 => fewestAlternatives:\t"-} fewest	--Repeat to meet the minimum requirement.+														then {-zero unconsumable data-} fewest	--Repeat to meet the minimum requirement. 														else {-unconsumable data-} maxBound	--Failure is inevitable. 													else {-non-zero => can divide-} max fewest . succ {-account for expanded instance-} $ minDataAvailable' /+ maxConsumptionAlternatives -										mostAlternatives	= {-#SCC "mostAlternatives" #-} {-Unsafe.printShow "mostAlternatives:\t" $-} case most of+										mostAlternatives	= {-#SCC "mostAlternatives" #-} case most of 											Just cap	-> cap `min` mostPermissibleRepetitions	--Create a ceiling above which the calculated number of permissible repetitions can't rise. 											_		-> mostPermissibleRepetitions 											where@@ -998,13 +1008,13 @@ 											minConsumptionAlternatives > 0		--Otherwise, any number of repetitions can occur without necessarily triggering back-tracking. 										 ] 											then case maximumDataBeforePegs of-												Just maximumDataBeforePegs'	-> {-Unsafe.printShow ("Reducing mostAlternatives=" ++ show mostAlternatives ++ "\t-> ") $-} mostAlternatives `min` (+												Just maximumDataBeforePegs'	-> mostAlternatives `min` ( 													length maximumDataBeforePegs' `div` minConsumptionAlternatives 												 ) --Cap upper bound.-												_				-> {-Unsafe.printShow "Peg match-failure:\t" $-} negate 1	--Guaranteed to be < 'fewestAlternatives'.+												_				-> negate 1	--Guaranteed to be < 'fewestAlternatives'. 											else {-no requirement for this optimisation-} mostAlternatives 									in [fewestAlternatives .. mostAlternatives']	--The permissible repetition-range of any Alternative, constrained by the amount of data available, after subtracting fixed consumption-requirements.-							 ) $ {-Unsafe.printShow "extendedRegExList:\t" .-} (+							 ) . ( 								if ExecutionOptions.permitReorderingOfAlternatives executionOptions {-  The order in which 'Alternatives' are evaluated, should make no difference to the final result; unless 'ExecutionOptions.useFirstMatchAmongAlternatives'.@@ -1026,8 +1036,8 @@ 							 ) extendedRegExAlternatives 						in if null matchPairList 							then if fewest <= 0-								then {-Unsafe.printShow "Trying zero Alternatives:\t"-} zeroRepetitions	--Which might still fail, depending on 'tailMatch'.-								else {-zero repetitions isn't permissible-} {-Unsafe.printShow "Alternatives-mismatch:\t"-} Nothing+								then zeroRepetitions	--Which might still fail, depending on 'tailMatch'.+								else {-zero repetitions isn't permissible-} Nothing 							else {-at least one Alternative matched-} {-#SCC "selectAlternative" #-} Just . uncurry (:) {-re-join head & tail-} $ ( {-  At least one 'Match' has been found amongst the combinations of repetitions of various 'Alternatives',@@ -1039,7 +1049,7 @@ 									then head 									else snd {-remove prepended selection-criterion-} . Data.List.maximumBy {-select the best match-} ( 										Data.Ord.comparing fst	--Compare using only the criterion, not the result from which it was derived.-									) . {-Unsafe.printShow "Ranked matchPairList:\t" .-} map (+									) . map ( 										( {-  If the primary selection-criterion doesn't resolve the choice between candidate 'Match'es, I employ these ad-hoc criteria.@@ -1118,7 +1128,7 @@ 	* CAVEAT: much more expensive then '=~': in /ghci/, 'Just' can be observed to be printed /long/ before the 'MatchList' from which 'Result' is constructed, 	as the lazy algorithm finds the first solution, but not yet necessarily the optimal solution, amongst 'Alternatives'. -}-(+~) :: (Eq m, NFData m, Show m)+(+~) :: (Eq m, NFData m) 	=> InputData m					-- ^ The input data within which to locate a match. 	-> RegExOpts.RegExOpts (ExtendedRegEx m)	-- ^ The match-options parameterised by the regex against which to match the input data. 	-> Result m@@ -1150,14 +1160,14 @@ 	the discovery of /any/ solution is sufficient to generate the return-value; 	lazy-evaluation avoids the requirement to identify the irrelevant optimal solution. -}-(=~) :: (Eq m, NFData m, Show m)+(=~) :: (Eq m, NFData m) 	=> InputData m					-- ^ The input data within which to locate a match. 	-> RegExOpts.RegExOpts (ExtendedRegEx m)	-- ^ The match-options parameterised by the regex against which to match the input data. 	-> Bool inputData =~ regExOpts	= Data.Maybe.isJust $ fmap drift (RegExOpts.setVerbose False regExOpts) `findMatch` inputData  -- | Pattern-mismatch operator.-(/~) :: (Eq m, NFData m, Show m)+(/~) :: (Eq m, NFData m) 	=> InputData m					-- ^ The input data within which to locate a match. 	-> RegExOpts.RegExOpts (ExtendedRegEx m)	-- ^ The match-options parameterised by the regex against which to match the input data. 	-> Bool
src/RegExDot/Repeatable.hs view
@@ -132,9 +132,9 @@ 	one b	--The default; there's no concept of greediness here.  ) $ do 	repeatable	<- Parsec.choice [-		(Parsec.char oneOrMoreToken <?> "Repeatable.oneOrMoreToken " ++ show oneOrMoreToken)	>> return {-to GenParser-monad-} (oneOrMore b),-		(Parsec.char zeroOrOneToken <?> "Repeatable.zeroOrOneToken " ++ show zeroOrOneToken)	>> return {-to GenParser-monad-} (zeroOrOne b),-		(Parsec.char zeroOrMoreToken <?> "Repeatable.zeroOrMoreToken " ++ show zeroOrMoreToken)	>> return {-to GenParser-monad-} (zeroOrMore b),+		(Parsec.char oneOrMoreToken <?> "Repeatable.oneOrMoreToken " ++ show oneOrMoreToken)	>> return {-to ParsecT-monad-} (oneOrMore b),+		(Parsec.char zeroOrOneToken <?> "Repeatable.zeroOrOneToken " ++ show zeroOrOneToken)	>> return {-to ParsecT-monad-} (zeroOrOne b),+		(Parsec.char zeroOrMoreToken <?> "Repeatable.zeroOrMoreToken " ++ show zeroOrMoreToken)	>> return {-to ParsecT-monad-} (zeroOrMore b), 		(b ^#->#) {-arbitrarily greedy for now-} <$> uncurry Parsec.between (ToolShed.Data.Pair.mirror Parsec.char rangeDelimiters) ( 			do 				fewest	<- Parsec.spaces >> (read <$> Parsec.many1 Parsec.digit <?> "Repetition-range minimum")@@ -148,16 +148,16 @@ 							Just . read <$> Parsec.many1 Parsec.digit	<?> "Repetition-range maximum" 						 ) -						Parsec.spaces >> return {-to GenParser-monad-} i+						Parsec.spaces >> return {-to ParsecT-monad-} i 				 ) -				return {-to GenParser-monad-} (fewest, most)+				return {-to ParsecT-monad-} (fewest, most) 		) <?> "Repeatable.rangeDelimiters " ++ show rangeDelimiters 	 ] -	g	<- Parsec.option True {-the default-} $ (Parsec.char nonGreedyToken <?> "Repeatable.nonGreedyToken " ++ show nonGreedyToken) >> return {-to GenParser-monad-} False+	g	<- Parsec.option True {-the default-} $ (Parsec.char nonGreedyToken <?> "Repeatable.nonGreedyToken " ++ show nonGreedyToken) >> return {-to ParsecT-monad-} False -	return {-to GenParser-monad-} repeatable { isGreedy = g }	--Correct prior assumption.+	return {-to ParsecT-monad-} repeatable { isGreedy = g }	--Correct prior assumption.  instance Read a => Read (Repeatable a)	where 	readsPrec _ s	= case reads s {-first, read the base-type-} of