diff --git a/README.markdown b/README.markdown
new file mode 100644
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,23 @@
+# **RegExDot**.
+
+This is **RegExDot**, a polymorphic regex-engine.
+
+## Installation
+
+It can be built and installed using [Cabal](https://www.haskell.org/cabal/users-guide/installing-packages.html).
+
+## Documentation
+
+More information about this library can be found at [RegExDot](http://functionalley.eu/RegExDot/regExDot.html).
+
+## License
+
+For information on copying and distributing this package, see the file **LICENSE** in this directory.
+
+## Bug-reporting
+
+Bug-reports should be emailed to <regexdot *at* functionalley *dot* eu>.
+
+## Author
+
+This library is written and maintained by Dr. Alistair Ward.
diff --git a/changelog b/changelog
deleted file mode 100644
--- a/changelog
+++ /dev/null
@@ -1,47 +0,0 @@
-2010-11-18 Dr. Alistair Ward <regexdot at functionalley dot eu>
-
-0.9.0.0
-	* First version of the package.
-0.10.0.0
-	* Reacted to major-number changes in the package 'ToolShed-0.10.0.0'.
-	* Created "src/RegExDot/" sub-directory & then modified module-names accordingly.
-	* Pacified 'hlint'.
-	* Added a makefile.
-	* Removed awkward unary operators from 'Repeatable.hs'.
-	* Qualified identifiers used in error-messages.
-0.10.0.1
-	* Ported to ghc-7.0.1:
-		Used definitions of 'NFData' & 'rnf' from new package 'deepseq', rather than 'parallel'.
-		Replaced reference to the deprecated function 'Control.Parallel.Strategies.parFlatMap' with @concat . Control.Parallel.Strategies.parMap@.
-0.10.1.0
-	* Set @threaded@ flag to @True@ by default.
-	* Replaced use of @threaded@-flag in source-code, with CABAL CPP-macro.
-	* Relocated "RegExDot.Options" to "ToolShed.Options".
-0.10.2.0
-	* Renamed package from 'RegExDot' to 'regexdot', for compatibility with Debian's ".deb"-format.
-0.10.2.1
-	* Added manually controlled "llvm" flag to "regexdot.cabal".
-	* Changed identifier for type-parameters, to better reflect its role.
-	* Reacted to the creation of module "ToolShed.Defaultable".
-	* Uploaded to <http://hackage.haskell.org/packages/hackage.html>.
-0.10.2.2
-	* Amended 'regexdot.cabal' to more correctly specify dependency on package 'toolshed'.
-	* Used new module "ToolShed.Pair" from package toolshed-0.12.0.0.
-	* Guarded 'eager-blackholing' flag in cabal file.
-0.11.0.0
-	* Replaced '(+ 1)' and '(- 1)' with the faster calls 'succ' and 'pred', in "RegExDot.RegEx".
-	* Reacted to new module-hierarchy, creation of new module "ToolShed.Data.List.Splits" and addition of method 'ToolShed.SelfValidate.getErrors', in toolshed-0.13.0.0, and used it to improved error-reporting in @instance Read RegExDot.RegEx.ExtendedRegEx@.
-	* Minor reworking of 'RegExDot.Repeatable.repeatableParser'.
-	* 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'.
-0.11.1.1
-	* Tested with 'haskell-platform-2013.2.0.0'.
-	* Replaced preprocessor-directives with 'build-depends' constraints in 'regexdot.cabal'.
-	* In function 'RegExDot.RegEx.findMatch.findMatchSlave.matchPairList', changed 'fromIntegral' (which required a type-signature) to 'toRational'.
-	* Either replaced instances of '(<$>)' with 'fmap' to avoid ambiguity between "Control.Applicative" & "Prelude" which (from 'base-4.8') also exports this symbol, or hid the symbol when importing the "Prelude"..
diff --git a/changelog.markdown b/changelog.markdown
new file mode 100644
--- /dev/null
+++ b/changelog.markdown
@@ -0,0 +1,53 @@
+# 2010-11-18 Dr. Alistair Ward <regexdot at functionalley dot eu>
+
+## 0.9.0.0
+	* First version of the package.
+## 0.10.0.0
+	* Reacted to major-number changes in the package **ToolShed-0.10.0.0**.
+	* Created **src/RegExDot/** sub-directory & then modified module-names accordingly.
+	* Pacified **hlint**.
+	* Added a makefile.
+	* Removed awkward unary operators from **Repeatable.hs**.
+	* Qualified identifiers used in error-messages.
+## 0.10.0.1
+	* Ported to ghc-7.0.1:
+		Used definitions of `NFData` & `rnf` from new package **deepseq**, rather than **parallel**.
+		Replaced reference to the deprecated function `Control.Parallel.Strategies.parFlatMap` with `concat . Control.Parallel.Strategies.parMap`.
+## 0.10.1.0
+	* Set @threaded@ flag to @True@ by default.
+	* Replaced use of @threaded@-flag in source-code, with CABAL CPP-macro.
+	* Relocated **RegExDot.Options** to **ToolShed.Options**.
+## 0.10.2.0
+	* Renamed package from **RegExDot** to **regexdot**, for compatibility with Debian's *.deb*-format.
+## 0.10.2.1
+	* Added manually controlled **llvm** flag to the *.cabal*-file.
+	* Changed identifier for type-parameters, to better reflect its role.
+	* Reacted to the creation of module **ToolShed.Defaultable**.
+	* Uploaded to [Hackage](http://hackage.haskell.org/packages/hackage.html).
+## 0.10.2.2
+	* Amended the *.cabal*-file to more correctly specify dependency on package **toolshed**.
+	* Used new module **ToolShed.Pair** from package **toolshed-0.12.0.0**.
+	* Guarded **eager-blackholing** flag in the *.cabal*-file.
+## 0.11.0.0
+	* Replaced `(+ 1)` and `(- 1)` with the faster calls `succ` and `pred`, in **RegExDot.RegEx**.
+	* Reacted to new module-hierarchy, creation of new module **ToolShed.Data.List.Splits** and addition of method `ToolShed.SelfValidate.getErrors`, in **toolshed-0.13.0.0**, and used it to improved error-reporting in `instance Read RegExDot.RegEx.ExtendedRegEx`.
+	* Minor reworking of `RegExDot.Repeatable.repeatableParser`.
+	* 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`.
+## 0.11.1.1
+	* Tested with **haskell-platform-2013.2.0.0**.
+	* Replaced preprocessor-directives with **build-depends** constraints in the *.cabal*-file.
+	* In function `RegExDot.RegEx.findMatch.findMatchSlave.matchPairList`, changed `fromIntegral` (which required a type-signature) to `toRational`.
+	* Either replaced instances of `(<$>)` with `fmap` to avoid ambiguity between **Control.Applicative** & **Prelude** which (from **base-4.8**) also exports this symbol, or hid the symbol when importing the **Prelude**..
+## 0.11.1.2
+	* Added **Default-language**-specification to the *.cabal*-file.
+	* Added file **README.markdown**.
+	* Converted this file to markdown-format.
+	* Renamed directory **src/** to **src-lib/** for consistency with other packages. 
+	* Used **CPP** to control the import of symbols from **Control.Applicative**.
diff --git a/copyright b/copyright
--- a/copyright
+++ b/copyright
@@ -5,7 +5,7 @@
 	Copyright (C) 2010-2011 Dr. Alistair Ward. All Rights Reserved.
 
 Home-page:
-	http://functionalley.eu
+	http://functionalley.eu/RegExDot/regExDot.html
 
 License:
 	GNU GENERAL PUBLIC LICENSE Version 3; see '/usr/share/common-licenses/GPL-3' or '/usr/share/doc/licenses/gpl-3.0.txt' where available, or the local packaged file 'LICENSE'.
diff --git a/makefile b/makefile
deleted file mode 100644
--- a/makefile
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (C) 2010-2014 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/>.
-
-.PHONY: all build check clean configure copy haddock help hlint install prof sdist
-
-all: install
-
-install: build haddock
-	@[ -z "$$CABAL_INSTALL_OPTIONS" ] || echo "INFO: CABAL_INSTALL_OPTIONS='$$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 $@ $$CABAL_COPY_OPTIONS
-
-build: configure
-	@[ -z "$$CABAL_BUILD_OPTIONS" ] || echo "INFO: CABAL_BUILD_OPTIONS='$$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 $@ $$CABAL_CONFIGURE_OPTIONS	#--user
-
-haddock: configure
-	PATH=~/.cabal/bin:$$PATH runhaskell Setup $@ --hyperlink-source	#Amend path to find 'HsColour', as required for 'hyperlink-source'.
-
-hlint:
-	@$@ -i 'Use &&' src/ -i 'Use ||' +RTS -N
-
-sdist:
-	TAR_OPTIONS='--format=ustar' runhaskell Setup $@
-
-check: sdist
-	cabal upload --check --verbose=3 dist/*.tar.gz;
-
-clean:
-	runhaskell Setup $@
-	find src -type f \( -name '*.hc' -o -name '*.hcr' -o -name '*.hi' -o -name '*.o' \) -delete
-
-help:
-	@grep '^[a-zA-Z].*:' makefile | sed -e 's/:.*//'
-
-rpm: regexdot.rpm build
-
diff --git a/regexdot.cabal b/regexdot.cabal
--- a/regexdot.cabal
+++ b/regexdot.cabal
@@ -1,30 +1,51 @@
--- Package-properties
-Name:			regexdot
-Version:		0.11.1.1
-Cabal-Version:		>= 1.6
-Copyright:		(C) 2010-2015 Dr. Alistair Ward
-License:		GPL
-License-file:		LICENSE
-Author:			Dr. Alistair Ward
-Stability:		Unstable interface, incomplete features.
-Synopsis:		A polymorphic, POSIX, extended regex-engine.
-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, GHC == 7.4, GHC == 7.6, GHC == 7.10
-Homepage:		http://functionalley.eu
-Maintainer:		regexdot <at> functionalley <dot> eu
-Bug-reports:		regexdot <at> functionalley <dot> eu
-Extra-Source-Files:	changelog, copyright, makefile
+-- This file is part of RegExDot.
+--
+-- RegExDot 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.
+--
+-- RegExDot 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 RegExDot.  If not, see <http://www.gnu.org/licenses/>.
 
--- Turn on using: 'runhaskell ./Setup.hs configure -f llvm'.
+Name:		regexdot
+Version:	0.11.1.2
+Cabal-version:	>= 1.10
+Copyright:	(C) 2010-2015 Dr. Alistair Ward
+License:	GPL
+License-file:	LICENSE
+Author:		Dr. Alistair Ward
+Stability:	stable
+Synopsis:	A polymorphic, POSIX, extended regex-engine.
+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, GHC == 7.4, GHC == 7.6, GHC == 7.8, GHC == 7.10
+Homepage:	http://functionalley.eu/RegExDot/regExDot.html
+Maintainer:	mailto <colon> regexdot <at> functionalley <dot> eu
+Bug-reports:	mailto <colon> regexdot <at> functionalley <dot> eu
+
+-- None of these files are needed at run-time.
+Extra-source-files:
+    changelog.markdown
+    copyright
+    README.markdown
+
+-- Enable using: 'cabal configure -f llvm'.
 flag llvm
     Description:	Whether the 'llvm' compiler-backend has been installed and is required for code-generation.
-    manual:		True
-    default:		False
+    Manual:		True
+    Default:		False
 
 Library
-    hs-source-dirs:	src
+    Default-language:	Haskell2010
+    GHC-options:	-Wall -O2 -fno-warn-tabs
+    Hs-source-dirs:	src-lib
 
     Exposed-modules:
         RegExDot.Anchor
@@ -54,8 +75,6 @@
         parallel >= 3.0,
         parsec == 3.*,
         toolshed >= 0.13
-
-    GHC-options:	-Wall -O2 -fno-warn-tabs
 
     if impl(ghc >= 7.4.1)
         GHC-prof-options:	-prof -fprof-auto -fprof-cafs
diff --git a/src-lib/RegExDot/Anchor.hs b/src-lib/RegExDot/Anchor.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/Anchor.hs
@@ -0,0 +1,90 @@
+{-
+	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
+
+import qualified	Control.DeepSeq
+
+-- | 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 Control.DeepSeq.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)
+
diff --git a/src-lib/RegExDot/BracketExpression.hs b/src-lib/RegExDot/BracketExpression.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/BracketExpression.hs
@@ -0,0 +1,63 @@
+{-
+	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@]
+
+	This concept was traditionally known as a /Character-class/,
+	but to distinguish it from the more recently introduced & narrower /POSIX Character-class/, it has been renamed /Bracket-expression/.
+-}
+
+module RegExDot.BracketExpression(
+-- * Types
+-- ** Type-synonyms
+	BracketExpression,
+-- * Constants
+	delimiterTokens,
+	negationToken,
+	tokens,
+-- * Functions
+-- ** Predicates
+	containsMatch
+) where
+
+import			RegExDot.BracketExpressionMember((=~))
+import qualified	RegExDot.BracketExpressionMember	as BracketExpressionMember
+
+-- | A /Bracket-expression/ consists of a list of 'BracketExpressionMember.Member's.
+type BracketExpression m	= [BracketExpressionMember.Member m]
+
+-- | True if the specified datum matches any 'BracketExpressionMember.Member' of the 'BracketExpression'.
+containsMatch :: Eq m
+	=> m			-- ^ The input datum.
+	-> BracketExpression m	-- ^ The list of bracket-expression members within which to find a match.
+	-> Bool
+containsMatch datum	= any (datum =~)
+
+-- | The delimiters of a /bracket-expression/, when in 'String'-form.
+delimiterTokens :: (Char, Char)
+delimiterTokens	= ('[', ']')
+
+-- | Used to denote a negated /bracket-expression/, when in 'String'-form.
+negationToken :: Char
+negationToken	= '^'
+
+-- | The set of 'Char' to which a specific meaning is attributed, when reading from 'String'.
+tokens :: String
+tokens	= [fst delimiterTokens, snd delimiterTokens, negationToken]
+
diff --git a/src-lib/RegExDot/BracketExpressionMember.hs b/src-lib/RegExDot/BracketExpressionMember.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/BracketExpressionMember.hs
@@ -0,0 +1,93 @@
+{-
+	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@]
+
+	Permits /Perl-style shortcut/s to be canned & assigned a single-'Char' mnemonic for subsequent reference;
+	the implementation of 'Read' looks for a back-slashed 'Char', for which it expects there to be a corresponding canned 'ShowablePredicate.ShowablePredicate'.
+
+ [@CAVEATS@]
+
+	Since the underlying polymorphic data-type isn't required to implement neither 'Enum' nor 'Ord', the implementation of 'Read' can't cope with range-specifications.
+	Lacking this, Bracket-expression members must be enumerated exhaustively.
+-}
+
+module RegExDot.BracketExpressionMember(
+-- * Type-classes
+	ShortcutExpander(..),
+-- * Types
+-- ** Data-types
+	Member(..),
+-- * Functions
+-- ** Operators
+	(=~)
+) where
+
+import qualified	Control.Arrow
+import qualified	Control.DeepSeq
+import qualified	RegExDot.ShowablePredicate	as ShowablePredicate
+
+infix 4 =~	-- Same as (==).
+
+{- |
+	* The interface via which /Perl-style shortcut/s are expanded (when they occur within a /bracket-expression/), in a manner appropriate to the chosen type-parameter.
+
+	* The expansion of /Perl-style shortcut/s, is more restricted inside than outside, a /bracket-expression/,
+	& consequently are merely represented here by a 'ShowablePredicate.ShowablePredicate', rather than providing a more general form suitable also for those /Perl-style shortcuts/ found outside /bracket-expression/s.
+
+	* This interface is implemented elsewhere, where the specific type-parameter & consequently the appropriate set of /Perl-style shortcut/s, are defined.
+-}
+class ShortcutExpander a	where
+	findPredicate	:: Char -> Maybe (ShowablePredicate.ShowablePredicate a)	-- ^ Attempt to find the appropriate 'ShowablePredicate.ShowablePredicate' to implement this /Perl-style shortcut/.
+
+{- |
+	* A /BracketExpression/ can contain either a literal, a range of literals given @(Enum a, Ord a)@, a /Perl-style shortcut/, or when 'Char' is the type-parameter, a /POSIX Character-class/.
+
+	* This data-type reduces the representation of all these possibilities to either a predicate or a literal.
+-}
+data Member m	=
+	Predicate (ShowablePredicate.ShowablePredicate m)	-- ^ This 'Member' is described using a /predicate/, which is run to determine whether the datum conforms & is a member of the "BracketExpression".
+	| Literal m						-- ^ This 'Member' is defined literally, using an item of the polymorphic type.
+	deriving Eq
+
+instance Show m => Show (Member m)	where
+	showsPrec _ (Predicate showablePredicate)	= shows showablePredicate
+	showsPrec _ (Literal literal)			= shows literal
+
+instance (ShortcutExpander m, Read m) => Read (Member m)	where
+	readsPrec _ []				= []		-- No parse.
+	readsPrec _ (' ' : s)			= reads s	-- Consume white-space.
+	readsPrec _ ('\t' : s)			= reads s	-- Consume white-space.
+	readsPrec _ ('\\' : shortcut : s)	= case findPredicate shortcut of
+		Just showablePredicate	-> [(Predicate showablePredicate, s)]
+		_			-> error $ "readsPrec RegExDot.BracketExpressionMember.Member:\tfindPredicate failed for shortcut " ++ show shortcut
+	readsPrec _ literal			= Control.Arrow.first Literal `map` reads literal
+
+instance Control.DeepSeq.NFData m => Control.DeepSeq.NFData (Member m)	where
+	rnf (Predicate showablePredicate)	= Control.DeepSeq.rnf showablePredicate
+	rnf (Literal literal)			= Control.DeepSeq.rnf literal
+
+-- | Match-operator.
+(=~) :: Eq m
+	=> m		-- ^ The input datum.
+	-> Member m	-- ^ The member of the bracket-expression against which the input-datum is to be matched.
+	-> Bool		-- ^ The result of the match-operation.
+datum =~ Predicate showablePredicate	= ShowablePredicate.predicate showablePredicate datum
+datum =~ Literal literal		= datum == literal
+
diff --git a/src-lib/RegExDot/CompilationOptions.hs b/src-lib/RegExDot/CompilationOptions.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/CompilationOptions.hs
@@ -0,0 +1,48 @@
+{-
+	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@]
+
+	* Defines those options relating to compile-time.
+
+	* These tend to be options which affect the result, rather than the means by which it is achieved.
+
+	* Whilst similar structures are present in other regex-implementations, there's no standardisation of the fields.
+-}
+
+module RegExDot.CompilationOptions(
+-- * Types
+-- ** Data-types
+	CompilationOptions(..)
+) where
+
+import qualified	ToolShed.Defaultable
+import qualified	ToolShed.Options
+
+-- | The switch(es) used to control compilation of the /regex/-engine.
+data CompilationOptions	= MkCompilationOptions {
+	complyStrictlyWithPosix	:: Bool		-- ^ Define the offset of captured data, corresponding to a sub-expression which matched zero times, as the artificial value @-1@ specified by POSIX.
+} deriving (Eq, Show)
+
+instance ToolShed.Defaultable.Defaultable CompilationOptions	where
+	defaultValue	= ToolShed.Options.blankValue { complyStrictlyWithPosix	= True }
+
+instance ToolShed.Options.Options CompilationOptions	where
+	blankValue	= MkCompilationOptions { complyStrictlyWithPosix = undefined }
+
diff --git a/src-lib/RegExDot/Consumer.hs b/src-lib/RegExDot/Consumer.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/Consumer.hs
@@ -0,0 +1,105 @@
+{-
+	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@]
+
+	* Define the requirements & capabilities of a data-type which is designed to consume data.
+
+	* This module also facilitates investigation of group-behaviour, by defining operations on either concatenations or alternations of 'Consumer's.
+
+	* This module is specifically for use in a /regex/-engine,
+	in which the meta-data from which the /regex/ is composed, are considered to /consume/ input data,
+	whilst concatenation & alternation of such elements, behave as a different types of groups of consumer.
+-}
+
+module RegExDot.Consumer(
+-- * Type-classes
+	Consumer(..),
+-- * Types
+-- ** Type-synonyms
+--	StarHeight,
+-- * Functions
+	accumulateConsumptionProfiles,
+--	accumulateConsumptionProfilesFrom,
+	aggregateConsumptionProfilesFromAlternatives,
+	aggregateConsumptionProfilesFromConcatenation,
+-- ** Query
+	getConsumptionBounds,
+	getFewest,
+	getHasSpecificRequirement
+) where
+
+import			RegExDot.ConsumptionProfile((<>), (|+|))
+import qualified	Data.List
+import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
+import qualified	RegExDot.ConsumptionProfile	as ConsumptionProfile
+
+{- |
+	* A measure of the complexity of a /regex/, which has some baring on either the time-complexity or the space-complexity of the solution.
+
+	* <http://en.wikipedia.org/wiki/Star_height>
+-}
+type StarHeight	= Int
+
+{- |
+	* The interface, to which types, which have a data-requirement, may conform.
+
+	* Regrettably, methods requiring reference to the type of the consumable, would require multi-parameter type-classes.
+
+	* 'consumptionProfile' defines the quantity-range of data which may be consumed, & any specific data-requirements.
+
+	* 'starHeight' measures the complexity of the 'Consumer'.
+-}
+class Consumer c	where
+	consumptionProfile	:: c -> ConsumptionProfile.ConsumptionProfile
+	starHeight		:: c -> StarHeight
+
+instance Consumer c => Consumer [c] where
+	consumptionProfile	= undefined
+	starHeight		= Data.List.foldl' (\l -> max l . starHeight) 0
+
+-- | Convenience-function, to query the 'ConsumptionBounds.ConsumptionBounds' of a 'Consumer'.
+getConsumptionBounds :: Consumer c => c -> ConsumptionBounds.ConsumptionBounds
+getConsumptionBounds	= ConsumptionProfile.consumptionBounds . consumptionProfile
+
+-- | Determine the minimum acceptable quantity of data.
+getFewest :: Consumer c => c -> ConsumptionBounds.DataLength
+getFewest	= fst . getConsumptionBounds
+
+-- | Determine whether the specified 'Consumer', has a specific requirement.
+getHasSpecificRequirement :: Consumer c => c -> Bool
+getHasSpecificRequirement	= ConsumptionProfile.hasSpecificRequirement . consumptionProfile
+
+-- | The aggregate of the specified alternation of 'ConsumptionProfile.ConsumptionProfile's.
+aggregateConsumptionProfilesFromAlternatives :: Consumer c => [c] -> ConsumptionProfile.ConsumptionProfile
+aggregateConsumptionProfilesFromAlternatives []	= error "RegExDot.Consumer.aggregateConsumptionProfilesFromAlternatives:\tnull list"
+aggregateConsumptionProfilesFromAlternatives l	= Data.List.foldl1' (<>) $ consumptionProfile `map` l
+
+-- | Get the 'ConsumptionProfile.ConsumptionProfile's for the specified list of 'Consumer's, then find the net effect of concatenating them.
+aggregateConsumptionProfilesFromConcatenation :: Consumer c => [c] -> ConsumptionProfile.ConsumptionProfile
+aggregateConsumptionProfilesFromConcatenation	= Data.List.foldl' (\acc -> (acc |+|) . consumptionProfile) ConsumptionProfile.zero {-initial value-}
+
+-- | Get the 'ConsumptionProfile.ConsumptionProfile' for the specified list of 'Consumer's, then accumulate them, from the specified initial value.
+accumulateConsumptionProfilesFrom :: Consumer c => ConsumptionProfile.ConsumptionProfile -> [c] -> ConsumptionProfile.AccumulatedConsumptionProfiles
+accumulateConsumptionProfilesFrom	= scanr ((|+|) . consumptionProfile)
+
+-- | Get the 'ConsumptionProfile.ConsumptionProfile' for the specified list of 'Consumer's, then accumulate them.
+accumulateConsumptionProfiles :: Consumer c => [c] -> ConsumptionProfile.AccumulatedConsumptionProfiles
+accumulateConsumptionProfiles	= {-init .-} accumulateConsumptionProfilesFrom ConsumptionProfile.zero	-- It's useful to leave the initial value at the end of the list.
+
diff --git a/src-lib/RegExDot/ConsumptionBounds.hs b/src-lib/RegExDot/ConsumptionBounds.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/ConsumptionBounds.hs
@@ -0,0 +1,48 @@
+{-
+	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@]	Describes the bounds of data-consumption.
+-}
+
+module RegExDot.ConsumptionBounds(
+-- * Types
+-- ** Type-synonyms
+	ConsumptionBounds,
+	DataLength,
+-- * Constants
+	zero,
+-- * Functions
+-- ** Predicates
+	isPrecise
+) where
+
+-- | A measure of the quantity of an unspecified type of data.
+type DataLength	= Int
+
+-- | The minimum & maximum bounds of potential data-consumption.
+type ConsumptionBounds	= (DataLength, Maybe DataLength)
+
+-- | Exactly zero consumption.
+zero :: ConsumptionBounds
+zero	= (0, Just 0)
+
+-- | Predicate which is 'True' if only a precise quantity of data is consumable; no more, no less.
+isPrecise :: ConsumptionBounds -> Bool
+isPrecise (fewest, most)	= Just fewest == most
+
diff --git a/src-lib/RegExDot/ConsumptionProfile.hs b/src-lib/RegExDot/ConsumptionProfile.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/ConsumptionProfile.hs
@@ -0,0 +1,151 @@
+{-# LANGUAGE CPP #-}
+{-
+	Copyright (C) 2010-2015 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 'RegExDot.ConsumptionProfile' is composed from both a capacity to consume, & an ability to discriminate based on the specific data.
+	The former is described by 'consumptionBounds' & the latter by both 'hasSpecificRequirement' & 'canConsumeAnything'.
+-}
+
+module RegExDot.ConsumptionProfile(
+-- * Types
+-- ** Type-synonyms
+	AccumulatedConsumptionProfiles,
+-- ** Data-types
+	ConsumptionProfile(..),
+-- * Constants
+	zero,
+-- * Functions
+	accumulateFrom,
+	aggregateFromConcatenation,
+-- ** Operators
+	(|+|),
+	(<>),
+-- ** Predicates
+--	isPrecise,
+	withinConsumptionBounds
+) where
+
+import			Control.Arrow((***))
+import qualified	Data.List
+import qualified	Data.Maybe
+import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
+import qualified	ToolShed.SelfValidate
+
+#if !MIN_VERSION_base(4,8,0)
+import	Control.Applicative((<$>), (<*>))
+#endif
+
+infixr 5 |+|	-- Same as (++).
+infixr 2 <>	-- Same as (||).
+
+{- |
+	* A 'Consumer' is considered to have a 'ConsumptionProfile' composed from both a capacity to consume, & an ability to discriminate.
+
+	* Whilst 'hasSpecificRequirement' & 'canConsumeAnything' look like opposites, they can assume independent values; the instance can be both, but only be neither when empty.
+-}
+data ConsumptionProfile	= MkConsumptionProfile {
+	consumptionBounds	:: ConsumptionBounds.ConsumptionBounds,	-- ^ The permissible quantity of data, which can be consumed.
+	hasSpecificRequirement	:: Bool,				-- ^ Whether at least one specific input datum is required.
+	canConsumeAnything	:: Bool					-- ^ Whether at least one arbitrary input datum can be consumed.
+} deriving (Eq, Read, Show)
+
+instance ToolShed.SelfValidate.SelfValidator ConsumptionProfile	where
+	getErrors c@(
+		MkConsumptionProfile {
+			consumptionBounds	= (fewest, most),
+			hasSpecificRequirement	= hasSpecificRequirement',
+			canConsumeAnything	= canConsumeAnything'
+		}
+	 ) = ToolShed.SelfValidate.extractErrors [
+		(fewest < 0, "Negative fewest=" ++ show fewest ++ "."),
+		(
+			case most of
+				Just m	-> m < fewest
+				_	-> False,
+			"Invalid 'most'; " ++ show c ++ "."
+		),
+		(not $ or [c == zero, hasSpecificRequirement', canConsumeAnything'], "Invalid " ++ show c ++ ".")
+	 ]
+
+{-
+-- | True if there's no choice in the quantity of data to consume.
+isPrecise :: ConsumptionProfile -> Bool
+isPrecise	= ConsumptionBounds.isPrecise . consumptionBounds
+-}
+
+-- | Predicate, which is 'True' if the specified data-length, falls within the specified 'ConsumptionBounds.ConsumptionBounds'.
+withinConsumptionBounds
+	:: ConsumptionBounds.DataLength	-- ^ The actual quantity of data consumed.
+	-> ConsumptionProfile		-- ^ The bounds within which data-consumption is required to fall.
+	-> Bool
+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
+zero	= MkConsumptionProfile {
+	consumptionBounds	= ConsumptionBounds.zero,
+	hasSpecificRequirement	= False,
+	canConsumeAnything	= False
+}
+
+-- | The net effect of two concatenated 'ConsumptionProfile's.
+(|+|) :: ConsumptionProfile -> ConsumptionProfile -> ConsumptionProfile
+MkConsumptionProfile {
+	consumptionBounds	= (lf, ls),
+	hasSpecificRequirement	= lh,
+	canConsumeAnything	= lc
+} |+| MkConsumptionProfile {
+	consumptionBounds	= (rf, rs),
+	hasSpecificRequirement	= rh,
+	canConsumeAnything	= rc
+} = MkConsumptionProfile {
+	consumptionBounds	= (lf + rf, (+) <$> ls <*> rs),	-- The sum of those of the concatenation.
+	hasSpecificRequirement	= lh || rh,			-- The concatenation mandates consumption of at least one specific input datum, if either 'ConsumptionProfile' does.
+	canConsumeAnything	= lc || rc			-- The concatenation can consume at least one arbitrary input datum, if either 'ConsumptionProfile' can.
+}
+
+-- | The net effect of two alternative 'ConsumptionProfile's.
+(<>) :: ConsumptionProfile -> ConsumptionProfile -> ConsumptionProfile
+MkConsumptionProfile {
+	consumptionBounds	= (lf, ls),
+	hasSpecificRequirement	= lh,
+	canConsumeAnything	= lc
+} <> MkConsumptionProfile {
+	consumptionBounds	= (rf, rs),
+	hasSpecificRequirement	= rh,
+	canConsumeAnything	= rc
+} = MkConsumptionProfile {
+	consumptionBounds	= (lf `min` rf, max <$> ls <*> rs),	-- Stretched to envelope alternatives.
+	hasSpecificRequirement	= lh && rh,				-- The alternation mandates consumption of at least one specific input datum, if both 'ConsumptionProfile's do.
+	canConsumeAnything	= lc || rc				-- The alternation can consume at least one arbitrary input datum, if either 'ConsumptionProfile' can.
+}
+
+-- | The aggregate of the specified concatenation of 'ConsumptionProfile's.
+aggregateFromConcatenation :: [ConsumptionProfile] -> ConsumptionProfile
+aggregateFromConcatenation	= Data.List.foldl' (|+|) zero {-initial value-}
+
+-- | The 'ConsumptionProfile's of all the aggregated tails of a list of 'Consumer's.
+type AccumulatedConsumptionProfiles	= [ConsumptionProfile]
+
+-- | Accumulate the specified list of 'ConsumptionProfile's, from the specified initial value.
+accumulateFrom :: ConsumptionProfile -> [ConsumptionProfile] -> AccumulatedConsumptionProfiles
+accumulateFrom	= scanr (|+|)
+
diff --git a/src-lib/RegExDot/DSL.hs b/src-lib/RegExDot/DSL.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/DSL.hs
@@ -0,0 +1,117 @@
+{-
+	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@]
+
+	* Defines /binary/ operators, to form a /Domain-specific Language/, by which to compose 'RegEx.Concatenations' from 'RegEx.Pattern's.
+
+	* Each operator quantifies the specified 'RegEx.Pattern', & prepends it to the specified 'RegEx.Concatenation'.
+
+ [@TODO@]	Could @[]@ & 'Meta' be instances of a type-class which has methods (-:) etc.,
+		allowing the former to prepend 'RegEx.captureGroup' & the latter 'RegEx.Require' ?
+
+-}
+
+module RegExDot.DSL(
+-- * Functions
+-- ** Operators
+	(-:),
+	(?:),
+	(??:),
+	(*:),
+	(*?:),
+	(+:),
+	(+?:),
+	( #->#:),
+	( #->#?:),
+	( #->:),
+	( #->?:),
+	( #:),
+	(<~>)
+) where
+
+import			RegExDot.Repeatable((^#->#), (^#->#?), (^#->), (^#->?), (^#))
+import qualified	RegExDot.Anchor		as Anchor
+import qualified	RegExDot.RegEx		as RegEx
+import qualified	RegExDot.Repeatable	as Repeatable
+
+infixr 5 -:, ?:, ??:, *:, *?:, +:, +?:,#->#:, #->#?:, #->:, #->?:, #:, <~>	-- Same as for ':', & lower than Repeatable's operators.
+
+-- | Prepend an unrepeated 'RegEx.Pattern', to the specified 'RegEx.Concatenation'.
+(-:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
+(-:) pattern	= (Repeatable.one pattern :)
+
+-- | Prepend an optional 'RegEx.Pattern', to the specified 'RegEx.Concatenation'.
+(?:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
+(?:) pattern	= (Repeatable.zeroOrOne pattern :)
+
+-- | A /non-greedy/ version of '?:'.
+(??:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
+(??:) pattern	= (Repeatable.zeroOrOne' pattern :)
+
+-- | Prepend a 'RegEx.Pattern', repeatable zero or more times, to the specified 'RegEx.Concatenation'.
+(*:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
+(*:) pattern	= (Repeatable.zeroOrMore pattern :)
+
+-- | A /non-greedy/ version of '*:'.
+(*?:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
+(*?:) pattern	= (Repeatable.zeroOrMore' pattern :)
+
+-- | Prepend a 'RegEx.Pattern', repeatable one or more times, to the specified 'RegEx.Concatenation'.
+(+:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
+(+:) pattern	= (Repeatable.oneOrMore pattern :)
+
+-- | A /non-greedy/ version of '+:'.
+(+?:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
+(+?:) pattern	= (Repeatable.oneOrMore' pattern :)
+
+-- | Prepend a 'RegEx.Pattern', repeated a range of times, to the specified 'RegEx.Concatenation'.
+( #->#:) :: (RegEx.Pattern a, Repeatable.RepetitionBounds) -> RegEx.Concatenation a -> RegEx.Concatenation a
+( #->#:) (pattern, bounds)	= (pattern ^#-># bounds :)
+
+-- | A /non-greedy/ version of '#->#:'.
+( #->#?:) :: (RegEx.Pattern a, Repeatable.RepetitionBounds) -> RegEx.Concatenation a -> RegEx.Concatenation a
+( #->#?:) (pattern, bounds)	= (pattern ^#->#? bounds :)
+
+-- | Prepend a 'RegEx.Pattern', repeated at least a specified number of times, to the specified 'RegEx.Concatenation'.
+( #->:) :: (RegEx.Pattern a, Repeatable.Repetitions) -> RegEx.Concatenation a -> RegEx.Concatenation a
+( #->:) (pattern, fewest)	= (pattern ^#-> fewest :)
+
+-- | A /non-greedy/ version of '#->:'.
+( #->?:) :: (RegEx.Pattern a, Repeatable.Repetitions) -> RegEx.Concatenation a -> RegEx.Concatenation a
+( #->?:) (pattern, fewest)	= (pattern ^#->? fewest :)
+
+-- | Prepend a 'RegEx.Pattern', repeated a precise number of times, to the specified 'RegEx.Concatenation'.
+( #:) :: (RegEx.Pattern a, Repeatable.Repetitions) -> RegEx.Concatenation a -> RegEx.Concatenation a
+( #:) (pattern, r)	= (pattern ^# r :)
+
+{- |
+	* Sandwiches a 'RegEx.Concatenation' between optional 'Anchor.Anchor's to construct a 'RegEx.ExtendedRegEx'.
+
+	* Accounts for the unusual requirement to place an 'Anchor.Stern' at the start of the 'RegEx.Concatenation', or an 'Anchor.Bow' at the end.
+-}
+(<~>)
+	:: 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,
+	RegEx.sternAnchor	= stern
+}
diff --git a/src-lib/RegExDot/DataSpan.hs b/src-lib/RegExDot/DataSpan.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/DataSpan.hs
@@ -0,0 +1,61 @@
+{-
+	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@]	Augments a 'Span.Span', with the specific data concerned.
+-}
+
+module RegExDot.DataSpan(
+-- * Types
+-- ** Type-synonyms
+	DataSpan,
+-- * Functions
+	after,
+	empty,
+	join
+) where
+
+import			Control.Arrow((***))
+import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
+import qualified	RegExDot.Span			as Span
+
+{- |
+	* Augment 'Span.Span' with a copy of the data to which it refers.
+
+	* Similar to <http://hackage.haskell.org/packages/archive/regex-base/latest/doc/html/Text-Regex-Base-RegexLike.html#t%3AMatchText>.
+-}
+type DataSpan a	= ([a], Span.Span)
+
+-- | Constructs an empty instance, located at the specified offset.
+empty :: ConsumptionBounds.DataLength -> DataSpan a
+empty offset	= ([], Span.empty offset)
+
+-- | Returns the furthest extent, i.e. the offset just after the end.
+after :: DataSpan a -> ConsumptionBounds.DataLength
+after	= Span.after . snd
+
+{- |
+	* Condenses a list into a single value.
+
+	* Expects a gap-free, sorted list.
+-}
+join
+	:: ConsumptionBounds.DataLength	-- ^ The offset at which the concatenated match is considered to have occurred.
+	-> [DataSpan a]			-- ^ The list to be concatenated.
+	-> DataSpan a
+join offset	= (concat *** Span.join offset) . unzip
diff --git a/src-lib/RegExDot/DataSpanTree.hs b/src-lib/RegExDot/DataSpanTree.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/DataSpanTree.hs
@@ -0,0 +1,108 @@
+{-
+	Copyright (C) 2010-2015 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@]	Permits transformation of 'RegEx.MatchList', to facilitate standardisation.
+-}
+
+module RegExDot.DataSpanTree(
+-- * Types
+-- ** Type-synonyms
+--	DataSpanTree,
+--	DataSpanTreeList,
+-- * Functions
+	extractCaptureGroups,
+	flattenTreeList,
+	toTreeList
+) where
+
+import qualified	Data.Foldable
+import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
+import qualified	RegExDot.DataSpan		as DataSpan
+import qualified	RegExDot.RegEx			as RegEx
+import qualified	RegExDot.Tree			as Tree
+
+-- | Defines a similar 'Tree.Tree' to 'RegEx.Match', but with different 'Tree.Leaf's.
+type DataSpanTree a	= Tree.Tree (DataSpan.DataSpan a)
+
+-- | Defines a similar structure to 'RegEx.MatchList'.
+type DataSpanTreeList a	= [DataSpanTree a]
+
+-- | Converts a 'RegEx.MatchList' into a 'DataSpanTreeList', by transforming the 'Tree.Leaf's.
+toTreeList :: RegEx.MatchList a -> DataSpanTreeList a
+toTreeList	= map toTree	where
+	toTree :: RegEx.Match a -> DataSpanTree a
+	toTree	= fmap toDataSpan	where
+		toDataSpan :: RegEx.MatchedData a -> DataSpan.DataSpan a
+		toDataSpan (_, inputDataOffset, inputData)	= (inputData, (inputDataOffset, length inputData))
+
+-- | Condenses a 'DataSpanTreeList's into a list of 'DataSpan.DataSpan's, using 'DataSpan.join'.
+flattenTreeList
+	:: ConsumptionBounds.DataLength	-- ^ The offset into the input-data at which a match occurred.
+	-> DataSpanTreeList a		-- ^ The tree to flatten.
+	-> [DataSpan.DataSpan a]
+flattenTreeList _ []				= []
+flattenTreeList offset (tree : treeList)	= flattenedTree : flattenTreeList (DataSpan.after flattenedTree) treeList	where
+--	flattenedTree :: DataSpan.DataSpan a
+	flattenedTree	= DataSpan.join offset $ Data.Foldable.toList tree
+
+{- |
+	* POSIX describes the contents of /capture-groups/, as summarised in <http://www2.research.att.com/~gsf/testregex/>.
+
+	* 'RegEx.Result', is a complete description of the match between 'RegEx.InputData' & RegEx.ExtendedRegEx'; this function extracts a POSIX-conformant list from it.
+
+	* The major differences are, that:
+
+		Only data from parenthesized sub-expressions ('RegEx.Alternatives') is captured.
+
+		Only the /last/ repetition of a repeated sub-expression is returned.
+		<http://www.opengroup.org/onlinepubs/009695399/functions/regcomp.html>.
+
+		The data captured within each parenthesized sub-expression, is summarised as a single 'DataSpan.DataSpan'.
+
+		POSIX specifies a 'Span.Span'-offset of @-1@, for sub-expressions which match zero times; cf sub-expressions which consume nothing, once.
+		<http://www.opengroup.org/onlinepubs/009695399/functions/regcomp.html>.
+		@
+			("ace" Text.Regex.Posix.=~ "a(b)*c(d)?e") :: Text.Regex.Base.RegexLike.MatchArray
+			array (0,2) [(0,(0,3)),(1,(-1,0)),(2,(-1,0))]
+
+			("ace" Text.Regex.Posix.=~ "a(b*)c(d?)e") :: Text.Regex.Base.RegexLike.MatchArray
+			array (0,2) [(0,(0,3)),(1,(1,0)),(2,(2,0))]
+		@
+		I consider this a poor convention, resulting from the focus of POSIX on C, which makes subsequent calculation from the list of 'DataSpan's difficult & error-prone.
+-}
+extractCaptureGroups
+	:: Bool			-- ^ Whether to strictly comply with /POSIX/.
+	-> DataSpanTreeList a	-- ^ The tree-structure from which to extract the capture-groups.
+	-> [DataSpan.DataSpan a]
+extractCaptureGroups complyStrictlyWithPosix	= extractCaptureGroups' 0	where
+	extractCaptureGroups' :: ConsumptionBounds.DataLength -> DataSpanTreeList a -> [DataSpan.DataSpan a]
+	extractCaptureGroups' _ []			= []
+	extractCaptureGroups' offset (tree : treeList)	= let
+--		recurseHorizontallyFrom :: ConsumptionBounds.DataLength -> [DataSpan.DataSpan a]
+		recurseHorizontallyFrom	= (`extractCaptureGroups'` treeList)
+	 in case tree of
+		Tree.Leaf dataSpan	-> recurseHorizontallyFrom $ DataSpan.after dataSpan
+		Tree.Node []		-> DataSpan.empty (if complyStrictlyWithPosix then -1 else offset) : recurseHorizontallyFrom offset	-- POSIX specifies an Span-offset of -1, for sub-expressions which match 0 times; cf sub-expressions which consumes nothing, once.
+		Tree.Node treeLists	-> joinedFlattenedTreeList : (extractCaptureGroups' offset lastMatch {-recurse vertically-} ++ recurseHorizontallyFrom (DataSpan.after joinedFlattenedTreeList))	where
+--			lastMatch :: DataSpanTreeList a
+			lastMatch	= last treeLists	-- <http://www.opengroup.org/onlinepubs/009695399/functions/regcomp.html>.
+
+--			joinedFlattenedTreeList :: DataSpan.DataSpan a
+			joinedFlattenedTreeList	= DataSpan.join offset $ flattenTreeList offset lastMatch
+
diff --git a/src-lib/RegExDot/ExecutionOptions.hs b/src-lib/RegExDot/ExecutionOptions.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/ExecutionOptions.hs
@@ -0,0 +1,102 @@
+{-
+	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@]
+
+	* Defines those options relating to the "RegExDot.RegEx"-runtime.
+
+	* These tend to be options which don't affect the result, only the means by which it is achieved.
+
+	* Whilst similar structures are present in other regex-implementations, there's no standardisation of the fields.
+-}
+
+module RegExDot.ExecutionOptions(
+-- * Types
+-- ** Data-types
+	ExecutionOptions(..),
+-- * Functions
+-- ** Mutators
+	setVerbose
+) where
+
+import qualified	ToolShed.Defaultable
+import qualified	ToolShed.Options
+
+-- | The switches used to control execution of the /regex/-engine.
+data ExecutionOptions	= MkExecutionOptions {
+	abortTrialRepetitionsOnInherentFailure	:: Bool,	-- ^ If an /alternative/ can't match, irrespective of the subsequent /RegExDot.RegEx.Concatenation/, then avoid futile trial /RegExDot.Repeatable.Repetitions/. The converse of 'checkForUnconsumableData'.
+	abortTrialRepetitionsOnZeroConsumption	:: Bool,	-- ^ Check for zero data-consumption by the @n@-th /RegExDot.Repeatable.Repeatable RegExDot.RegEx.CaptureGroup/, before attempting @n+1@.
+	bypassInputDataForLiberalConsumer	:: Bool,	-- ^ Whether to bypass reading of the input data, if the mapping to specific /RegExDot.RegEx.RepeatablePattern/s isn't required, & the /RegExDot.RegEx.ExtendedRegEx/ can consume the required quantity of anything.
+	catchIncompatibleAnchors		:: Bool,	-- ^ Avoid futile trial solutions, involving repetitions of anchored alternatives, which must consume data.
+	checkExistenceOfInelasticTail		:: Bool,	-- ^ If the /RegExDot.RegEx.ExtendedRegEx/ ends in an inelastic (zero /Star-height/) tail, confirm its existence at the end of the /RegExDot.RegEx.InputData/.
+	checkForUnconsumableData		:: Bool,	-- ^ Check whether there's no possibility of consuming some of the input data. The converse of 'abortTrialRepetitionsOnInherentFailure'.
+	moderateGreed				:: Bool,	-- ^ Greedily consume data, only up to the limit beyond which, future requirements would be compromised.
+	permitReorderingOfAlternatives		:: Bool,	-- ^ Permit /RegExDot.RegEx.Alternatives/ to be re-ordered, in an attempt to more quickly locate a result.
+	preferAlternativesWhichFeedTheGreedy	:: Bool,	-- ^ Within the /RegExDot.RegEx.MatchedData/ from which each candidate /RegExDot.RegEx.Match/ amongst sequences of /RegExDot.RegEx.Alternatives/, is ultimately composed, prefer /RegExDot.ConsumptionBounds.ConsumptionBounds/ of /RegExDot.RegEx.InputData/, beyond /RegExDot.Repeatable.getFewest/, by /RegExDot.Repeatable.isGreedy RegExDot.RegEx.RepeatablePattern/s.
+	preferAlternativesWhichMimickUnrolling	:: Bool,	-- ^ Compare /RegExDot.ConsumptionBounds.ConsumptionBounds/ on successive /RegExDot.Repeatable.Repetitions/ of /RegExDot.RegEx.CaptureGroup/, between candidate /RegExDot.RegEx.Match/es, to mimic the behaviour of the unrolled /RegExDot.Repeatable.Repetitions/.
+	preferFewerRepeatedAlternatives		:: Bool,	-- ^ Prefer fewer /RegExDot.Repeatable.Repetitions/ of /RegExDot.RegEx.Alternatives/, to discourage the capture of null lists of /RegExDot.RegEx.InputData/.
+	requireMatchList			:: Bool,	-- ^ If merely interested in a 'Bool' result, rather than the optimal mapping of input data to /RegExDot.RegEx.RepeatablePattern/s, avoid unnecessary evaluation of the /RegEx.Match/.
+	unrollRepeatedSingletonAlternative	:: Bool,	-- ^ Check whether /RegExDot.RegEx.Alternatives/ consists of just a singleton /RegExDot.RegEx.ExtendedRegEx/, & has therefore been used merely as a capture-group. Though this doesn't affect the result, it vastly improves efficiency.
+	useFirstMatchAmongAlternatives		:: Bool,	-- ^ Rather than performing an exhaustive search for the optimal choice amongst /RegExDot.RegEx.Alternatives/, merely select the first that matches; conform to /Perl/ rather than /POSIX/.
+	validateMinConsumptionOfAlternatives	:: Bool		-- ^ When the number of repetitions of a /RegExDot.RegEx.CaptureGroup/ is precisely specified, check whether the resulting minimum data-requirement is available.
+} deriving (Eq, Show)
+
+instance ToolShed.Defaultable.Defaultable ExecutionOptions	where
+	defaultValue	= setVerbose False $ ToolShed.Options.blankValue {
+		abortTrialRepetitionsOnInherentFailure	= True,		-- Regrettably, this slightly reduces performance for most non-pathological patterns.
+		catchIncompatibleAnchors		= True,
+		checkExistenceOfInelasticTail		= True,
+		checkForUnconsumableData		= True,		-- Expensive, particularly when (not requireMatchList), & only typically useful in failure-scenarios.
+		moderateGreed				= True,		-- Cost may exceed benefit. TODO: confirm.
+		preferAlternativesWhichFeedTheGreedy	= True,
+		preferAlternativesWhichMimickUnrolling	= True,
+		preferFewerRepeatedAlternatives		= True,
+		unrollRepeatedSingletonAlternative	= True,		-- Affects only efficiency, not the result.
+		useFirstMatchAmongAlternatives		= False,	-- Perl-style matching may be faster, but may also yield a sub-optimal Match.
+		validateMinConsumptionOfAlternatives	= False		-- The cost outweighs the small infrequent dividend.
+	}
+
+instance ToolShed.Options.Options ExecutionOptions	where
+	blankValue	= MkExecutionOptions {
+		abortTrialRepetitionsOnInherentFailure	= undefined,
+		abortTrialRepetitionsOnZeroConsumption	= undefined,
+		bypassInputDataForLiberalConsumer	= undefined,
+		catchIncompatibleAnchors		= undefined,
+		checkExistenceOfInelasticTail		= undefined,
+		checkForUnconsumableData		= undefined,
+		moderateGreed				= undefined,
+		permitReorderingOfAlternatives		= undefined,
+		preferAlternativesWhichFeedTheGreedy	= undefined,
+		preferAlternativesWhichMimickUnrolling	= undefined,
+		preferFewerRepeatedAlternatives		= undefined,
+		requireMatchList			= undefined,
+		unrollRepeatedSingletonAlternative	= undefined,
+		useFirstMatchAmongAlternatives		= undefined,
+		validateMinConsumptionOfAlternatives	= undefined
+	}
+
+-- | Sets those fields which depend crucially on whether the caller wants to retrieve any /RegExDot.RegEx.MatchList/ from the /RegExDot.RegEx.Result/, or just query whether there is one.
+setVerbose :: Bool -> ExecutionOptions -> ExecutionOptions
+setVerbose verbose e	= e {
+	abortTrialRepetitionsOnZeroConsumption	= verbose,	-- The corresponding check, involves evaluation of a /RegExDot.RegEx.MatchList/, which is too expensive if the /RegExDot.RegEx.Matchlist/ isn't otherwise required.
+	bypassInputDataForLiberalConsumer	= not verbose,	-- Potentially bypasses reading of /RegExDot.RegEx.InputData/, which is inappropriate if the mapping into a /RegExDot.RegEx.Result/ is required.
+	permitReorderingOfAlternatives		= not verbose,	-- Doesn't help when 'requireMatchList', since an exhaustive search of /RegExDot.RegEx.Alternatives/, for the optimal solution, is performed.
+	requireMatchList			= verbose
+}
+
diff --git a/src-lib/RegExDot/InstanceInt.hs b/src-lib/RegExDot/InstanceInt.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/InstanceInt.hs
@@ -0,0 +1,43 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+{-
+	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@]	Provides a default implementation of the type-classes, required for 'RegEx.ExtendedRegEx' Int.
+
+ [@CAVEATS@]
+
+	In contrast to the traditional regex, there's no reason to escape a 'Char', other than when referring to a /shortcut/.
+	Since no /shortcuts/ are defined in this minimal definition, it's always an error to escape a character.
+-}
+
+module RegExDot.InstanceInt() where
+
+import qualified	RegExDot.BracketExpressionMember	as BracketExpressionMember
+import qualified	RegExDot.Meta				as Meta
+import qualified	RegExDot.RegEx				as RegEx
+
+instance BracketExpressionMember.ShortcutExpander Int	where
+	findPredicate _	= Nothing
+
+instance Meta.ShortcutExpander Int	where
+	expand c	= error $ "RegExDot.Meta.ShortcutExpander.expand RegExDot.InstanceInt:\tunrecognised shortcut '" ++ show c ++ "'."	-- A shortcut is the only legitimate reason to escape a character.
+
+instance RegEx.ShortcutExpander Int	where
+	expand c	= error $ "RegExDot.RegEx.ShortcutExpander.expand RegExDot.InstanceInt:\tunrecognised shortcut '" ++ show c ++ "'."	-- A shortcut is the only legitimate reason to escape a character.
+
diff --git a/src-lib/RegExDot/Meta.hs b/src-lib/RegExDot/Meta.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/Meta.hs
@@ -0,0 +1,144 @@
+{-
+	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@]
+
+	* Describes the set of polymorphic data, which can be matched.
+
+	* Only permits a match against exactly one polymorphic datum, which distinguishes it from a /zero-width assertion/, like an /anchor/, /word-boundary/, or /look-ahead assertion/.
+
+	* Designed to be used by a polymorphic /regex/-engine, to implement the traditional meta-characters; @. [] [^]@.
+
+	* Permits /Perl-style shortcuts/ for commonly used 'Meta'-data, to be canned & assigned a single-'Char' mnemonic for subsequent reference;
+	the implementation of 'Read' looks for a back-slashed 'Char', for which it expects there to be a corresponding canned 'Meta'.
+	Since this class is polymorphic, it has no knowledge of what shortcuts might be appropriate for the chosen type-parameter,
+	so the expansion from the back-slashed 'Char' to corresponding 'Meta'-data, is performed through the 'expand' interface of the 'ShortcutExpander' class, which should be implemented elsewhere.
+-}
+
+module RegExDot.Meta(
+-- * Type-classes
+	ShortcutExpander(..),
+-- * Types
+-- ** Data-types
+	Meta(..),
+-- * Constants
+	shortcutToken,
+	anyToken,
+	tokens,
+-- * Functions
+-- ** Predicates
+	isMatch
+) where
+
+import qualified	Control.Arrow
+import qualified	Control.DeepSeq
+import qualified	RegExDot.BracketExpression		as BracketExpression
+import qualified	RegExDot.BracketExpressionMember	as BracketExpressionMember
+import qualified	RegExDot.Consumer			as Consumer
+import qualified	RegExDot.ConsumptionProfile		as ConsumptionProfile
+import qualified	RegExDot.ShowablePredicate		as ShowablePredicate
+import qualified	ToolShed.SelfValidate
+
+{- |
+	* The interface via which /Perl-style shortcut/s are expanded, in a manner appropriate to the chosen type-parameter.
+
+	* Since the expansion of /Perl-style shortcut/s, is more restricted inside than outside a 'BracketExpression.BracketExpression',
+	the former is considered to be a superclass, providing a base from which to build alternative implementations.
+-}
+class BracketExpressionMember.ShortcutExpander m => ShortcutExpander m	where
+	expand	:: Char -> Meta m	-- ^ Expand a /Perl-style shortcut/.
+
+-- | Declares a polymorphic data-type.
+data Meta m =
+	Any							-- ^ Any datum matches. Equivalent to @NoneOf []@, but more efficient. CAVEAT: independent of the type-parameter @a@.
+	| Literal m						-- ^ The datum matches, if it's equal to the specified value. Equivalent to @AnyOf [BracketExpression.Literal x]@, but more efficient.
+	| AnyOf (BracketExpression.BracketExpression m)		-- ^ The datum matches, if 'BracketExpression.containsMatch'.
+	| NoneOf (BracketExpression.BracketExpression m)	-- ^ The datum matches, if @not BracketExpression.containsMatch@.
+	| Predicate (ShowablePredicate.ShowablePredicate m)	-- ^ The datum matches if 'ShowablePredicate.ShowablePredicate'.
+	deriving (
+		Eq
+--		Read,	-- Specialised below.
+--		Show	-- Specialised below.
+	)
+
+instance ToolShed.SelfValidate.SelfValidator (Meta m)	where
+	getErrors _	= []
+
+instance Show m => Show (Meta m)	where
+	showsPrec _ Any					= showChar anyToken
+	showsPrec _ (Literal m)				= shows m
+	showsPrec _ (AnyOf bracketExpression)		= shows bracketExpression
+	showsPrec _ (NoneOf bracketExpression)		= showChar x . showChar BracketExpression.negationToken . showString xs	where (x : xs)	= show $ AnyOf bracketExpression
+	showsPrec _ (Predicate showablePredicate)	= shows showablePredicate
+
+instance (ShortcutExpander m, Read m) => Read (Meta m)	where
+	readsPrec _ []				= []		-- No parse.
+	readsPrec _ (' ' : s)			= reads s	-- Consume white-space.
+	readsPrec _ ('\t' : s)			= reads s	-- Consume white-space.
+	readsPrec _ ('.' : s)			= [(Any, s)]
+	readsPrec _ ('[' : '^' : noneOf)	= Control.Arrow.first NoneOf `map` reads (fst BracketExpression.delimiterTokens : noneOf) {-Reconstruct without negation, & recurse-}
+	readsPrec _ anyOf@('[' : _)		= Control.Arrow.first AnyOf `map` reads anyOf {-singleton-}
+	readsPrec _ ('\\' : c : s)		= [(expand c, s)]
+	readsPrec _ literal			= Control.Arrow.first Literal `map` reads literal {-singleton-}
+
+instance Consumer.Consumer (Meta m)	where
+	consumptionProfile meta	= let
+		hasSpecificDataRequirement :: Bool
+		hasSpecificDataRequirement	= case meta of
+			Any		-> False
+			NoneOf []	-> False
+			_		-> True
+	 in ConsumptionProfile.MkConsumptionProfile {
+		ConsumptionProfile.consumptionBounds		= (1, Just 1),
+		ConsumptionProfile.hasSpecificRequirement	= hasSpecificDataRequirement,
+		ConsumptionProfile.canConsumeAnything		= not hasSpecificDataRequirement
+	 }
+
+	starHeight _	= 0
+
+instance Control.DeepSeq.NFData m => Control.DeepSeq.NFData (Meta m)	where
+	rnf Any					= ()
+	rnf (Literal m)				= Control.DeepSeq.rnf m
+	rnf (AnyOf bracketExpression)		= Control.DeepSeq.rnf bracketExpression
+	rnf (NoneOf bracketExpression)		= Control.DeepSeq.rnf bracketExpression
+	rnf (Predicate showablePredicate)	= Control.DeepSeq.rnf showablePredicate
+
+-- | True if the specified datum matches.
+isMatch :: Eq m
+	=> m		-- ^ The input datum.
+	-> Meta m	-- ^ The meta-entity against which the input datum is to be matched.
+	-> Bool		-- ^ The result of the match-operation.
+isMatch _ Any					= True
+isMatch datum (Literal literal)			= datum == literal
+isMatch datum (AnyOf bracketExpression)		= datum `BracketExpression.containsMatch` bracketExpression
+isMatch datum (NoneOf bracketExpression)	= not $ datum `isMatch` AnyOf bracketExpression	-- This implementation leverages future enhancements to 'AnyOf'.
+isMatch datum (Predicate showablePredicate)	= ShowablePredicate.predicate showablePredicate datum
+
+-- | The token used to precede a /Perl-style shortcut/, when in the 'String'-form.
+shortcutToken :: Char
+shortcutToken	= '\\'
+
+-- | The token used to denote 'Any', when in the 'String'-form.
+anyToken :: Char
+anyToken	= '.'
+
+-- | The set of 'Char' to which a specific meaning is attributed, when reading from 'String'.
+tokens :: String
+tokens	= [shortcutToken, anyToken] ++ BracketExpression.tokens
+
diff --git a/src-lib/RegExDot/RegEx.hs b/src-lib/RegExDot/RegEx.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/RegEx.hs
@@ -0,0 +1,1198 @@
+{-
+	Copyright (C) 2010-2015 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@]
+
+	* 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@.
+
+	* 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.
+	Each element of this 'Concatenation' is a 'RepeatablePattern', which describes a permissible match against 'InputData'.
+
+	* 'RepeatablePattern' can take one of two forms.
+	In the simplest case, it matches just a single item of the underlying polymorphic type, perhaps literally, though looser specifications also exist:
+	@.@ matches any input datum; @[x, y, z]@ matches any of @x@, @y@, or @z@; @[^x, y, z]@ matches anything but @x@, @y@, or @z@.
+	To support POSIX /ERE/s, 'RepeatablePattern' can also be a list 'Alternatives', each of which is recursively defined as an 'ExtendedRegEx', to form a tree-structure.
+
+	* Each 'Pattern', can optionally be /quantified/ by either a traditional /greedy/, or a /Perl/-style /non-greedy/, suffix, e.g.; @[*, +, ?, {n, m}, {n,}, {n}, *?, +?, ??, {n, m}?, {n,}?]@.
+
+	* For convenience, common specifications can be canned & assigned a single 'Char' mnemonic, for subsequent reference.
+	Since 'ExtendedRegEx' is polymorphic, the set of abbreviations appropriate in the context of the unspecified base-type,
+	must be implemented externally through the 'Meta.ShortcutExpander' interface.
+	This permits the use, when the type-parameter is 'Char', of /Perl-style shortcuts/ @[\\d\\D\\s\\S\\w\\W]@.
+
+	* The algorithm, is the classic /back-tracking/ one, rather than either a /DFA/ or /NFA/.
+	This permits construction of 'Result' via which one can discover the deep mapping of 'InputData' into 'ExtendedRegEx',
+	& provides the flexibility to add the features now expected by modern /regex/-engines.
+	Since the type-parameter is unknown, & may represent a large object, the exponential space-complexity of creating a /DFA/ may present additional problems.
+	The exponential time-complexity of the /back-tracking/ algorithm is partially tamed by targeting obvious inefficiencies with specific optimisations.
+
+	* Char-based regexen, traditionally overload the delimiters of a set of 'Alternatives' (parentheses), as a request for data-capture.
+	Here, in contrast, all 'RepeatablePattern's capture data, & repeated sub-expressions capture a list of data,
+	rather than arbitrarily recording just the last (<http://www.opengroup.org/onlinepubs/009695399/functions/regcomp.html>) item.
+
+ [@REFERENCES@]
+
+	* <http://en.wikipedia.org/wiki/Regular_expression>
+
+	* <http://swtch.com/~rsc/regexp/regexp1.html>
+
+	* <http://docstore.mik.ua/orelly/perl/prog/ch02_04.htm#PERL2-CH-2-SECT-4.1.2>
+
+	* <http://www.macs.hw.ac.uk/~dsg/gph/papers/html/Strategies/strategies.html>
+
+	* <http://hackage.haskell.org/packages/archive/regex-posix/latest/doc/html/Text-Regex-Posix.html>
+
+	* <http://www.haskell.org/haskellwiki/Regular_expressions>
+
+	* <http://www2.research.att.com/~gsf/testregex/re-interpretation.html>
+
+ [@CAVEATS@]
+
+	* Because of the definition of mutually recursive data-types, it is difficult to split this annoyingly large module, & preserve compatibility across compilers,
+	but it may be possible to break this cyclic dependency, by defining an interface to which one of the data-types defined here conforms.
+
+	* Doesn't implement /Back-references/, making the definition of the 'ExtendedRegEx' context-free.
+
+	* There's no integration with the type-classes defined in "Text.Regex.Base.RegexLike", which assumes 'Char'-based 'InputData';
+	though this could be added to a specialised instance.
+
+	* When 'Alternatives' are defined, 'Result' becomes a tree-like structure.
+	Unless the alternative is a singleton, the specific alternative selected in the solution is typically unknown, & therefore the /structure/ of the branch of this tree is also unknown.
+	This lack of clarity is compounded when the 'Alternatives' are 'Repeatable.Repeatable', since a different one may be selected on each successive repetition.
+	Consequently, the user can't navigate this portion of the structure in a statically defined manner, to acquire the captured data.
+	Despite this, & in contrast to other /regex/-engines, access to the whole data-structure is available, since it doesn't seem advantage to hide it.
+	The user can then either use 'extractDataFromMatch' for that element of 'Result', thus aggregating the data from sections of unknown structure, or 'show' it, as an aid to debugging.
+
+ [@TODO@]
+
+	* Test parallel-operation, on a 3 or more processor machine.
+	If 'rnf' is less effective than 'rwhnf',
+	then the 'Control.DeepSeq.NFData' context can be removed,
+	reducing the requirements imposed on the type-parameter 'a'.
+
+	* Try 'Data.List.Stream' (stream-fusion), a faster drop-in replacement for 'Data.List'; possibly integrated in GHC-6.12.
+
+	* 'ExecutionOptions.bypassInputDataForLiberalConsumer' is too restrictive.
+	More generally, we can test whether the set of different 'a' in 'InputData', is a subset of those common to all remaining terms in the 'ExtendedRegEx'.
+	Using this rule, we can infer @"aaa ..." =~ MkExtendedRegEx [a,a+,a?,[ab]{2,3}]@, given compatible 'ConsumptionProfile.consumptionBounds'.
+
+	* Nested repetitions, where nothing has been added to the expression, result in repeated trials of the same expression,
+	e.g.; @"(x{i,}){j,}"@ results in the same expansion for @(i, j) in [(2, 3), (3, 2), (6, 1), (1, 6)]@.
+	The resulting 'MatchList' may be different, but if the first such trial fails, so will all the remainder.
+
+	* Should cope with empty sets of 'Alternatives' & zero repetitions, neither of which can ever match, but the wider pattern can, e.g. @(()|x{0}|y)@.
+
+	* By removing 'RepeatablePattern' from 'Match', it can be isolated in a new module.
+	This would result in a significant loss of discoverability.
+
+	* Expand repeated 'Anchor.Bow' with @fewest - 1@ null matches followed by recursive 'findMatch'-call with @repetitions = 1@.
+-}
+
+module RegExDot.RegEx(
+-- * Type-classes
+	ShortcutExpander(..),
+-- * Types
+-- ** Type-synonyms
+--	BasicRegEx,
+	Concatenation,
+	ExternalMatch,
+	InputData,
+	MatchedData,
+	MatchList,
+--	MetaDataList,
+	RepeatablePattern,
+--	Transformation,
+-- ** Data-types
+	Alternatives(..),
+	Match,
+	ExtendedRegEx(..),
+	Pattern(..),
+	Result,
+-- * Constants
+	alternativeExtendedRegExSeparatorToken,
+--	anyDatum,
+	captureGroupDelimiters,
+	tokens,
+-- * Functions
+--	accumulateDistinctInputData,
+--	accumulateDistinctMetaDataFrom,
+	dock,
+--	drift,
+--	findMatch,
+	captureGroup,
+--	mkNullMatchFromConcatenation,
+--	mkNullMatchFromExtendedRegEx,
+--	mkNullMatchFromRepeatablePattern,
+--	safeReciprocal,
+--	shiftMatchedData,
+--	shiftMatch,
+	shiftMatchList,
+	showsMaybeAnchor,
+	simply,
+	transformExtendedRegEx,
+-- ** Accessors (Deconstructors)
+	deconstructAlternatives,
+--	getInputData,
+-- ** Operators
+	(+~),
+	(=~),
+	(/~),
+	(.*),
+	(.*?),
+--	(/+)
+-- ** Predicates
+--	hasBowAnchor,
+--	hasSternAnchor,
+	isDefined,
+	isCaptureGroup,
+	isSingletonAlternatives,
+--	isUnconsumableByAnyOf,
+-- ** Query
+--	getDistinctMetaDataFromAlternatives,
+--	getDistinctMetaDataFromConcatenation,
+--	getDistinctMetaDataFromExtendedRegEx,
+--	getDistinctMetaDataFromPattern,
+--	getDistinctMetaDataFromRepeatablePattern,
+	externalMatchLength,
+	extractDataFromMatch,
+	extractDataFromMatch',
+	extractDataFromMatchList
+) where
+
+import			Control.Arrow((&&&))
+import qualified	Control.Arrow
+import qualified	Control.DeepSeq
+import qualified	Control.Parallel.Strategies
+import qualified	Data.Char
+import qualified	Data.Foldable
+import qualified	Data.List
+import qualified	Data.Maybe
+import qualified	Data.Ord
+import qualified	RegExDot.Anchor			as Anchor
+import qualified	RegExDot.Consumer		as Consumer
+import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
+import qualified	RegExDot.ConsumptionProfile	as ConsumptionProfile
+import qualified	RegExDot.ExecutionOptions	as ExecutionOptions
+import qualified	RegExDot.Meta			as Meta
+import qualified	RegExDot.RegExOpts		as RegExOpts
+import qualified	RegExDot.Repeatable		as Repeatable
+import			RegExDot.Repeatable((^#->))
+import qualified	RegExDot.Tree			as Tree
+import qualified	ToolShed.Data.List
+import qualified	ToolShed.Data.List.Splits
+import qualified	ToolShed.SelfValidate
+
+infix 4 +~, =~, /~	-- Same as (==) & (/=).
+
+-- | The type of a /regex/, in which there's no provision for either 'Alternatives' or 'Anchor.Anchor's.
+type BasicRegEx m	= [Repeatable.Repeatable (Meta.Meta m)]
+
+{- |
+	* Defines the method required to expand a mnemonic into an 'ExtendedRegEx'.
+
+	* CAVEAT: this interface must be declared locally, since it references 'ExtendedRegEx', & 'ExtendedRegEx' references it.
+-}
+class ShortcutExpander m	where
+	expand	:: Char -> ExtendedRegEx m	-- ^ Expand a single-'Char' mnemonic into the corresponding 'ExtendedRegEx'.
+
+{- |
+	* Represents the /alternation/ feature of 'ExtendedRegEx's.
+
+	* One could amalgamate this with 'Pattern', since it seems to exist merely as a peg to hang /instance/-declarations from.
+-}
+newtype Alternatives m	= MkAlternatives [ExtendedRegEx m]	deriving Eq
+
+-- | Accessor, to expose the guts.
+deconstructAlternatives :: Alternatives m -> [ExtendedRegEx m]
+deconstructAlternatives (MkAlternatives extendedRegExList)	= extendedRegExList
+
+-- | Similar to 'fmap', but operates on ['ExtendedRegEx'], rather than just @a@.
+transformAlternatives
+	:: ([ExtendedRegEx m] -> [ExtendedRegEx m])	-- ^ The transformation function to apply to the list of data behind the constructor.
+	-> Alternatives m
+	-> Alternatives m
+transformAlternatives f	= MkAlternatives . f . deconstructAlternatives
+
+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
+		[(extendedRegEx, s1)]	-> case dropWhile Data.Char.isSpace s1 of
+			('|' : s2)	-> Control.Arrow.first (transformAlternatives (extendedRegEx :)) `map` reads s2 {-singleton-}
+			_		-> [(MkAlternatives [extendedRegEx], s1)]
+		_			-> []	-- No parse.
+
+instance Show m => Show (Alternatives m)	where
+	showsPrec _	= foldl (.) (showString "") . Data.List.intersperse (showChar alternativeExtendedRegExSeparatorToken) . map shows . deconstructAlternatives	-- Replace the default list-format, with 'egrep'-syntax.
+
+instance Consumer.Consumer (Alternatives m)	where
+	consumptionProfile	= Consumer.aggregateConsumptionProfilesFromAlternatives . deconstructAlternatives
+	starHeight		= Consumer.starHeight . deconstructAlternatives	-- Must evaluate all Alternatives to determine best.
+
+instance ToolShed.SelfValidate.SelfValidator (Alternatives m)	where
+	getErrors	= ToolShed.SelfValidate.getErrors . deconstructAlternatives
+
+instance Control.DeepSeq.NFData m => Control.DeepSeq.NFData (Alternatives m)	where
+	rnf	= Control.DeepSeq.rnf . deconstructAlternatives
+
+-- | 'Alternatives' can be employed as a simple /capture-group/ as well as a switch, under which circumstances there's no choice amongst multiple 'Alternatives'.
+isSingletonAlternatives :: Alternatives m -> Bool
+isSingletonAlternatives	= (== 1) . length . deconstructAlternatives
+
+-- | A set of 'Meta.Meta' which can be consumed.
+type MetaDataList m	= [Meta.Meta m]
+
+{- |
+	* '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,
+	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.
+	-> MetaDataList m	-- ^ The list of meta-data against any of which a match can occur.
+	-> Bool
+isUnconsumableByAnyOf i	= not . any (Meta.isMatch i)
+
+-- | The set of distinct 'Meta.Meta', in the specified 'Alternatives'.
+getDistinctMetaDataFromAlternatives :: Eq m => Alternatives m -> MetaDataList m
+getDistinctMetaDataFromAlternatives	= foldr (Data.List.union . getDistinctMetaDataFromExtendedRegEx) [] . deconstructAlternatives
+
+-- | Defines either a simple 'Meta.Meta', which can match exactly one datum, or a set of 'Alternatives', each of which is recursively defined above, as an 'ExtendedRegEx'.
+data Pattern m	=
+	Require (Meta.Meta m)		-- ^ Describes a requirement for a simple scalar datum of the polymorphic type.
+	| CaptureGroup (Alternatives m)	-- ^ A sub-expression containing a selection of recursively defined alternatives, thus forming a tree-structure.
+	deriving Eq
+
+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
+		[(alternatives, s1)]	-> case dropWhile Data.Char.isSpace s1 of
+			(')' : s2)	-> [(CaptureGroup alternatives, s2)]
+			_		-> []	-- No parse.
+		_			-> []	-- No parse.
+	readsPrec _ s		= case reads s of
+		[pair]	-> [Control.Arrow.first Require pair]
+		_	-> []	-- No parse.
+
+instance Show m => Show (Pattern m)	where
+	showsPrec _ (Require meta)		= shows meta
+	showsPrec _ (CaptureGroup alternatives)	= showChar (fst captureGroupDelimiters) . shows alternatives . showChar (snd captureGroupDelimiters)
+
+instance Consumer.Consumer (Pattern m)	where
+	consumptionProfile (Require meta)		= Consumer.consumptionProfile meta
+	consumptionProfile (CaptureGroup alternatives)	= Consumer.consumptionProfile alternatives
+
+	starHeight (Require meta)		= Consumer.starHeight meta
+	starHeight (CaptureGroup alternatives)	= Consumer.starHeight alternatives
+
+instance ToolShed.SelfValidate.SelfValidator (Pattern m)	where
+	getErrors (Require meta)		= ToolShed.SelfValidate.getErrors meta
+	getErrors (CaptureGroup alternatives)	= ToolShed.SelfValidate.getErrors alternatives
+
+instance Control.DeepSeq.NFData m => Control.DeepSeq.NFData (Pattern m)	where
+	rnf (Require meta)		= Control.DeepSeq.rnf meta
+	rnf (CaptureGroup alternatives)	= Control.DeepSeq.rnf alternatives
+
+-- | Convenience-function to build a 'CaptureGroup' from a list of alternative 'ExtendedRegEx's.
+captureGroup :: [ExtendedRegEx m] -> Pattern m
+captureGroup	= CaptureGroup . MkAlternatives
+
+-- | True if the 'Pattern' was constructed via 'CaptureGroup'.
+isCaptureGroup :: Pattern m -> Bool
+isCaptureGroup (CaptureGroup _)	= True
+isCaptureGroup _		= False
+
+-- | The set of distinct 'Meta.Meta', in the specified 'Pattern'.
+getDistinctMetaDataFromPattern :: Eq m => Pattern m -> MetaDataList m
+getDistinctMetaDataFromPattern pattern	= case pattern of
+	Require meta			-> [meta]
+	CaptureGroup alternatives	-> getDistinctMetaDataFromAlternatives alternatives
+
+-- | Constant pattern, representing a lax 'Require'ment.
+anyDatum :: Pattern a
+anyDatum	= Require Meta.Any
+
+-- | Make 'Pattern's, 'Repeatable.Repeatable'.
+type RepeatablePattern m	= Repeatable.Repeatable (Pattern m)
+
+-- | Construct a null 'Match' by assuming that the specified 'RepeatablePattern' consumes zero 'InputData'; of which the caller should ensure it's capable.
+mkNullMatchFromRepeatablePattern
+	:: ConsumptionBounds.DataLength	-- ^ The offset into the list of input data at which the zero-length match occurred.
+	-> RepeatablePattern m		-- ^ The pattern that the input data matched.
+	-> Match m			-- ^ The resulting match-structure.
+mkNullMatchFromRepeatablePattern offset r	= case Repeatable.base r of
+	Require _	-> Tree.Leaf (r, offset, [])
+	CaptureGroup _	-> Tree.Node $ Repeatable.getFewest r `replicate` []
+
+-- | The set of distinct 'Meta.Meta', in the specified 'RepeatablePattern'.
+getDistinctMetaDataFromRepeatablePattern :: Eq m => RepeatablePattern m -> MetaDataList m
+getDistinctMetaDataFromRepeatablePattern	= getDistinctMetaDataFromPattern . Repeatable.base
+
+{- |
+	* Represents a black hole, which will greedily consume all data.
+
+	* CAVEAT: nullary, i.e. a constant.
+-}
+(.*) :: RepeatablePattern m
+(.*)	= Repeatable.zeroOrMore anyDatum
+
+-- | A /non-greedy/ version of '.*'.
+(.*?) :: RepeatablePattern m
+(.*?)	= Repeatable.zeroOrMore' anyDatum
+
+-- | Convenience-function, to build a 'RepeatablePattern' from an unrepeated instance of the specified 'Meta.Meta'-datum.
+simply :: Meta.Meta m -> RepeatablePattern m
+simply	= Repeatable.one . Require
+
+-- | Represents the /concatenation/ aspect of 'ExtendedRegEx's.
+type Concatenation m	= [RepeatablePattern m]
+
+-- | Construct a null 'Match' by assuming that the specified 'Concatenation' consumes zero 'InputData'.
+mkNullMatchFromConcatenation
+	:: ConsumptionBounds.DataLength	-- ^ The offset into the list of input data at which the zero-length match occurred.
+	-> Concatenation m		-- ^ The list of repeatable patterns that the input data matched.
+	-> MatchList m			-- ^ The resulting match-structure.
+mkNullMatchFromConcatenation offset	= map $ mkNullMatchFromRepeatablePattern offset
+
+-- | The set of distinct 'Meta.Meta', in the specified 'Concatenation'.
+getDistinctMetaDataFromConcatenation :: Eq m => Concatenation m -> MetaDataList m
+getDistinctMetaDataFromConcatenation	= foldr (Data.List.union . getDistinctMetaDataFromRepeatablePattern) []
+
+-- | The accumulating set of 'MetaDataList', resulting from each successive 'RepeatablePattern' in the specified 'Concatenation'.
+accumulateDistinctMetaDataFrom :: Eq m => MetaDataList m -> Concatenation m -> [MetaDataList m]
+accumulateDistinctMetaDataFrom	= scanr (Data.List.union . getDistinctMetaDataFromRepeatablePattern)
+
+-- | Constructs an 'ExtendedRegEx', by surrounding a 'Concatenation' with optional 'Anchor.Anchor's.
+data ExtendedRegEx m	= MkExtendedRegEx {
+	bowAnchor	:: Maybe Anchor.Anchor,	-- ^ An option to anchor the /regex/ to the start of the 'InputData'.
+	concatenation	:: Concatenation m,	-- ^ The sequence of 'RepeatablePattern's defining the 'Require'ments that the 'InputData' must meet.
+	sternAnchor	:: Maybe Anchor.Anchor	-- ^ An option to anchor the /regex/ to the end of the 'InputData'.
+} deriving Eq
+
+-- | The type of a function which transforms an 'ExtendedRegEx'.
+type Transformation m	= ExtendedRegEx m -> ExtendedRegEx m
+
+-- | Similar to 'fmap', but operates on 'Concatenation', rather than just @a@.
+transformExtendedRegEx
+	:: (Concatenation m -> Concatenation m)	-- ^ The function used to transform the data behind the constructor.
+	-> Transformation m
+transformExtendedRegEx f extendedRegEx	= extendedRegEx { concatenation	= f $ concatenation extendedRegEx }
+
+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.
+	readsPrec _ ('\\' : c : s)	= [(expand c, s)]
+	readsPrec _ s			= case singleton of
+		[(extendedRegEx, _)]
+			| ToolShed.SelfValidate.isValid extendedRegEx	-> singleton
+			| otherwise					-> error $ ToolShed.SelfValidate.getFirstError extendedRegEx	-- Parsed OK, but invalid.
+		_							-> []								-- No parse.
+		where
+--			singleton :: (Eq m, Meta.ShortcutExpander m, Read m, ShortcutExpander m) => [(ExtendedRegEx m, String)]
+			singleton = [
+				(
+					MkExtendedRegEx {
+						bowAnchor	= maybeBowAnchor,
+						concatenation	= concatenation',
+						sternAnchor	= maybeSternAnchor
+					},
+					remainder
+				) |
+					(maybeBowAnchor, s1)		<- readsMaybeAnchor s,
+					(concatenation', s2)		<- reads s1,
+					(maybeSternAnchor, remainder)	<- readsMaybeAnchor s2
+			 ] {-list-comprehension-} where
+				readsMaybeAnchor :: ReadS (Maybe Anchor.Anchor)
+				readsMaybeAnchor s'	= return {-to List-monad-} $ case reads s' of
+					[pair]	-> Control.Arrow.first Just pair
+					_	-> (Nothing, s')
+
+-- | Shows either the specified 'Anchor.Anchor', or a null string where 'Nothing' is specified.
+showsMaybeAnchor :: Maybe Anchor.Anchor -> String -> String
+showsMaybeAnchor maybeAnchor
+	| Data.Maybe.isJust maybeAnchor	= shows $ Data.Maybe.fromJust maybeAnchor
+	| otherwise			= id
+
+instance Show m => Show (ExtendedRegEx m)	where
+	showsPrec _ MkExtendedRegEx {
+		bowAnchor	= maybeBowAnchor,	-- CAVEAT: this could be 'Nothing' or perversely an 'Anchor.Stern'.
+		concatenation	= concatenation',
+		sternAnchor	= maybeSternAnchor	-- CAVEAT: this could be 'Nothing' or perversely an 'Anchor.Bow'.
+	} = showsMaybeAnchor maybeBowAnchor . shows concatenation' . showsMaybeAnchor maybeSternAnchor
+
+instance Consumer.Consumer (ExtendedRegEx m)	where
+	consumptionProfile	= Consumer.aggregateConsumptionProfilesFromConcatenation . concatenation
+	starHeight		= Consumer.starHeight . concatenation
+
+instance ToolShed.SelfValidate.SelfValidator (ExtendedRegEx m)	where
+	getErrors	= ToolShed.SelfValidate.getErrors . concatenation
+
+instance Control.DeepSeq.NFData m => Control.DeepSeq.NFData (ExtendedRegEx m)	where
+	rnf MkExtendedRegEx {
+		bowAnchor	= maybeBowAnchor,
+		concatenation	= concatenation',
+		sternAnchor	= maybeSternAnchor
+	} = Control.DeepSeq.rnf (maybeBowAnchor, concatenation', maybeSternAnchor)
+
+-- | Drop 'Anchor.Anchor's at both bow & stern of the specified 'ExtendedRegEx'.
+dock :: Transformation m
+dock e	= e {
+	bowAnchor	= Just Anchor.Bow,
+	sternAnchor	= Just Anchor.Stern
+}
+
+-- | Amend the 'Concatenation' in the specified 'ExtendedRegEx', by prepending '.*' where there's a missing top-level 'Anchor.Bow' & appending '.*?' where there's a missing top-level 'Anchor.Stern'.
+drift :: Transformation m
+drift extendedRegEx	= transformExtendedRegEx (
+	(
+		if hasBowAnchor extendedRegEx then id else {-no anchor-} ((.*?) :)
+	) . (
+		if hasSternAnchor extendedRegEx then id else {-no anchor-} (++ [(.*)])
+	)
+ ) extendedRegEx
+
+-- | True if the specified 'ExtendedRegEx' has an initial 'Anchor.Bow'. CAVEAT: though typically the alternative is no 'Anchor.Anchor', there may perversely be an initial 'Anchor.Stern', but neither qualify.
+hasBowAnchor :: ExtendedRegEx m -> Bool
+hasBowAnchor	= (== Just Anchor.Bow) . bowAnchor
+
+-- | True if the specified 'ExtendedRegEx' has a terminal 'Anchor.Stern'. CAVEAT: though typically the alternative is no 'Anchor.Anchor', there may perversely be a terminal 'Anchor.Bow', but neither qualify.
+hasSternAnchor :: ExtendedRegEx m -> Bool
+hasSternAnchor	= (== Just Anchor.Stern) . sternAnchor
+
+-- | 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
+
+-- | Construct a null 'Match' by assuming that the specified 'ExtendedRegEx' consumes zero 'InputData'.
+mkNullMatchFromExtendedRegEx :: ConsumptionBounds.DataLength -> ExtendedRegEx m -> MatchList m
+mkNullMatchFromExtendedRegEx offset	= mkNullMatchFromConcatenation offset . concatenation
+
+-- | The set of distinct (i.e. unique) 'Meta.Meta', in the specified 'ExtendedRegEx'.
+getDistinctMetaDataFromExtendedRegEx :: Eq m => ExtendedRegEx m -> MetaDataList m
+getDistinctMetaDataFromExtendedRegEx	= getDistinctMetaDataFromConcatenation . concatenation
+
+{- |
+	* The input-data is just a list.
+
+	* Whilst typically this list is also a 'String', & could therefore be more efficiently implemented using "Data.ByteString",
+	we can't assume that the polymorphic base-type is always 'Char'.
+-}
+type InputData m = [m]
+
+-- | The accumulating sets of distinct input data.
+accumulateDistinctInputData :: Eq m => InputData m -> [InputData m]
+accumulateDistinctInputData	= scanr (Data.List.union . return) []
+
+-- | Tag the 'InputData' with the 'RepeatablePattern' it matched (which unfortunately confines the definition to this (bloated) module), & the offset from the start of the data;
+type MatchedData m	= (RepeatablePattern m, ConsumptionBounds.DataLength, InputData m)
+
+-- | Shifts the offset of the specified 'MatchedData'.
+shiftMatchedData
+	:: ConsumptionBounds.DataLength	-- ^ The offset by which to shift the position into the input-data at which a match occurred.
+	-> MatchedData m		-- ^ The match-structure whose offset is to be shifted.
+	-> MatchedData m
+shiftMatchedData i (r, offset, d)	= (r, offset + i, d)
+
+-- | Accessor.
+getInputData :: MatchedData m -> InputData m
+getInputData (_, _, inputData)	= inputData
+
+-- | Describes the manner in which a 'RepeatablePattern' successfully consumed 'InputData'.
+type Match m	= Tree.Tree (MatchedData m)
+
+-- | Shifts the offsets of all the 'MatchedData' contained in the specified 'Match'.
+shiftMatch
+	:: ConsumptionBounds.DataLength	-- ^ The offset by which to shift the position into the input-data at which a match occurred.
+	-> Match m			-- ^ The match-structure whose offset is to be shifted.
+	-> Match m
+shiftMatch i	= (shiftMatchedData i `fmap`)
+
+-- | Extract & concatenate, the 'InputData' from a 'Match'.
+extractDataFromMatch :: Match m -> InputData m
+extractDataFromMatch	= Data.Foldable.foldMap getInputData	-- Uses the List-monoid's associative binary operator (++), to concatenate the values returned by the specified function.
+
+-- | Extract & concatenate, the 'InputData' from a 'Match'; null if it didn't match any.
+extractDataFromMatch' :: Maybe (Match m) -> InputData m
+extractDataFromMatch' (Just match)	= extractDataFromMatch match
+extractDataFromMatch' _			= []
+
+-- | Describes the manner in which a 'Concatenation' successfully consumed 'InputData'.
+type MatchList m	= [Match m]
+
+-- | Shifts the offsets of all the 'MatchedData' contained in the specified 'MatchList'.
+shiftMatchList
+	:: ConsumptionBounds.DataLength	-- ^ The offset by which to shift the position into the input-data at which a each listed match occurred.
+	-> MatchList m			-- ^ The list of match-structures, each of whose offsets are to be shifted.
+	-> MatchList m
+shiftMatchList i	= map (shiftMatch i)
+
+-- | Extract & concatenate, the 'InputData', from the 'MatchList'.
+extractDataFromMatchList :: MatchList m -> InputData m
+extractDataFromMatchList	= concatMap extractDataFromMatch	-- CAVEAT: too fine-grain for effective data-parallelism.
+
+-- | At the top-level of an 'ExtendedRegEx', the lack of an 'Anchor.Anchor' allows the 'ExtendedRegEx' to drift away from the corresponding end of the input-data; this data-gap is captured here.
+type ExternalMatch m	= Maybe (Match m)
+
+-- | Captures the list of input-data consumed by the 'Concatenation', bracketed by any data-prefix or data-suffix.
+type Result m	= (ExternalMatch m, Maybe (MatchList m), ExternalMatch m)
+
+-- | Returns the length of data consumed by the specified 'ExternalMatch'.
+externalMatchLength :: ExternalMatch m -> ConsumptionBounds.DataLength
+externalMatchLength	= length . extractDataFromMatch'
+
+{- |
+	* Similar to '+~', but exposes 'ExecutionOptions.ExecutionOptions', permitting greater control; & enough rope to hang yourself.
+
+	* The parameter-order facilitates partial application, to acquire a matcher-function for a specific 'ExtendedRegEx', which can be applied repeatedly to different 'InputData'.
+
+	* Performs some one-off @O(n)@ time-complexity preparation, then delegates the grunt-work to a private recursive function.
+
+	* 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, Control.DeepSeq.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)
+findMatch regExOpts@RegExOpts.MkRegExOpts {
+	RegExOpts.executionOptions	= executionOptions,
+	RegExOpts.regEx			= extendedRegEx
+} originalInputData
+	| let
+		extractLowStarHeightTail :: ExtendedRegEx m -> Concatenation m
+		extractLowStarHeightTail	= {-#SCC "extractLowStarHeightTail" #-} fromConcatenation . reverse . concatenation	where
+			fromConcatenation :: Concatenation m -> Concatenation m
+			fromConcatenation []					= []
+			fromConcatenation (repeatablePattern : concatenation')
+				| Consumer.starHeight repeatablePattern == 0	= repeatablePattern : fromConcatenation {-recurse-} concatenation'
+				| Repeatable.getFewest repeatablePattern > 0	= case Repeatable.base repeatablePattern of
+					CaptureGroup alternatives
+						| isSingletonAlternatives alternatives	-> extractLowStarHeightTail {-recurse-} . head $ deconstructAlternatives alternatives
+						| otherwise				-> {-non-singleton-} []
+					_				-> []	-- Zero 'Consumer.StarHeight' would have been detected by 'fromConcatenation'.
+				| otherwise					= []
+
+--		lowStarHeightTail :: Concatenation a
+		lowStarHeightTail	= extractLowStarHeightTail extendedRegEx
+	in and [
+		ExecutionOptions.checkExistenceOfInelasticTail executionOptions,
+		not $ null lowStarHeightTail,	-- Prevent infinite recursion.
+		reverse originalInputData /~ RegExOpts.mkRegEx MkExtendedRegEx {
+			bowAnchor	= Just Anchor.Bow,
+			concatenation	= lowStarHeightTail,
+			sternAnchor	= Nothing
+		} -- Check for mismatch with the corresponding tail of 'InputData'.
+	]		= Nothing
+	| otherwise	= findMatchSlave originalConcatenation (
+		Consumer.accumulateConsumptionProfiles originalConcatenation
+	) (
+		accumulateDistinctMetaDataFrom [] originalConcatenation
+	) originalInputData originalInputDataLength (
+		accumulateDistinctInputData originalInputData
+	)
+	where
+--		originalConcatenation :: Concatenation a
+		originalConcatenation	= concatenation extendedRegEx
+
+		originalInputDataLength :: ConsumptionBounds.DataLength
+		originalInputDataLength	= length originalInputData
+{-
+ This beast takes a lot of parameters.
+ 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, Control.DeepSeq.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 [] _ _ [] _ _	= 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	= 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.
+				not $ ExecutionOptions.requireMatchList executionOptions,				-- Otherwise the precise mapping of the 'inputData' to 'RepeatablePattern's must be determined.
+				not $ ConsumptionProfile.hasSpecificRequirement accumulatedConsumptionProfileHead	-- Otherwise a match for the specific 'Meta'-data must be found.
+			] = Just undefined {-shouldn't be evaluated according to 'ExecutionOptions.requireMatchList'-}
+			| and [
+				ExecutionOptions.checkForUnconsumableData executionOptions,
+				not $ ConsumptionProfile.canConsumeAnything accumulatedConsumptionProfileHead,	-- Otherwise the subsequent test will always fail.
+				(`isUnconsumableByAnyOf` distinctMetaDataHead) `any` distinctInputDataHead	-- Occasionally failure is both inevitable & obvious.
+			] = Nothing
+			| otherwise	= {-#SCC "findMatchSlave" #-} let
+				tailConsumptionProfile :: ConsumptionProfile.ConsumptionProfile
+				tailConsumptionProfile@(
+					ConsumptionProfile.MkConsumptionProfile {
+						ConsumptionProfile.consumptionBounds	= (minConsumptionConcatenationTail, maybeMaxConsumptionConcatenationTail)
+					}
+				 ) = 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 Nothing
+				else {-inputData is sufficient for concatenationTail-} let
+					Repeatable.MkRepeatable {
+						Repeatable.base			= base,
+						Repeatable.repetitionBounds	= (fewest, most),
+						Repeatable.isGreedy		= isGreedy
+					} = 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 (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'.
+ The resulting 'BasicRegEx', with /Kleene Star/s weeded-out & 'Alternatives' pruned, can be matched in O(n)-time, to verify minimal requirements.
+-}
+						extractMinimumRequirementFromConcatenation :: Concatenation m -> BasicRegEx m
+						extractMinimumRequirementFromConcatenation	= concatMap (
+							\repeatablePattern -> case Repeatable.base repeatablePattern of
+								Require datum	-> return {-to List-monad-} repeatablePattern { Repeatable.base = datum }
+								CaptureGroup a
+									| isSingletonAlternatives a	-> concat . replicate (Repeatable.getFewest repeatablePattern) . extractMinimumRequirementFromConcatenation {-recurse-} . concatenation . head $ deconstructAlternatives a
+									| otherwise			-> []
+						 ) . filter ((> 0) . Repeatable.getFewest)
+
+						maximumDataAfterPegs :: Eq m => BasicRegEx m -> InputData m -> Maybe (InputData m)
+						maximumDataAfterPegs pegList@(
+							Repeatable.MkRepeatable {
+								Repeatable.base			= metaPeg,
+								Repeatable.repetitionBounds	= (fewestPeg, _)
+							} : pegListTail
+						 ) inputData'
+							| null remainingInputData && length candidateMatchedInputData < fewestPeg		= Nothing							-- Insufficient data to ever match.
+							| fewestPeg == 1 || (`Meta.isMatch` metaPeg) `all` tail candidateMatchedInputData	= pegListTail `maximumDataAfterPegs` remainingInputData		-- Success => recurse.
+							| otherwise										= pegList `maximumDataAfterPegs` tail candidateInputData	-- Failed candidate => recurse.
+							where
+--								candidateInputData, candidateMatchedInputData, remainingInputData :: InputData a
+								candidateInputData				= dropWhile (not . (`Meta.isMatch` metaPeg)) inputData'
+								(candidateMatchedInputData, remainingInputData)	= fewestPeg `splitAt` candidateInputData
+						maximumDataAfterPegs [] inputData'	= Just inputData'	-- All the pegs have been matched.
+{-
+ Each 'repeatablePatternHead' can either be a 'Require' or a 'CaptureGroup'.
+ The former case needs further reduction & we can proceed to construct a 'Tree.Leaf' from any matching 'inputData'.
+ We attempt to reduce the latter case to an instance of the former, by expanding all combinations of repetitions of various 'Alternatives', constructing a new 'ExtendedRegEx' from each, & recursing.
+-}
+				in case base of
+					Require meta
+						| null maybeMatchList	-> Nothing
+						| otherwise		-> head {-most suitable-} maybeMatchList
+						where
+{-
+ Attempt to narrow the repetition-range, from the potentially unbounded specification, to that which is possible according to,
+ the 'inputDataLength', & the specified consumption-bounds of the remainder of the /regex/.
+ 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 . map (
+								\(consumedInputData, unconsumedInputData)	-> let
+									consumedInputDataLength :: ConsumptionBounds.DataLength
+									consumedInputDataLength	= length consumedInputData
+								in (
+									Tree.Leaf (repeatablePatternHead, inputDataOffset, consumedInputData) :
+								) `fmap` {-apply to Maybe Functor-} findMatchSlave concatenationTail accumulatedConsumptionProfilesTail distinctMetaDataTail unconsumedInputData (
+									inputDataLength - consumedInputDataLength
+								) (
+									consumedInputDataLength `drop` distinctInputData
+								) -- Recurse, to check whether the 'unconsumedInputData' tail also matches.
+							 ) $ let
+								fewestData, mostData, mostData' :: Repeatable.Repetitions
+								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" #-} 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.
+										_		-> maxDataAvailable
+
+--									measureUnmatchableTail :: InputData m -> ConsumptionBounds.DataLength -> ConsumptionBounds.DataLength
+									measureUnmatchableTail _ 0	= 0						-- Have matched all the data.
+									measureUnmatchableTail (a : as) unmatched
+										| a `Meta.isMatch` meta	= measureUnmatchableTail as $ pred unmatched	-- Recurse.
+										| otherwise		= unmatched					-- Return the unmatchable tail-length.
+									measureUnmatchableTail [] _	= error "RegExDot.RegEx.findMatch.findMatchSlave.maybeMatchList.mostData.measureUnmatchableTail:\tdata unexpectedly exhausted."
+{-
+ 'most' has been extracted from 'repeatablePatternHead',
+ & reduced according to the length of 'inputData' which actually matches, to form 'mostData',
+ but if it still exceeds 'fewestData', the resulting repetition-range may trigger backtracking.
+ So, attempt to further reduce this ill-defined repetition-range, according to the competing requirements of 'concatenationTail'.
+-}
+								mostData'
+									| and [
+										ExecutionOptions.moderateGreed executionOptions,
+										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'	-> 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.
+							 ) `take` (
+								if isGreedy
+									then ToolShed.Data.List.Splits.splitsLeftFrom mostData'
+									else ToolShed.Data.List.Splits.splitsRightFrom fewestData
+							 ) inputData
+
+					CaptureGroup alternatives
+						| and [
+							not isGreedy,
+							fewest <= 0,	-- Zero repetitions permissible.
+							Data.Maybe.isJust tailMatch
+						] -> zeroRepetitions	-- Zero repetitions is the optimal solution, rendering the choice of Alternative irrelevant.
+						| and [
+							ExecutionOptions.catchIncompatibleAnchors executionOptions,
+							fewest > 1,			-- Multiple repetitions.
+							minConsumptionAlternatives > 0,	-- InputData required.
+							($ extendedRegExAlternatives) `any` [(hasBowAnchor `all`), (hasSternAnchor `all`)]
+						]							-> Nothing	-- 'extendedRegExFromAlternative' requires 'InputData', therefore 'Anchor.Bow' can only pass on the 1st repetition & 'Anchor.Stern' can only pass on the last.
+						| otherwise						-> let
+{-
+ We're about to try all repetitions of one Alternative before progressing to the next.
+ One could alternatively transpose this search-pattern, & investigate all 'Alternatives' permissible at n repetitions, before trying (n + 1); I've not pursued this option.
+ 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 . concat . Control.Parallel.Strategies.parMap Control.Parallel.Strategies.rseq {-Particularly effective when 'not ExecutionOptions.requireMatchList' -} (
+--								:: ExtendedRegEx m -> [Maybe (Match m, MatchList m)]
+								\extendedRegExFromAlternative@MkExtendedRegEx {
+									concatenation	= concatenationFromAlternative
+								} -> let
+									components :: Int
+									components	= length concatenationFromAlternative
+
+									consumptionProfileConcatenationFromAlternative :: [ConsumptionProfile.ConsumptionProfile]
+									consumptionProfileConcatenationFromAlternative	= map Consumer.consumptionProfile concatenationFromAlternative
+
+									minConsumptionConcatenationFromAlternative	:: ConsumptionBounds.DataLength
+									maybeMaxConsumptionConcatenationFromAlternative	:: Maybe ConsumptionBounds.DataLength
+									(minConsumptionConcatenationFromAlternative, maybeMaxConsumptionConcatenationFromAlternative)	= ConsumptionProfile.consumptionBounds $ ConsumptionProfile.aggregateFromConcatenation consumptionProfileConcatenationFromAlternative
+								in (
+									if ExecutionOptions.abortTrialRepetitionsOnZeroConsumption executionOptions && Data.Maybe.isNothing most {-constrained only by 'inputDataLength'-}
+										then {-#SCC "abortTrialRepetitionsOnZeroConsumption" #-} ToolShed.Data.List.takeUntil $ \maybeMatchPair -> case maybeMatchPair of
+											Just (match, _)	-> ($ Tree.pop match) `all` [
+												(>= fewest) . length,			-- Must achieve 'Repeatable.getFewest', regardless of data-consumption.
+												null . extractDataFromMatchList . last	-- If the n-th repetition consumed nothing, so will the (n + 1)-th.
+											 ]
+											_		-> False			-- Failure with n repetitions, doesn't preclude success with n + 1.
+										else {-optimisation not required-} id
+								) . (
+--									:: Maybe (Match m, MatchList m) -> Maybe (Match m, MatchList m)
+									\maybeMatchPairList	-> if ExecutionOptions.abortTrialRepetitionsOnInherentFailure executionOptions
+{-
+ We're iterating through the identified range of possible repetitions, of one possible 'concatenationFromAlternative'.
+ If failure can be proven, for an arbitrary number of repetitions, then we can bypass the futile remainder.
+ If the first trial succeeded, then clearly there's no such inherent problem with 'concatenationFromAlternative', & it's necessary to evaluate all subsequent trial-repetitions.
+ Otherwise, assuming there're subsequent trials to be bypassed, attempt to prove that failure is inevitable, by launching a pilot-study,
+ using a single repetition of 'concatenationFromAlternative' followed by a replacement infallible 'concatenationTail'.
+-}
+										then {-#SCC "abortTrialRepetitionsOnInherentFailure" #-} case maybeMatchPairList of
+											(Nothing {-failed attempt-} : _ {-subsequent attempt worth bypassing-} : _)	-> if (
+												minConsumptionConcatenationFromAlternative == 0	-- Can delegate consumption of unconsumable data to the infallible tail => unprovable culpability.
+											 ) || inputData =~ RegExOpts.mkRegEx MkExtendedRegEx {
+												bowAnchor	= Just Anchor.Bow,
+												concatenation	= concatenationFromAlternative ++ [anyDatum ^#-> minConsumptionConcatenationTail],	-- Infallible tail.
+												sternAnchor	= Just Anchor.Stern
+											 }
+												then maybeMatchPairList
+												else []	-- Abandon further repetitions of 'Alternatives'.
+											_ {-Alternative is OK, or there's no subsequent attempt to bypass-}		-> maybeMatchPairList
+										else {-optimisation not required-} maybeMatchPairList
+								) . map (
+--									:: Repeatable.Repetitions -> Maybe (Match m, MatchList m)
+									\repetitions	-> if hasSternAnchor extendedRegExFromAlternative
+										then if (repetitions == 1 || minConsumptionConcatenationFromAlternative == 0) && minConsumptionConcatenationTail == 0
+											then (
+												shiftMatch inputDataOffset . Tree.Node . (
+													: replicate (
+														pred repetitions	-- Typically degenerates to zero, since anchored sub-expressions aren't normally repeatable.
+													) (
+														mkNullMatchFromExtendedRegEx 0 extendedRegExFromAlternative	-- Other Alternatives may be available & suitable.
+													) -- Repeated null match may, lacking other suitable Alternatives, correspond to this stern-anchored ExtendedRegEx, so data must be consumed before them.
+												) &&& const (mkNullMatchFromConcatenation inputDataOffset concatenationTail)
+											) `fmap` findMatch regExOpts { RegExOpts.regEx = extendedRegExFromAlternative } inputData	-- Recurse, either consuming all inputData or failing.
+											else Nothing
+										else {-no Anchor.Stern-} let
+{-
+ Expand the 'Repeatable CaptureGroup', so that after recursion it is ultimately reduced in complexity, to just a 'Concatenation' of 'Repeatable Require', & can be handled above as a POSIX BRE.
+
+ There're two special cases; one repetition of n 'Alternatives' & n repetitions of one Alternative.
+ If there's only one repetition, we can reduce the implementation-logic substantially, to the point where the implementation's independent of whether there's a choice of 'Alternatives'.
+ If there only one Alternative, then the entire repetition-sequence can be immediately expanded, vastly reducing the required number of recursions,
+ otherwise we can only expand the first repetition, leaving the option of matching a different Alternative on subsequent repetitions.
+
+ In all cases, we must subsequently re-compose any 'MatchList' resulting of the recursive call, into one corresponding to the structure of original ExtendedRegEx.
+ The expansion-process & corresponding subsequent collation, are associated in a tuple, in which the consumption-profile of the expansion is also contained.
+-}
+--											collater					:: MatchList m -> (Match m, MatchList m)
+											consumptionProfileExpandedConcatenationPrefix	:: [ConsumptionProfile.ConsumptionProfile]
+--											expandedConcatenationPrefix			:: Concatenation a
+											(collater, consumptionProfileExpandedConcatenationPrefix, expandedConcatenationPrefix)
+												| repetitions == 1	= (
+													Control.Arrow.first (
+														Tree.Node . return {-to List-monad-}
+													) . splitAt components,	-- Bisect the 'MatchList', into the part resulting from the Alternative, & that for 'concatenationTail'.
+													consumptionProfileConcatenationFromAlternative,
+													concatenationFromAlternative
+												) -- Both tuples below, can degenerate to this simple case; it isn't a fundamentally different algorithm.
+												| and [
+													ExecutionOptions.unrollRepeatedSingletonAlternative executionOptions,
+													isSingletonAlternative,
+													not $ hasBowAnchor extendedRegExFromAlternative
+												] = (
+													Control.Arrow.first (
+														Tree.Node . ToolShed.Data.List.chunk components
+													) . splitAt (
+														components * repetitions
+													), -- Bisect the 'MatchList', into the part resulting from (Alternative){n}, & that for 'concatenationTail'.
+													concat $ replicate repetitions consumptionProfileConcatenationFromAlternative,
+													concat $ replicate repetitions concatenationFromAlternative	-- Expand all repetitions of the single alternative.
+												)
+												| otherwise {-choice of Alternatives or has Anchor.Bow-}	=  let
+													remainingRepetitions :: Repeatable.Repetitions
+													remainingRepetitions	= pred repetitions	-- Expand just the first repetition of the set of 'Alternatives'.
+
+--													singletonRepeatable :: RepeatablePattern a
+													singletonRepeatable	= Repeatable.toSingleton repeatablePatternHead
+												in (
+													Control.Arrow.first (
+														Tree.Node . uncurry (:) . Control.Arrow.second (
+															concatMap Tree.pop		-- Amalgamate the repeated singleton 'MatchList's.
+														) . splitAt components			-- Bisect first 'MatchList', into the part resulting from 'concatenationFromAlternative', & that for 'replicate remainingRepetitions'.
+													) . splitAt (
+														components + remainingRepetitions	-- Bisect the 'MatchList', into the part resulting from (Alternatives){n}, & that for 'concatenationTail'.
+													),
+													consumptionProfileConcatenationFromAlternative ++ replicate remainingRepetitions (Consumer.consumptionProfile singletonRepeatable),
+													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 `fmap` {-apply to Maybe Functor-} findMatchSlave (
+										expandedConcatenationPrefix ++ concatenationTail
+									) (
+										ConsumptionProfile.accumulateFrom tailConsumptionProfile {-initial value-} consumptionProfileExpandedConcatenationPrefix ++ tail accumulatedConsumptionProfilesTail
+									) (
+										accumulateDistinctMetaDataFrom (head distinctMetaDataTail) {-initial value-} expandedConcatenationPrefix ++ tail distinctMetaDataTail
+									) inputData inputDataLength distinctInputData	-- Recurse to get 'Maybe (MatchList a)'.
+								) $ 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 []	-- Failure is inevitable.
+										else [fewest]
+									else {-imprecise range-} let
+{-
+ Attempt to narrow the repetition-range, from the potentially unbounded specification, to that which is possible according to (data available / consumption-requirement),
+ where there're bounds for both numerator & denominator.
+ Additionally, one must account for the possibility of the denominator being zero, & if so, select the optimal value if the numerator is also zero.
+ 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" #-} 1 {-zero is handled later-} `max` if any Data.Maybe.isNothing [maybeMaxConsumptionConcatenationTail, maybeMaxConsumptionAlternatives]
+											then fewest
+											else {-no unlimited capacities-} let
+												minDataAvailable, maxConsumptionAlternatives :: ConsumptionBounds.DataLength
+												minDataAvailable		= inputDataLength - Data.Maybe.fromJust maybeMaxConsumptionConcatenationTail	-- CAVEAT: can be negative.
+												maxConsumptionAlternatives	= Data.Maybe.fromJust maybeMaxConsumptionAlternatives
+											in if isSingletonAlternative
+												then if maxConsumptionAlternatives == 0							-- Denominator.
+													then {-sole Alternative can't consume anything ?!-} if minDataAvailable <= 0	-- Numerator.
+														then {-tail may consume all data-} fewest	-- Repeat to meet the minimum requirement.
+														else {-unconsumable data-} maxBound		-- Failure is inevitable.
+													else {-non-zero => can divide-} max fewest $ minDataAvailable /+ maxConsumptionAlternatives
+												else {-choice of Alternatives-} let
+													minDataAvailable' :: ConsumptionBounds.DataLength
+													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-} 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" #-} case most of
+											Just cap	-> cap `min` mostPermissibleRepetitions	-- Create a ceiling above which the calculated number of permissible repetitions can't rise.
+											_		-> mostPermissibleRepetitions
+											where
+												mostPermissibleRepetitions :: Repeatable.Repetitions
+												mostPermissibleRepetitions
+													| isSingletonAlternative		= if minConsumptionAlternatives == 0							-- Denominator.
+														then {-sole Alternative can consume zero data-} if maxDataAvailable == 0	-- Numerator.
+															then {-zero data available-} fewest		-- Repeat to meet the minimum requirement.
+															else {-data available-} maxDataAvailable	-- Either each repetition consumes something, or (n - 1) repetitions is a better solution.
+														else {-non-zero => can divide-} maxDataAvailable `div` minConsumptionAlternatives	-- Divide & round down.
+													| otherwise {-choice of Alternatives-}	= 1 {-account for instance expanded as 'concatenationFromAlternative'-} + let
+														maxDataAvailable' :: ConsumptionBounds.DataLength
+														maxDataAvailable'	= maxDataAvailable - minConsumptionConcatenationFromAlternative	-- CAVEAT: potentially negative.
+													in if minConsumptionAlternatives == 0							-- Denominator.
+														then {-@ least one Alternative can consume zero-} if maxDataAvailable' == 0	-- Numerator.
+															then {-zero data available $-} pred fewestAlternatives	-- Repeat as required. CAVEAT: an annoying dependency, which prevents parallel-evaluation.
+															else {-data available-} if and [
+																False,	-- The cost outweighs the small infrequent dividend.
+																minConsumptionConcatenationFromAlternative == 0,
+																maxDataAvailable > fewest
+															] -- If 'fewest' can be met, without unconsuming repetitions of 'concatenationFromAlternative', then stop short of permitting it.
+																then pred maxDataAvailable	-- Any greater, & one repetition (possibly that currently expanded) must needlessly consume nothing.
+																else maxDataAvailable'		-- Either all n repetitions consumes something, or (n - 1) is a better solution.
+														else {-non-zero => can divide-} maxDataAvailable' `div` minConsumptionAlternatives	-- Divide & round down.
+{-
+ 'most' has been extracted from 'repeatablePatternHead',
+ & reduced according to the number of times it can fit into the maximum available data, to form 'mostAlternatives',
+ but if it still exceeds 'fewestAlternatives', the resulting repetition-range may trigger backtracking.
+ So, attempt to further reduce this ill-defined repetition-range, according to the competing requirements of 'concatenationTail'.
+ CAVEAT: this pays-off infrequently, but not necessarily insignificantly.
+-}
+										mostAlternatives'	= {-#SCC "mostAlternatives'" #-} if and [
+											ExecutionOptions.moderateGreed executionOptions,
+											mostAlternatives > fewestAlternatives,	-- Otherwise, there's no unbridled greed to moderate.
+											minConsumptionAlternatives > 0		-- Otherwise, any number of repetitions can occur without necessarily triggering back-tracking.
+										 ]
+											then case maximumDataBeforePegs of
+												Just maximumDataBeforePegs'	-> mostAlternatives `min` (
+													length maximumDataBeforePegs' `div` minConsumptionAlternatives
+												 ) -- Cap upper bound.
+												_				-> 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.
+							 ) . (
+								if ExecutionOptions.permitReorderingOfAlternatives executionOptions
+{-
+ The order in which 'Alternatives' are evaluated, should make no difference to the final result; unless 'ExecutionOptions.useFirstMatchAmongAlternatives'.
+ This order can be manipulated in an attempt to more quickly locate any 'Just MatchList', though if 'ExecutionOptions.requireMatchList', an exhaustive search for the optimal solution must be performed anyway.
+ Tackling lower-complexity 'Alternatives' first makes sense, in the hope of finding any easy solution before becoming entrenched fighting some hideous monster.
+ Preferring 'Alternatives' which require more data also makes sense, regardless of 'Repeatable.isGreedy' which just a preference for a type of solution, because fewer repetitions are then permissible;
+ this is rather like trying to pack a box & preferring to try the biggest items first.
+-}
+									then Data.List.sortBy $ Data.Ord.comparing (
+										Consumer.starHeight &&& safeReciprocal . (fromIntegral :: ConsumptionBounds.DataLength -> Rational) . Consumer.getFewest
+									) -- Firstly increasing complexity, then decreasing minimum data-capacity, otherwise stable.
+									else id
+							 ) $ filter (
+								\e	-> (
+									not (hasBowAnchor e) || inputDataOffset == 0			-- Necessary & sufficient.
+								) && (
+									not (hasSternAnchor e) || minConsumptionConcatenationTail == 0	-- Necessary but insufficient, since though minimum consumption is zero, maximum isn't necessarily.
+								)
+							 ) extendedRegExAlternatives
+						in if null matchPairList
+							then if fewest <= 0
+								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',
+ & if the caller reduces the 'Just MatchList' to 'True', that'd be sufficient, but otherwise one must identify the optimal 'MatchList'.
+ The primary selection-criterion used is the POSIX one, based on total maximum (or minimum for non-'Repeatable.isGreedy' capture-groups) data-consumption.
+ /Perl/'s "first-past-the-post" policy is available as an alternative.
+-}
+								if ExecutionOptions.useFirstMatchAmongAlternatives executionOptions || length matchPairList == 1
+									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.
+									) . map (
+										(
+{-
+ If the primary selection-criterion doesn't resolve the choice between candidate 'Match'es, I employ these ad-hoc criteria.
+
+	* Fewer repetitions are preferred, which discourages the capture of null lists of 'InputData'.
+
+	* Within the 'MatchedData', from which a candidate 'Match' is ultimately composed, consumption of 'InputData' beyond 'Repeatable.getFewest' by 'Repeatable.isGreedy' 'RepeatablePattern's, is preferred to non-greedy ones.
+
+	* The consumption on each successive repetition is compared between candidate 'Match'es (which are now known to have used an equal number of repetitions);
+	this causes the data-consumption to flow towards earlier repetitions for greedy capture-groups, & towards later repetitions in non-greedy ones,
+	thus mimicking the behaviour of the unrolled repetition.
+
+	* PS: more precise criteria are defined in <http://www2.research.att.com/~gsf/testregex/re-interpretation.html>.
+-}
+											\match -> let
+												dataLengthCriterion :: InputData m -> Rational
+												dataLengthCriterion	= (
+													if isGreedy
+														then id
+														else safeReciprocal	-- Prefer less data.
+												 ) . fromIntegral . length
+
+--												matchLists :: [MatchList m]
+												matchLists	= Tree.pop match
+											in (
+												dataLengthCriterion $ extractDataFromMatch match,
+												if ExecutionOptions.preferFewerRepeatedAlternatives executionOptions
+													then safeReciprocal . toRational $ length matchLists
+													else 0,
+												if ExecutionOptions.preferAlternativesWhichFeedTheGreedy executionOptions
+													then let
+														excessConsumption :: MatchedData m -> ConsumptionBounds.DataLength
+														excessConsumption (
+															Repeatable.MkRepeatable {
+																Repeatable.repetitionBounds	= (f, _),
+																Repeatable.isGreedy		= g
+															},
+															_,
+															consumedInputData
+														 )
+															| g		= l - f
+															| otherwise	= f - l
+															where
+																l :: ConsumptionBounds.DataLength
+																l	= length consumedInputData
+													in Data.Foldable.foldl' (\l -> (l +) . excessConsumption) 0 match
+													else 0,
+												if ExecutionOptions.preferAlternativesWhichMimickUnrolling executionOptions
+													then map (dataLengthCriterion . extractDataFromMatchList) matchLists
+													else []
+											) -- Create a tuple of selection-criteria, for simultaneous assessment.
+										) . fst {-focus the choice on the Alternatives-} &&& id	-- Prepend a selection-criterion to each result.
+									)
+							) matchPairList
+						where
+--							tailMatch, zeroRepetitions :: Maybe (MatchList m)
+							tailMatch	= findMatchSlave concatenationTail accumulatedConsumptionProfilesTail distinctMetaDataTail inputData inputDataLength distinctInputData	-- Recurse.
+							zeroRepetitions	= (Tree.Node [] :) `fmap` {-apply to Maybe Functor-} tailMatch	-- Prepend a null 'MatchList'.
+
+--							extendedRegExAlternatives :: [ExtendedRegEx m]
+							extendedRegExAlternatives	= Data.List.nub $ deconstructAlternatives alternatives
+
+							isSingletonAlternative :: Bool
+							isSingletonAlternative	= length extendedRegExAlternatives == 1
+
+							minConsumptionAlternatives	:: ConsumptionBounds.DataLength
+							maybeMaxConsumptionAlternatives	:: Maybe ConsumptionBounds.DataLength
+							(minConsumptionAlternatives, maybeMaxConsumptionAlternatives)	= Consumer.getConsumptionBounds alternatives	-- Independent of the choice of Alternative.
+			where
+				inputDataOffset :: ConsumptionBounds.DataLength
+				inputDataOffset	= originalInputDataLength - inputDataLength
+		findMatchSlave _ _ _ _ _ _	= error "RegExDot.RegEx.findMatch.findMatchSlave:\tunexpected parameter-pattern."
+
+{- |
+	* Operator's name was chosen to suggest something more than '=~'.
+
+	* 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, Control.DeepSeq.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
+inputData +~ regExOpts	= (
+	if hasBowAnchor' then Nothing else fmap head maybeMatchList,	-- Record the first 'Match', consumed in the absence of a top-level 'Anchor.Bow'.
+	fmap (
+		(
+			if hasBowAnchor' then id else tail			-- Remove the first 'Match', since this wasn't consumed by the 'Concatenation'.
+		) . (
+			if hasSternAnchor' then id else init			-- Remove the last 'Match', since this wasn't consumed by the 'Concatenation'.
+		)
+	) maybeMatchList,
+	if hasSternAnchor' then Nothing else fmap last maybeMatchList	-- Record the last 'Match', consumed in the absence of a top-level 'Anchor.Stern'.
+ ) where
+--	extendedRegEx :: ExtendedRegEx a
+	extendedRegEx	= RegExOpts.regEx regExOpts
+
+	hasBowAnchor', hasSternAnchor' :: Bool
+	hasBowAnchor'	= hasBowAnchor extendedRegEx
+	hasSternAnchor'	= hasSternAnchor extendedRegEx
+
+--	maybeMatchList :: Maybe (MatchList m)
+	maybeMatchList	= fmap drift (RegExOpts.setVerbose True regExOpts) `findMatch` inputData
+
+{- |
+	* Pattern-match operator.
+
+	* Identifier & parameter-order follow the lead of /Perl/'s pattern-match operator.
+
+	* Considerably more efficient than '+~', since even though they are both implemented via 'findMatch',
+	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, Control.DeepSeq.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, Control.DeepSeq.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	= not . (inputData =~)
+
+-- | The delimiters of 'Alternatives', when in the 'String'-form.
+captureGroupDelimiters :: (Char, Char)
+captureGroupDelimiters	= ('(', ')')
+
+-- | The token used to separate alternative 'ExtendedRegEx's, when in the 'String'-form.
+alternativeExtendedRegExSeparatorToken :: Char
+alternativeExtendedRegExSeparatorToken	= '|'
+
+-- | The set of 'Char' to which a specific meaning is attributed, when reading from 'String'.
+tokens :: String
+tokens	= [fst captureGroupDelimiters, snd captureGroupDelimiters, alternativeExtendedRegExSeparatorToken]
+
+{- |
+	* Invert the specified fraction, but return 'maxBound' if the result would otherwise be infinite.
+
+	* CAVEAT: this is an awful concept, and therefore intended for internal use only.
+-}
+safeReciprocal :: (Eq f, Fractional f) => f -> f
+safeReciprocal 0	= fromIntegral (maxBound :: Int)	-- Handle divide-by-zero error.
+safeReciprocal f	= recip f
+
+infixl 7 /+	-- Same as (/).
+
+{- |
+	* Integral division, with any fractional remainder rounded-up.
+
+	* A rather dubious requirement, so internal use only.
+-}
+-- (/+) :: Integral i => i -> i -> i
+(/+)
+	:: Int	-- ^ Numerator.
+	-> Int	-- ^ Denominator.
+	-> Int	-- 10% faster in unoptimised code, & more in optimised.
+_ /+ 0				= error "RegExDot.RegEx.(/+):\tzero denominator => infinity"
+-- numerator /+ denominator	= ceiling ((fromIntegral numerator / fromIntegral denominator) :: Double)
+numerator /+ denominator	= uncurry (+) . Control.Arrow.second signum $ quotRem numerator denominator	-- Slightly faster.
diff --git a/src-lib/RegExDot/RegExOpts.hs b/src-lib/RegExDot/RegExOpts.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/RegExOpts.hs
@@ -0,0 +1,65 @@
+{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+{-
+	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@]
+
+	* Provides a complete job-specification.
+
+	* 'regEx' is polymorphic, allowing use of either /RegExDot.RegEx.ExtendedRegEx/ (which is also polymorphic) or /RegExChar.ExtendedRegExChar.ExtendedRegExChar/.
+-}
+
+module RegExDot.RegExOpts(
+-- * Types
+-- ** Data-types
+	RegExOpts(..),
+-- * Functions
+	setVerbose,
+-- ** Constructors
+	mkRegEx
+) where
+
+import qualified	RegExDot.CompilationOptions	as CompilationOptions
+import qualified	RegExDot.ExecutionOptions	as ExecutionOptions
+import qualified	ToolShed.Defaultable
+
+-- | Aggregates both 'ExecutionOptions.ExecutionOptions' & 'CompilationOptions.CompilationOptions' with a polymorphic /regex/, to form a complete job-description.
+data RegExOpts a	= MkRegExOpts {
+	compilationOptions	:: CompilationOptions.CompilationOptions,	-- ^ Parameters governing the result, rather than the implementation.
+	executionOptions	:: ExecutionOptions.ExecutionOptions,		-- ^ Parameters governing the implementation, rather than the result.
+	regEx			:: a						-- ^ Polymorphic, to permit specialisation either of the type of /regex/ or the type of input-data.
+} deriving Show
+
+instance Functor RegExOpts	where
+	fmap f regExOpts	= regExOpts { regEx = f $ regEx regExOpts }
+
+-- | Smart constructor using 'ToolShed.Defaultable.defaultValue'.
+mkRegEx :: a -> RegExOpts a
+mkRegEx	r	= MkRegExOpts {
+	compilationOptions	= ToolShed.Defaultable.defaultValue,
+	executionOptions	= ToolShed.Defaultable.defaultValue,
+	regEx			= r
+}
+
+-- | Mutator, which sets an appropriate 'ExecutionOptions.ExecutionOptions', for the depth to which the caller wants to probe the resulting match.
+setVerbose :: Bool -> RegExOpts a -> RegExOpts a
+setVerbose verbose regExOpts	= regExOpts { executionOptions = ExecutionOptions.setVerbose verbose $ executionOptions regExOpts }
+
diff --git a/src-lib/RegExDot/Repeatable.hs b/src-lib/RegExDot/Repeatable.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/Repeatable.hs
@@ -0,0 +1,400 @@
+{-# LANGUAGE CPP #-}
+{-
+	Copyright (C) 2010-2015 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 data-type, which represents the permissible range of instances, of the underlying polymorphic datum.
+
+	* Designed for use in a polymorphic /regex/-engine, which specifies patterns composed of repeated /greedy/ & /non-greedy/ sequences of /Meta/-data;
+
+ >		*	+	?	{fewest, most}	{fewest,}	{fewest}
+ >		*?	+?	??	{fewest, most}?	{fewest,}?
+
+	* In the context of /regex/es, this concept is known as /Quantification/.
+
+	* /regex/es evolved from the minimal ability to optionally qualify the datum with a <http://en.wikipedia.org/wiki/Kleene_star> suffix.
+	More exotic repetition-specifications could be composed by concatenating these atomic building-blocks.
+	Here, I've taken the contrary top-down view, & assumed that all data are qualified by a full 'RepetitionBounds', which in most cases will degenerate into a simpler form.
+
+	* The type of entity which is being repeated, isn't the domain of this data-type; it's polymorphic.
+-}
+
+module RegExDot.Repeatable(
+-- * Types
+-- ** Type-synonyms
+	Repetitions,
+	RepetitionBounds,
+-- ** Data-types
+	Repeatable(..),
+-- * Constants
+--	nonGreedyToken,
+	oneOrMoreToken,
+	rangeDelimiters,
+	rangeSeparatorToken,
+	tokens,
+	zeroOrMoreToken,
+	zeroOrOneToken,
+-- * Functions
+	one,
+	oneOrMore,
+	oneOrMore',
+	zeroOrMore,
+	zeroOrMore',
+	zeroOrOne,
+	zeroOrOne',
+--	precisely,
+	repeatableParser,
+	showSuffix,
+-- ** Accessors
+	getFewest,
+	getMost,
+-- ** Mutators
+	focus,
+--	setNonGreedy,
+	toSingleton,
+-- ** Operators
+	(^#->#),
+	(^#->#?),
+	(^#->),
+	(^#->?),
+	(^#),
+-- ** Predicates
+	isPrecise,
+	hasPreciseBounds
+) where
+
+import			Control.Arrow((***))
+import qualified	Control.DeepSeq
+import qualified	Data.List
+import qualified	RegExDot.Consumer		as Consumer
+import qualified	RegExDot.ConsumptionProfile	as ConsumptionProfile
+import qualified	Text.ParserCombinators.Parsec	as Parsec
+import			Text.ParserCombinators.Parsec((<?>))
+import qualified	ToolShed.Data.Pair
+import qualified	ToolShed.SelfValidate
+
+#if !MIN_VERSION_base(4,8,0)
+import	Control.Applicative((<$>), (<*>))
+#endif
+
+infix 6 ^#->#, ^#->#?, ^#->, ^#->?, ^#	-- A notch tighter than "DSL"s binary operators.
+
+-- | A number of repetitions.
+type Repetitions	= Int
+
+-- | Defines the bounds of a range of permissible repetitions.
+type RepetitionBounds	= (Repetitions, Maybe Repetitions)
+
+-- | Creates a precise 'RepetitionBounds', i.e. both lower & upper bounds on the number of 'Repetitions' are equal to the same value.
+precisely :: Repetitions -> RepetitionBounds
+precisely i	= (i, Just i)
+
+-- | Predicate which is 'True' if exactly one value is permissible, ie lower & upper bounds on the number of 'Repetitions' are identical.
+hasPreciseBounds :: RepetitionBounds -> Bool
+hasPreciseBounds (fewest, most)	= Just fewest == most
+
+-- | Declares a polymorphic data-type, which augments the underlying 'base' datum, with the range of times it may be used.
+data Repeatable a	= MkRepeatable {
+	base			:: a,			-- ^ The underlying polymorphic datum.
+	repetitionBounds	:: RepetitionBounds,	-- ^ The bounds delimiting the range of permissible repetitions, of 'base'.
+	isGreedy		:: Bool			-- ^ Whether to demand as many matching instances of 'base' as possible; or as few (AKA /lazy quantification/).
+} deriving Eq
+
+instance Functor Repeatable	where
+	fmap f repeatable	= repeatable { base = f $ base repeatable }
+
+-- | True if there's no choice in the number of repetitions; implemented via 'isPrecise'.
+isPrecise :: Repeatable a -> Bool
+isPrecise	= hasPreciseBounds . repetitionBounds
+
+-- | Builds a parser for a specification of the number of permissible instances of the specified polymorphic parameter.
+repeatableParser :: a -> Parsec.Parser (Repeatable a)
+repeatableParser b	= Parsec.option (
+	one b	-- The default; there's no concept of greediness here.
+ ) $ do
+	repeatable	<- Parsec.choice [
+		(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")
+				most	<- Parsec.spaces >> Parsec.option (
+					Just fewest	-- The default.
+				 ) (
+					do
+						i	<- (
+							Parsec.char rangeSeparatorToken			<?> "Repeatable.rangeSeparatorToken " ++ show rangeSeparatorToken
+						 ) >> Parsec.spaces >> Parsec.option Nothing {-default to open-ended range-} (
+							Just . read <$> Parsec.many1 Parsec.digit	<?> "Repetition-range maximum"
+						 )
+
+						Parsec.spaces >> return {-to ParsecT-monad-} i
+				 )
+
+				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 ParsecT-monad-} False
+
+	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
+		[(base', s1)]	-> (error . ("readsPrec Repeatable:\tparse-error; " ++) . show) `either` return $ Parsec.parse ((,) <$> repeatableParser base' <*> Parsec.getInput) "Repeatable" s1
+		_		-> []	-- No parse.
+
+{- |
+	* A 'ShowS'-function for the suffix, denoting the permissible repetitions, of 'base'.
+
+	* This function converts the internal, into the tradition /greedy/ & /non-greedy/ quantifiers of various specific varieties.
+-}
+showSuffix :: Repeatable a -> ShowS
+showSuffix repeatable	= let
+	showRange :: ShowS -> ShowS
+	showRange x	= (\(begin, end) -> begin . x . end) $ ToolShed.Data.Pair.mirror showChar rangeDelimiters
+ in (
+	case repetitionBounds repeatable of
+		(0, Nothing)		-> showChar zeroOrMoreToken
+		(1, Nothing)		-> showChar oneOrMoreToken
+		(fewest, Nothing)	-> showRange $ shows fewest . showChar rangeSeparatorToken
+		(0, Just 1)		-> showChar zeroOrOneToken
+		(1, Just 1)		-> id	-- CAVEAT: since there's no explicit repetition-operator, the non-greedy modifier can't be appended.
+		(fewest, Just most)	-> showRange $ if fewest == most
+			then shows fewest	-- Single-valued range.
+			else shows fewest . showChar rangeSeparatorToken . shows most
+ ) . if ($ repeatable) `any` [isGreedy, isPrecise] {-without a range of possibilities, non-greediness is irrelevant-}
+	then id
+	else showChar nonGreedyToken	-- This can only be appended, if there a previous repetition-operator for it to modify.
+
+-- Replicate the syntax, for repetition, as used in a POSIX-standard /regex/.
+instance Show a => Show (Repeatable a)	where
+	showsPrec _ repeatable	= shows (base repeatable) . showSuffix repeatable
+
+instance Consumer.Consumer a => Consumer.Consumer (Repeatable a)	where
+	consumptionProfile MkRepeatable {
+		base			= b,
+		repetitionBounds	= (fewest, most)
+	} = baseConsumptionProfile {
+		ConsumptionProfile.consumptionBounds	= (fewest *) *** ((*) <$> most <*>) $ ConsumptionProfile.consumptionBounds baseConsumptionProfile	-- CAVEAT: special cases exist, where one or both halves of this calculation degenerate to a simpler form, but special treatment, in an attempt to improve performance, proved counterproductive.
+	} where
+		baseConsumptionProfile :: ConsumptionProfile.ConsumptionProfile
+		baseConsumptionProfile	= Consumer.consumptionProfile b
+
+	starHeight MkRepeatable {
+		base			= b,
+		repetitionBounds	= r
+	} = Consumer.starHeight b + if hasPreciseBounds r then 0 else 1
+
+instance ToolShed.SelfValidate.SelfValidator a => ToolShed.SelfValidate.SelfValidator (Repeatable a)	where
+	getErrors MkRepeatable {
+		base			= b,
+		repetitionBounds	= (fewest, most),
+		isGreedy		= g
+	}
+		| not $ ToolShed.SelfValidate.isValid b	= ToolShed.SelfValidate.getErrors b	-- Delegate.
+		| otherwise				= ToolShed.SelfValidate.extractErrors [
+			(fewest < 0, "Negative fewest=" ++ show fewest ++ "."),
+			(
+				case most of
+					Just m	-> m < fewest
+					_	-> False,
+				"Invalid repetition-range; '" ++ show (fewest, most) ++ "'."
+			), (
+				not g && case most of
+					Just m	-> fewest >= m	-- There ought to be potential for non-greediness, where specified: the converse isn't true, since greediness isn't explicit, & may not have been wanted.
+					_	-> False,
+				"Invalid non-greedy repetition-range; '" ++ show (fewest, most) ++ "'."
+			)
+		]
+
+instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Repeatable a)	where
+	rnf MkRepeatable {
+		base			= b,
+		repetitionBounds	= r,
+		isGreedy		= g
+	} = Control.DeepSeq.rnf (b, r, g)
+
+-- | Mutator.
+setNonGreedy :: Repeatable a -> Repeatable a
+setNonGreedy r	= r { isGreedy = False }
+
+{- |
+	* Construct a greedy 'Repeatable', from a polymorphic datum, with the specified range of permissible instances.
+
+	* The /#/s in the identifier represent the two bounds.
+
+	* /a{f, m}/
+-}
+(^#->#)
+	:: a			-- ^ The polymorphic payload from which to construct the 'Repeatable'.
+	-> RepetitionBounds	-- ^ The permissible repetition-bounds for the polymorphic data.
+	-> Repeatable a
+b ^#-># bounds	= MkRepeatable {
+	base			= b,
+	repetitionBounds	= bounds,
+	isGreedy		= True
+}
+
+{- |
+	* Construct a non-greedy version of '^#->#'.
+
+	* /a{f, m}?/
+-}
+(^#->#?)
+	:: a			-- ^ The polymorphic payload from which to construct the 'Repeatable'.
+	-> RepetitionBounds	-- ^ The permissible repetition-bounds for the polymorphic data.
+	-> Repeatable a
+b ^#->#? bounds	= setNonGreedy (b ^#-># bounds)
+
+{- |
+	* Construct a greedy 'Repeatable', tailored for data repeated at least the specified number of times.
+
+	* The /#/ in the identifier represents the single bound.
+
+	* /a{f,}/
+-}
+(^#->)
+	:: a		-- ^ The polymorphic payload from which to construct the 'Repeatable'.
+	-> Repetitions	-- ^ The minimum permissible repetitions of the polymorphic data.
+	-> Repeatable a
+b ^#-> fewest	= b ^#-># (fewest, Nothing)
+
+{- |
+	* Construct a non-greedy version of '^#->'.
+
+	* /a{f,}?/
+-}
+(^#->?)
+	:: a		-- ^ The polymorphic payload from which to construct the 'Repeatable'.
+	-> Repetitions	-- ^ The minimum permissible repetitions of the polymorphic data.
+	-> Repeatable a
+b ^#->? fewest	= setNonGreedy (b ^#-> fewest)
+
+{- |
+	* Construct a 'Repeatable', tailored for data repeated a precise number of times.
+
+	* The /#/ in the identifier represents the single bound.
+
+	* /a{f}/
+-}
+(^#)
+	:: a		-- ^ The polymorphic payload from which to construct the 'Repeatable'.
+	-> Repetitions	-- ^ The precise number of repetitions of the polymorphic data which is required.
+	-> Repeatable a
+b ^# r	= b ^#-># precisely r
+
+{- |
+	* Construct a 'Repeatable', tailored for unrepeated data.
+
+	* A degenerate case of '^#'.
+-}
+one :: a -> Repeatable a
+one	= (^# 1)
+
+{- |
+	* Construct a greedy 'Repeatable', from a polymorphic datum, with 'fewest' == 0 & 'most' == 1.
+
+	* A specific case of '^#->#'.
+-}
+zeroOrOne :: a -> Repeatable a
+zeroOrOne	= (^#-># (0, Just 1))
+
+-- | Construct a non-greedy version of 'zeroOrOne'.
+zeroOrOne' :: a -> Repeatable a
+zeroOrOne'	= setNonGreedy . zeroOrOne
+
+{- |
+	* Construct a greedy 'Repeatable', from a polymorphic datum, with 'fewest' == 0.
+
+	* A specific case of '^#->'.
+-}
+zeroOrMore :: a -> Repeatable a
+zeroOrMore	= (^#-> 0)
+
+-- | Construct a non-greedy version of 'zeroOrMore'.
+zeroOrMore' :: a -> Repeatable a
+zeroOrMore'	= setNonGreedy . zeroOrMore
+
+{- |
+	* Construct a greedy 'Repeatable', from a polymorphic datum, with lower 'RepetitionBounds' == one.
+
+	* A specific case of '^#->'.
+-}
+oneOrMore :: a -> Repeatable a
+oneOrMore	= (^#-> 1)
+
+-- | Construct a non-greedy version of 'oneOrMore'.
+oneOrMore' :: a -> Repeatable a
+oneOrMore'	= setNonGreedy . oneOrMore
+
+-- | Reduces a 'Repeatable', with a range of 'RepetitionBounds', to a precise number of repetitions.
+focus :: Repeatable a -> Repetitions -> Repeatable a
+focus r i	= r { repetitionBounds = precisely i }
+
+{- |
+	* Reduces a 'Repeatable', with a range of 'RepetitionBounds', to a singleton.
+
+	* A degenerate case of 'focus'.
+-}
+toSingleton :: Repeatable a -> Repeatable a
+toSingleton	= (`focus` 1)
+
+-- | Accessor.
+getFewest :: Repeatable a -> Repetitions
+getFewest MkRepeatable { repetitionBounds = (f, _) }	= f
+
+-- | Accessor.
+getMost :: Repeatable a -> Maybe Repetitions
+getMost MkRepeatable { repetitionBounds = (_, m) }	= m
+
+-- | The token used to denote /non-greedy/, when in the 'String'-form.
+nonGreedyToken :: Char
+nonGreedyToken	= '?'
+
+{- |
+	* The token used to denote 'zeroOrMore', when in the 'String'-form.
+
+	* AKA /Kleene Star/.
+-}
+zeroOrMoreToken :: Char
+zeroOrMoreToken	= '*'
+
+-- | The token used to denote 'zeroOrOne', when in the 'String'-form.
+zeroOrOneToken :: Char
+zeroOrOneToken	= '?'
+
+-- | The token used to denote 'oneOrMore', when in the 'String'-form.
+oneOrMoreToken :: Char
+oneOrMoreToken	= '+'
+
+-- | The delimiters of '^#->#', when in the 'String'-form.
+rangeDelimiters :: (Char, Char)
+rangeDelimiters	= ('{', '}')
+
+-- | The token used to separate 'RepetitionBounds', when in the 'String'-form.
+rangeSeparatorToken :: Char
+rangeSeparatorToken	= ','
+
+-- | The set of 'Char' to which a specific meaning is attributed, when reading from 'String'.
+tokens :: String
+tokens	= Data.List.nub [nonGreedyToken, zeroOrMoreToken, zeroOrOneToken, oneOrMoreToken, fst rangeDelimiters, snd rangeDelimiters, rangeSeparatorToken]
+
diff --git a/src-lib/RegExDot/Result.hs b/src-lib/RegExDot/Result.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/Result.hs
@@ -0,0 +1,60 @@
+{-
+	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@]	Tools to manipulate a 'RegEx.Result'.
+
+ [@CAVEAT@]	The data-definition remains in "RegEx", since it references 'RegEx.Match'.
+-}
+
+module RegExDot.Result(
+-- * Functions
+-- ** Accessors (Deconstructors)
+	getMatchList,
+	getPreMatch,
+	getPostMatch,
+-- ** Predicates
+	isMatch,
+-- ** Query
+	countMatches
+) where
+
+import qualified	Data.Maybe
+import qualified	RegExDot.RegEx	as RegEx
+
+-- | Accessor.
+getPreMatch :: RegEx.Result a -> RegEx.ExternalMatch a
+getPreMatch (externalMatch, _, _)	= externalMatch
+
+-- | Accessor.
+getPostMatch :: RegEx.Result a -> RegEx.ExternalMatch a
+getPostMatch (_, _, externalMatch)	= externalMatch
+
+-- | Accessor.
+getMatchList :: RegEx.Result a -> Maybe (RegEx.MatchList a)
+getMatchList (_, maybeMatchList, _)	= maybeMatchList
+
+-- | True if the 'RegEx.InputData' matched the 'RegEx.ExtendedRegEx'.
+isMatch :: RegEx.Result a -> Bool
+isMatch	= Data.Maybe.isJust . getMatchList
+
+-- | Counts the number of top-level 'RegEx.Match'es.
+countMatches :: RegEx.Result a -> Int
+countMatches (_, Just matchList, _)	= length matchList
+countMatches _				= 0
+
diff --git a/src-lib/RegExDot/ShowablePredicate.hs b/src-lib/RegExDot/ShowablePredicate.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/ShowablePredicate.hs
@@ -0,0 +1,53 @@
+{-
+	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@]	Used to implement /Perl-shortcut/s, /BracketExpression/-ranges & /POSIX Character-classes/.
+-}
+
+module RegExDot.ShowablePredicate(
+-- * Types
+	Predicate,
+-- ** Data-types
+	ShowablePredicate(
+		MkShowablePredicate,
+		name,
+		predicate
+	)
+) where
+
+import qualified	Control.DeepSeq
+
+-- | An arbitrary polymorphic predicate function.
+type Predicate a	= a -> Bool
+
+-- | Container for both the /predicate/, & the name used in the implementation of 'Show'.
+data ShowablePredicate a	= MkShowablePredicate {
+	name		:: String,	-- ^ The identifier of this predicate when in string-form.
+	predicate	:: Predicate a	-- ^ The function used to determine whether an input datum matches.
+}
+
+instance Show (ShowablePredicate a)	where
+	showsPrec _	= showString . name
+
+instance Eq (ShowablePredicate a)	where
+	l == r	= name l == name r	-- Ignore 'predicate'.
+
+instance Control.DeepSeq.NFData (ShowablePredicate a)	where
+	rnf	= Control.DeepSeq.rnf . name	-- Ignore 'predicate'.
+
diff --git a/src-lib/RegExDot/Span.hs b/src-lib/RegExDot/Span.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/Span.hs
@@ -0,0 +1,64 @@
+{-
+	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@]	Delimits a data-sequence, via its offset & length, within a wider list.
+-}
+
+module RegExDot.Span(
+-- * Types
+-- ** Type-synonyms
+	Span,
+-- * Functions
+	after,
+	empty,
+	join
+) where
+
+import			Control.Arrow((***))
+import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
+
+{- |
+	* The offset & length of a specific data-sequence, within a wider list.
+
+	* Similar to <http://hackage.haskell.org/packages/archive/regex-base/latest/doc/html/Text-Regex-Base-RegexLike.html#t%3AMatchArray>.
+-}
+type Span	= (ConsumptionBounds.DataLength {-offset-}, ConsumptionBounds.DataLength)
+
+-- | An empty instance, located at the specified offset.
+empty :: ConsumptionBounds.DataLength -> Span
+empty offset	= (offset, 0)
+
+-- | Returns the furthest extent, i.e. the offset just after the end.
+after :: Span -> ConsumptionBounds.DataLength
+after	= uncurry (+)
+
+{- |
+	* Condenses a list into a single value.
+
+	* Expects a gap-free, sorted list.
+-}
+join
+	:: ConsumptionBounds.DataLength	-- ^ The offset into the list of input-data to use when a null list of spans is received.
+	-> [Span]
+	-> Span
+join offset []		= empty offset		-- The offset can't be deduced from a null list, so use the value provided.
+join _ [singleton]	= singleton		-- Merely for efficiency.
+join _ spanList		= head *** sum $ unzip spanList
+
+
diff --git a/src-lib/RegExDot/Tree.hs b/src-lib/RegExDot/Tree.hs
new file mode 100644
--- /dev/null
+++ b/src-lib/RegExDot/Tree.hs
@@ -0,0 +1,80 @@
+{-
+	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@]
+
+	* Defines a specific type of tree-structure, which is composed from either a datum, or a list of Tree-lists; <http://en.wikipedia.org/wiki/Rose_Tree>.
+
+	* This more general tree-structure has the shape of a regular-expression match.
+
+	* This contrasts with the typical binary-tree, which is either empty, or contains a (left Tree, datum, right Tree).
+-}
+
+module RegExDot.Tree(
+-- * Types
+-- ** Type-synonyms
+--	TreeList,
+-- ** Data-types
+	Tree(..),
+-- * Functions
+	pop
+) where
+
+import qualified	Control.Arrow
+import qualified	Control.DeepSeq
+import qualified	Data.Foldable
+import qualified	Data.List
+import qualified	Data.Monoid
+
+-- | A general purpose tree-type structure.
+data Tree a	=
+	Leaf a			-- ^ The payload.
+	| Node [TreeList a]	-- ^ Recurse. NB: a list of lists is required to contain the /MatchLists/ resulting from repeated /Alternatives/.
+	deriving Eq
+
+-- | A list of 'Tree's; significant only because it is the essence of the recursive nature of 'Tree'.
+type TreeList a	= [Tree a]
+
+instance Show a => Show (Tree a)	where
+	showsPrec _ (Leaf a)		= shows a
+	showsPrec _ (Node treeLists)	= showList treeLists
+
+instance Read a => Read (Tree a)	where
+	readsPrec _ node@('[' : _)	= Control.Arrow.first Node `map` readList node {-singleton-}
+	readsPrec _ leaf		= Control.Arrow.first Leaf `map` reads leaf {-singleton-}
+
+instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Tree a)	where
+	rnf (Leaf a)	= Control.DeepSeq.rnf a
+	rnf (Node l)	= Control.DeepSeq.rnf l
+
+instance Functor Tree	where
+	fmap f (Leaf a)		= Leaf $ f a
+	fmap f (Node treeLists)	= Node $ map (fmap {-recurse-} f `map`) treeLists
+
+instance Data.Foldable.Foldable Tree where
+	foldMap f (Leaf a)		= f a	-- CAVEAT: 'f' should be Associative, as required by a Monoid.
+	foldMap f (Node treeLists)	= Data.List.foldl' (Data.List.foldl' (\monoid -> (monoid `Data.Monoid.mappend`) . Data.Foldable.foldMap f)) Data.Monoid.mempty treeLists
+
+-- | Deconstruct the specified 'Node'; i.e. lop the apex from the 'Tree', leaving a flat top.
+pop
+	:: Tree a	-- ^ The tree from which to extract the list of trees hanging immediately beneath its apex.
+	-> [TreeList a]
+pop (Node treeLists)	= treeLists
+pop _			= error "RegExDot.Tree.pop:\tunexpected Leaf"
+
diff --git a/src/RegExDot/Anchor.hs b/src/RegExDot/Anchor.hs
deleted file mode 100644
--- a/src/RegExDot/Anchor.hs
+++ /dev/null
@@ -1,90 +0,0 @@
-{-
-	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
-
-import qualified	Control.DeepSeq
-
--- | 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 Control.DeepSeq.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)
-
diff --git a/src/RegExDot/BracketExpression.hs b/src/RegExDot/BracketExpression.hs
deleted file mode 100644
--- a/src/RegExDot/BracketExpression.hs
+++ /dev/null
@@ -1,63 +0,0 @@
-{-
-	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@]
-
-	This concept was traditionally known as a /Character-class/,
-	but to distinguish it from the more recently introduced & narrower /POSIX Character-class/, it has been renamed /Bracket-expression/.
--}
-
-module RegExDot.BracketExpression(
--- * Types
--- ** Type-synonyms
-	BracketExpression,
--- * Constants
-	delimiterTokens,
-	negationToken,
-	tokens,
--- * Functions
--- ** Predicates
-	containsMatch
-) where
-
-import			RegExDot.BracketExpressionMember((=~))
-import qualified	RegExDot.BracketExpressionMember	as BracketExpressionMember
-
--- | A /Bracket-expression/ consists of a list of 'BracketExpressionMember.Member's.
-type BracketExpression m	= [BracketExpressionMember.Member m]
-
--- | True if the specified datum matches any 'BracketExpressionMember.Member' of the 'BracketExpression'.
-containsMatch :: Eq m
-	=> m			-- ^ The input datum.
-	-> BracketExpression m	-- ^ The list of bracket-expression members within which to find a match.
-	-> Bool
-containsMatch datum	= any (datum =~)
-
--- | The delimiters of a /bracket-expression/, when in 'String'-form.
-delimiterTokens :: (Char, Char)
-delimiterTokens	= ('[', ']')
-
--- | Used to denote a negated /bracket-expression/, when in 'String'-form.
-negationToken :: Char
-negationToken	= '^'
-
--- | The set of 'Char' to which a specific meaning is attributed, when reading from 'String'.
-tokens :: String
-tokens	= [fst delimiterTokens, snd delimiterTokens, negationToken]
-
diff --git a/src/RegExDot/BracketExpressionMember.hs b/src/RegExDot/BracketExpressionMember.hs
deleted file mode 100644
--- a/src/RegExDot/BracketExpressionMember.hs
+++ /dev/null
@@ -1,93 +0,0 @@
-{-
-	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@]
-
-	Permits /Perl-style shortcut/s to be canned & assigned a single-'Char' mnemonic for subsequent reference;
-	the implementation of 'Read' looks for a back-slashed 'Char', for which it expects there to be a corresponding canned 'ShowablePredicate.ShowablePredicate'.
-
- [@CAVEATS@]
-
-	Since the underlying polymorphic data-type isn't required to implement neither 'Enum' nor 'Ord', the implementation of 'Read' can't cope with range-specifications.
-	Lacking this, Bracket-expression members must be enumerated exhaustively.
--}
-
-module RegExDot.BracketExpressionMember(
--- * Type-classes
-	ShortcutExpander(..),
--- * Types
--- ** Data-types
-	Member(..),
--- * Functions
--- ** Operators
-	(=~)
-) where
-
-import qualified	Control.Arrow
-import qualified	Control.DeepSeq
-import qualified	RegExDot.ShowablePredicate	as ShowablePredicate
-
-infix 4 =~	-- Same as (==).
-
-{- |
-	* The interface via which /Perl-style shortcut/s are expanded (when they occur within a /bracket-expression/), in a manner appropriate to the chosen type-parameter.
-
-	* The expansion of /Perl-style shortcut/s, is more restricted inside than outside, a /bracket-expression/,
-	& consequently are merely represented here by a 'ShowablePredicate.ShowablePredicate', rather than providing a more general form suitable also for those /Perl-style shortcuts/ found outside /bracket-expression/s.
-
-	* This interface is implemented elsewhere, where the specific type-parameter & consequently the appropriate set of /Perl-style shortcut/s, are defined.
--}
-class ShortcutExpander a	where
-	findPredicate	:: Char -> Maybe (ShowablePredicate.ShowablePredicate a)	-- ^ Attempt to find the appropriate 'ShowablePredicate.ShowablePredicate' to implement this /Perl-style shortcut/.
-
-{- |
-	* A /BracketExpression/ can contain either a literal, a range of literals given @(Enum a, Ord a)@, a /Perl-style shortcut/, or when 'Char' is the type-parameter, a /POSIX Character-class/.
-
-	* This data-type reduces the representation of all these possibilities to either a predicate or a literal.
--}
-data Member m	=
-	Predicate (ShowablePredicate.ShowablePredicate m)	-- ^ This 'Member' is described using a /predicate/, which is run to determine whether the datum conforms & is a member of the "BracketExpression".
-	| Literal m						-- ^ This 'Member' is defined literally, using an item of the polymorphic type.
-	deriving Eq
-
-instance Show m => Show (Member m)	where
-	showsPrec _ (Predicate showablePredicate)	= shows showablePredicate
-	showsPrec _ (Literal literal)			= shows literal
-
-instance (ShortcutExpander m, Read m) => Read (Member m)	where
-	readsPrec _ []				= []		-- No parse.
-	readsPrec _ (' ' : s)			= reads s	-- Consume white-space.
-	readsPrec _ ('\t' : s)			= reads s	-- Consume white-space.
-	readsPrec _ ('\\' : shortcut : s)	= case findPredicate shortcut of
-		Just showablePredicate	-> [(Predicate showablePredicate, s)]
-		_			-> error $ "readsPrec RegExDot.BracketExpressionMember.Member:\tfindPredicate failed for shortcut " ++ show shortcut
-	readsPrec _ literal			= Control.Arrow.first Literal `map` reads literal
-
-instance Control.DeepSeq.NFData m => Control.DeepSeq.NFData (Member m)	where
-	rnf (Predicate showablePredicate)	= Control.DeepSeq.rnf showablePredicate
-	rnf (Literal literal)			= Control.DeepSeq.rnf literal
-
--- | Match-operator.
-(=~) :: Eq m
-	=> m		-- ^ The input datum.
-	-> Member m	-- ^ The member of the bracket-expression against which the input-datum is to be matched.
-	-> Bool		-- ^ The result of the match-operation.
-datum =~ Predicate showablePredicate	= ShowablePredicate.predicate showablePredicate datum
-datum =~ Literal literal		= datum == literal
-
diff --git a/src/RegExDot/CompilationOptions.hs b/src/RegExDot/CompilationOptions.hs
deleted file mode 100644
--- a/src/RegExDot/CompilationOptions.hs
+++ /dev/null
@@ -1,48 +0,0 @@
-{-
-	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@]
-
-	* Defines those options relating to compile-time.
-
-	* These tend to be options which affect the result, rather than the means by which it is achieved.
-
-	* Whilst similar structures are present in other regex-implementations, there's no standardisation of the fields.
--}
-
-module RegExDot.CompilationOptions(
--- * Types
--- ** Data-types
-	CompilationOptions(..)
-) where
-
-import qualified	ToolShed.Defaultable
-import qualified	ToolShed.Options
-
--- | The switch(es) used to control compilation of the /regex/-engine.
-data CompilationOptions	= MkCompilationOptions {
-	complyStrictlyWithPosix	:: Bool		-- ^ Define the offset of captured data, corresponding to a sub-expression which matched zero times, as the artificial value @-1@ specified by POSIX.
-} deriving (Eq, Show)
-
-instance ToolShed.Defaultable.Defaultable CompilationOptions	where
-	defaultValue	= ToolShed.Options.blankValue { complyStrictlyWithPosix	= True }
-
-instance ToolShed.Options.Options CompilationOptions	where
-	blankValue	= MkCompilationOptions { complyStrictlyWithPosix = undefined }
-
diff --git a/src/RegExDot/Consumer.hs b/src/RegExDot/Consumer.hs
deleted file mode 100644
--- a/src/RegExDot/Consumer.hs
+++ /dev/null
@@ -1,105 +0,0 @@
-{-
-	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@]
-
-	* Define the requirements & capabilities of a data-type which is designed to consume data.
-
-	* This module also facilitates investigation of group-behaviour, by defining operations on either concatenations or alternations of 'Consumer's.
-
-	* This module is specifically for use in a /regex/-engine,
-	in which the meta-data from which the /regex/ is composed, are considered to /consume/ input data,
-	whilst concatenation & alternation of such elements, behave as a different types of groups of consumer.
--}
-
-module RegExDot.Consumer(
--- * Type-classes
-	Consumer(..),
--- * Types
--- ** Type-synonyms
---	StarHeight,
--- * Functions
-	accumulateConsumptionProfiles,
---	accumulateConsumptionProfilesFrom,
-	aggregateConsumptionProfilesFromAlternatives,
-	aggregateConsumptionProfilesFromConcatenation,
--- ** Query
-	getConsumptionBounds,
-	getFewest,
-	getHasSpecificRequirement
-) where
-
-import			RegExDot.ConsumptionProfile((<>), (|+|))
-import qualified	Data.List
-import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
-import qualified	RegExDot.ConsumptionProfile	as ConsumptionProfile
-
-{- |
-	* A measure of the complexity of a /regex/, which has some baring on either the time-complexity or the space-complexity of the solution.
-
-	* <http://en.wikipedia.org/wiki/Star_height>
--}
-type StarHeight	= Int
-
-{- |
-	* The interface, to which types, which have a data-requirement, may conform.
-
-	* Regrettably, methods requiring reference to the type of the consumable, would require multi-parameter type-classes.
-
-	* 'consumptionProfile' defines the quantity-range of data which may be consumed, & any specific data-requirements.
-
-	* 'starHeight' measures the complexity of the 'Consumer'.
--}
-class Consumer c	where
-	consumptionProfile	:: c -> ConsumptionProfile.ConsumptionProfile
-	starHeight		:: c -> StarHeight
-
-instance Consumer c => Consumer [c] where
-	consumptionProfile	= undefined
-	starHeight		= Data.List.foldl' (\l -> max l . starHeight) 0
-
--- | Convenience-function, to query the 'ConsumptionBounds.ConsumptionBounds' of a 'Consumer'.
-getConsumptionBounds :: Consumer c => c -> ConsumptionBounds.ConsumptionBounds
-getConsumptionBounds	= ConsumptionProfile.consumptionBounds . consumptionProfile
-
--- | Determine the minimum acceptable quantity of data.
-getFewest :: Consumer c => c -> ConsumptionBounds.DataLength
-getFewest	= fst . getConsumptionBounds
-
--- | Determine whether the specified 'Consumer', has a specific requirement.
-getHasSpecificRequirement :: Consumer c => c -> Bool
-getHasSpecificRequirement	= ConsumptionProfile.hasSpecificRequirement . consumptionProfile
-
--- | The aggregate of the specified alternation of 'ConsumptionProfile.ConsumptionProfile's.
-aggregateConsumptionProfilesFromAlternatives :: Consumer c => [c] -> ConsumptionProfile.ConsumptionProfile
-aggregateConsumptionProfilesFromAlternatives []	= error "RegExDot.Consumer.aggregateConsumptionProfilesFromAlternatives:\tnull list"
-aggregateConsumptionProfilesFromAlternatives l	= Data.List.foldl1' (<>) $ consumptionProfile `map` l
-
--- | Get the 'ConsumptionProfile.ConsumptionProfile's for the specified list of 'Consumer's, then find the net effect of concatenating them.
-aggregateConsumptionProfilesFromConcatenation :: Consumer c => [c] -> ConsumptionProfile.ConsumptionProfile
-aggregateConsumptionProfilesFromConcatenation	= Data.List.foldl' (\acc -> (acc |+|) . consumptionProfile) ConsumptionProfile.zero {-initial value-}
-
--- | Get the 'ConsumptionProfile.ConsumptionProfile' for the specified list of 'Consumer's, then accumulate them, from the specified initial value.
-accumulateConsumptionProfilesFrom :: Consumer c => ConsumptionProfile.ConsumptionProfile -> [c] -> ConsumptionProfile.AccumulatedConsumptionProfiles
-accumulateConsumptionProfilesFrom	= scanr ((|+|) . consumptionProfile)
-
--- | Get the 'ConsumptionProfile.ConsumptionProfile' for the specified list of 'Consumer's, then accumulate them.
-accumulateConsumptionProfiles :: Consumer c => [c] -> ConsumptionProfile.AccumulatedConsumptionProfiles
-accumulateConsumptionProfiles	= {-init .-} accumulateConsumptionProfilesFrom ConsumptionProfile.zero	-- It's useful to leave the initial value at the end of the list.
-
diff --git a/src/RegExDot/ConsumptionBounds.hs b/src/RegExDot/ConsumptionBounds.hs
deleted file mode 100644
--- a/src/RegExDot/ConsumptionBounds.hs
+++ /dev/null
@@ -1,48 +0,0 @@
-{-
-	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@]	Describes the bounds of data-consumption.
--}
-
-module RegExDot.ConsumptionBounds(
--- * Types
--- ** Type-synonyms
-	ConsumptionBounds,
-	DataLength,
--- * Constants
-	zero,
--- * Functions
--- ** Predicates
-	isPrecise
-) where
-
--- | A measure of the quantity of an unspecified type of data.
-type DataLength	= Int
-
--- | The minimum & maximum bounds of potential data-consumption.
-type ConsumptionBounds	= (DataLength, Maybe DataLength)
-
--- | Exactly zero consumption.
-zero :: ConsumptionBounds
-zero	= (0, Just 0)
-
--- | Predicate which is 'True' if only a precise quantity of data is consumable; no more, no less.
-isPrecise :: ConsumptionBounds -> Bool
-isPrecise (fewest, most)	= Just fewest == most
-
diff --git a/src/RegExDot/ConsumptionProfile.hs b/src/RegExDot/ConsumptionProfile.hs
deleted file mode 100644
--- a/src/RegExDot/ConsumptionProfile.hs
+++ /dev/null
@@ -1,148 +0,0 @@
-{-
-	Copyright (C) 2010-2015 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 'RegExDot.ConsumptionProfile' is composed from both a capacity to consume, & an ability to discriminate based on the specific data.
-	The former is described by 'consumptionBounds' & the latter by both 'hasSpecificRequirement' & 'canConsumeAnything'.
--}
-
-module RegExDot.ConsumptionProfile(
--- * Types
--- ** Type-synonyms
-	AccumulatedConsumptionProfiles,
--- ** Data-types
-	ConsumptionProfile(..),
--- * Constants
-	zero,
--- * Functions
-	accumulateFrom,
-	aggregateFromConcatenation,
--- ** Operators
-	(|+|),
-	(<>),
--- ** Predicates
---	isPrecise,
-	withinConsumptionBounds
-) where
-
-import Prelude hiding ((<$>), (<*>))	-- The "Prelude" from 'base-4.8' exports this symbol.
-import			Control.Applicative((<$>), (<*>))
-import			Control.Arrow((***))
-import qualified	Data.List
-import qualified	Data.Maybe
-import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
-import qualified	ToolShed.SelfValidate
-
-infixr 5 |+|	-- Same as (++).
-infixr 2 <>	-- Same as (||).
-
-{- |
-	* A 'Consumer' is considered to have a 'ConsumptionProfile' composed from both a capacity to consume, & an ability to discriminate.
-
-	* Whilst 'hasSpecificRequirement' & 'canConsumeAnything' look like opposites, they can assume independent values; the instance can be both, but only be neither when empty.
--}
-data ConsumptionProfile	= MkConsumptionProfile {
-	consumptionBounds	:: ConsumptionBounds.ConsumptionBounds,	-- ^ The permissible quantity of data, which can be consumed.
-	hasSpecificRequirement	:: Bool,				-- ^ Whether at least one specific input datum is required.
-	canConsumeAnything	:: Bool					-- ^ Whether at least one arbitrary input datum can be consumed.
-} deriving (Eq, Read, Show)
-
-instance ToolShed.SelfValidate.SelfValidator ConsumptionProfile	where
-	getErrors c@(
-		MkConsumptionProfile {
-			consumptionBounds	= (fewest, most),
-			hasSpecificRequirement	= hasSpecificRequirement',
-			canConsumeAnything	= canConsumeAnything'
-		}
-	 ) = ToolShed.SelfValidate.extractErrors [
-		(fewest < 0, "Negative fewest=" ++ show fewest ++ "."),
-		(
-			case most of
-				Just m	-> m < fewest
-				_	-> False,
-			"Invalid 'most'; " ++ show c ++ "."
-		),
-		(not $ or [c == zero, hasSpecificRequirement', canConsumeAnything'], "Invalid " ++ show c ++ ".")
-	 ]
-
-{-
--- | True if there's no choice in the quantity of data to consume.
-isPrecise :: ConsumptionProfile -> Bool
-isPrecise	= ConsumptionBounds.isPrecise . consumptionBounds
--}
-
--- | Predicate, which is 'True' if the specified data-length, falls within the specified 'ConsumptionBounds.ConsumptionBounds'.
-withinConsumptionBounds
-	:: ConsumptionBounds.DataLength	-- ^ The actual quantity of data consumed.
-	-> ConsumptionProfile		-- ^ The bounds within which data-consumption is required to fall.
-	-> Bool
-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
-zero	= MkConsumptionProfile {
-	consumptionBounds	= ConsumptionBounds.zero,
-	hasSpecificRequirement	= False,
-	canConsumeAnything	= False
-}
-
--- | The net effect of two concatenated 'ConsumptionProfile's.
-(|+|) :: ConsumptionProfile -> ConsumptionProfile -> ConsumptionProfile
-MkConsumptionProfile {
-	consumptionBounds	= (lf, ls),
-	hasSpecificRequirement	= lh,
-	canConsumeAnything	= lc
-} |+| MkConsumptionProfile {
-	consumptionBounds	= (rf, rs),
-	hasSpecificRequirement	= rh,
-	canConsumeAnything	= rc
-} = MkConsumptionProfile {
-	consumptionBounds	= (lf + rf, (+) <$> ls <*> rs),	-- The sum of those of the concatenation.
-	hasSpecificRequirement	= lh || rh,			-- The concatenation mandates consumption of at least one specific input datum, if either 'ConsumptionProfile' does.
-	canConsumeAnything	= lc || rc			-- The concatenation can consume at least one arbitrary input datum, if either 'ConsumptionProfile' can.
-}
-
--- | The net effect of two alternative 'ConsumptionProfile's.
-(<>) :: ConsumptionProfile -> ConsumptionProfile -> ConsumptionProfile
-MkConsumptionProfile {
-	consumptionBounds	= (lf, ls),
-	hasSpecificRequirement	= lh,
-	canConsumeAnything	= lc
-} <> MkConsumptionProfile {
-	consumptionBounds	= (rf, rs),
-	hasSpecificRequirement	= rh,
-	canConsumeAnything	= rc
-} = MkConsumptionProfile {
-	consumptionBounds	= (lf `min` rf, max <$> ls <*> rs),	-- Stretched to envelope alternatives.
-	hasSpecificRequirement	= lh && rh,				-- The alternation mandates consumption of at least one specific input datum, if both 'ConsumptionProfile's do.
-	canConsumeAnything	= lc || rc				-- The alternation can consume at least one arbitrary input datum, if either 'ConsumptionProfile' can.
-}
-
--- | The aggregate of the specified concatenation of 'ConsumptionProfile's.
-aggregateFromConcatenation :: [ConsumptionProfile] -> ConsumptionProfile
-aggregateFromConcatenation	= Data.List.foldl' (|+|) zero {-initial value-}
-
--- | The 'ConsumptionProfile's of all the aggregated tails of a list of 'Consumer's.
-type AccumulatedConsumptionProfiles	= [ConsumptionProfile]
-
--- | Accumulate the specified list of 'ConsumptionProfile's, from the specified initial value.
-accumulateFrom :: ConsumptionProfile -> [ConsumptionProfile] -> AccumulatedConsumptionProfiles
-accumulateFrom	= scanr (|+|)
-
diff --git a/src/RegExDot/DSL.hs b/src/RegExDot/DSL.hs
deleted file mode 100644
--- a/src/RegExDot/DSL.hs
+++ /dev/null
@@ -1,117 +0,0 @@
-{-
-	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@]
-
-	* Defines /binary/ operators, to form a /Domain-specific Language/, by which to compose 'RegEx.Concatenations' from 'RegEx.Pattern's.
-
-	* Each operator quantifies the specified 'RegEx.Pattern', & prepends it to the specified 'RegEx.Concatenation'.
-
- [@TODO@]	Could @[]@ & 'Meta' be instances of a type-class which has methods (-:) etc.,
-		allowing the former to prepend 'RegEx.captureGroup' & the latter 'RegEx.Require' ?
-
--}
-
-module RegExDot.DSL(
--- * Functions
--- ** Operators
-	(-:),
-	(?:),
-	(??:),
-	(*:),
-	(*?:),
-	(+:),
-	(+?:),
-	( #->#:),
-	( #->#?:),
-	( #->:),
-	( #->?:),
-	( #:),
-	(<~>)
-) where
-
-import			RegExDot.Repeatable((^#->#), (^#->#?), (^#->), (^#->?), (^#))
-import qualified	RegExDot.Anchor		as Anchor
-import qualified	RegExDot.RegEx		as RegEx
-import qualified	RegExDot.Repeatable	as Repeatable
-
-infixr 5 -:, ?:, ??:, *:, *?:, +:, +?:,#->#:, #->#?:, #->:, #->?:, #:, <~>	-- Same as for ':', & lower than Repeatable's operators.
-
--- | Prepend an unrepeated 'RegEx.Pattern', to the specified 'RegEx.Concatenation'.
-(-:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
-(-:) pattern	= (Repeatable.one pattern :)
-
--- | Prepend an optional 'RegEx.Pattern', to the specified 'RegEx.Concatenation'.
-(?:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
-(?:) pattern	= (Repeatable.zeroOrOne pattern :)
-
--- | A /non-greedy/ version of '?:'.
-(??:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
-(??:) pattern	= (Repeatable.zeroOrOne' pattern :)
-
--- | Prepend a 'RegEx.Pattern', repeatable zero or more times, to the specified 'RegEx.Concatenation'.
-(*:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
-(*:) pattern	= (Repeatable.zeroOrMore pattern :)
-
--- | A /non-greedy/ version of '*:'.
-(*?:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
-(*?:) pattern	= (Repeatable.zeroOrMore' pattern :)
-
--- | Prepend a 'RegEx.Pattern', repeatable one or more times, to the specified 'RegEx.Concatenation'.
-(+:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
-(+:) pattern	= (Repeatable.oneOrMore pattern :)
-
--- | A /non-greedy/ version of '+:'.
-(+?:) :: RegEx.Pattern a -> RegEx.Concatenation a -> RegEx.Concatenation a
-(+?:) pattern	= (Repeatable.oneOrMore' pattern :)
-
--- | Prepend a 'RegEx.Pattern', repeated a range of times, to the specified 'RegEx.Concatenation'.
-( #->#:) :: (RegEx.Pattern a, Repeatable.RepetitionBounds) -> RegEx.Concatenation a -> RegEx.Concatenation a
-( #->#:) (pattern, bounds)	= (pattern ^#-># bounds :)
-
--- | A /non-greedy/ version of '#->#:'.
-( #->#?:) :: (RegEx.Pattern a, Repeatable.RepetitionBounds) -> RegEx.Concatenation a -> RegEx.Concatenation a
-( #->#?:) (pattern, bounds)	= (pattern ^#->#? bounds :)
-
--- | Prepend a 'RegEx.Pattern', repeated at least a specified number of times, to the specified 'RegEx.Concatenation'.
-( #->:) :: (RegEx.Pattern a, Repeatable.Repetitions) -> RegEx.Concatenation a -> RegEx.Concatenation a
-( #->:) (pattern, fewest)	= (pattern ^#-> fewest :)
-
--- | A /non-greedy/ version of '#->:'.
-( #->?:) :: (RegEx.Pattern a, Repeatable.Repetitions) -> RegEx.Concatenation a -> RegEx.Concatenation a
-( #->?:) (pattern, fewest)	= (pattern ^#->? fewest :)
-
--- | Prepend a 'RegEx.Pattern', repeated a precise number of times, to the specified 'RegEx.Concatenation'.
-( #:) :: (RegEx.Pattern a, Repeatable.Repetitions) -> RegEx.Concatenation a -> RegEx.Concatenation a
-( #:) (pattern, r)	= (pattern ^# r :)
-
-{- |
-	* Sandwiches a 'RegEx.Concatenation' between optional 'Anchor.Anchor's to construct a 'RegEx.ExtendedRegEx'.
-
-	* Accounts for the unusual requirement to place an 'Anchor.Stern' at the start of the 'RegEx.Concatenation', or an 'Anchor.Bow' at the end.
--}
-(<~>)
-	:: 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,
-	RegEx.sternAnchor	= stern
-}
diff --git a/src/RegExDot/DataSpan.hs b/src/RegExDot/DataSpan.hs
deleted file mode 100644
--- a/src/RegExDot/DataSpan.hs
+++ /dev/null
@@ -1,61 +0,0 @@
-{-
-	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@]	Augments a 'Span.Span', with the specific data concerned.
--}
-
-module RegExDot.DataSpan(
--- * Types
--- ** Type-synonyms
-	DataSpan,
--- * Functions
-	after,
-	empty,
-	join
-) where
-
-import			Control.Arrow((***))
-import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
-import qualified	RegExDot.Span			as Span
-
-{- |
-	* Augment 'Span.Span' with a copy of the data to which it refers.
-
-	* Similar to <http://hackage.haskell.org/packages/archive/regex-base/latest/doc/html/Text-Regex-Base-RegexLike.html#t%3AMatchText>.
--}
-type DataSpan a	= ([a], Span.Span)
-
--- | Constructs an empty instance, located at the specified offset.
-empty :: ConsumptionBounds.DataLength -> DataSpan a
-empty offset	= ([], Span.empty offset)
-
--- | Returns the furthest extent, i.e. the offset just after the end.
-after :: DataSpan a -> ConsumptionBounds.DataLength
-after	= Span.after . snd
-
-{- |
-	* Condenses a list into a single value.
-
-	* Expects a gap-free, sorted list.
--}
-join
-	:: ConsumptionBounds.DataLength	-- ^ The offset at which the concatenated match is considered to have occurred.
-	-> [DataSpan a]			-- ^ The list to be concatenated.
-	-> DataSpan a
-join offset	= (concat *** Span.join offset) . unzip
diff --git a/src/RegExDot/DataSpanTree.hs b/src/RegExDot/DataSpanTree.hs
deleted file mode 100644
--- a/src/RegExDot/DataSpanTree.hs
+++ /dev/null
@@ -1,108 +0,0 @@
-{-
-	Copyright (C) 2010-2015 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@]	Permits transformation of 'RegEx.MatchList', to facilitate standardisation.
--}
-
-module RegExDot.DataSpanTree(
--- * Types
--- ** Type-synonyms
---	DataSpanTree,
---	DataSpanTreeList,
--- * Functions
-	extractCaptureGroups,
-	flattenTreeList,
-	toTreeList
-) where
-
-import qualified	Data.Foldable
-import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
-import qualified	RegExDot.DataSpan		as DataSpan
-import qualified	RegExDot.RegEx			as RegEx
-import qualified	RegExDot.Tree			as Tree
-
--- | Defines a similar 'Tree.Tree' to 'RegEx.Match', but with different 'Tree.Leaf's.
-type DataSpanTree a	= Tree.Tree (DataSpan.DataSpan a)
-
--- | Defines a similar structure to 'RegEx.MatchList'.
-type DataSpanTreeList a	= [DataSpanTree a]
-
--- | Converts a 'RegEx.MatchList' into a 'DataSpanTreeList', by transforming the 'Tree.Leaf's.
-toTreeList :: RegEx.MatchList a -> DataSpanTreeList a
-toTreeList	= map toTree	where
-	toTree :: RegEx.Match a -> DataSpanTree a
-	toTree	= fmap toDataSpan	where
-		toDataSpan :: RegEx.MatchedData a -> DataSpan.DataSpan a
-		toDataSpan (_, inputDataOffset, inputData)	= (inputData, (inputDataOffset, length inputData))
-
--- | Condenses a 'DataSpanTreeList's into a list of 'DataSpan.DataSpan's, using 'DataSpan.join'.
-flattenTreeList
-	:: ConsumptionBounds.DataLength	-- ^ The offset into the input-data at which a match occurred.
-	-> DataSpanTreeList a		-- ^ The tree to flatten.
-	-> [DataSpan.DataSpan a]
-flattenTreeList _ []				= []
-flattenTreeList offset (tree : treeList)	= flattenedTree : flattenTreeList (DataSpan.after flattenedTree) treeList	where
---	flattenedTree :: DataSpan.DataSpan a
-	flattenedTree	= DataSpan.join offset $ Data.Foldable.toList tree
-
-{- |
-	* POSIX describes the contents of /capture-groups/, as summarised in <http://www2.research.att.com/~gsf/testregex/>.
-
-	* 'RegEx.Result', is a complete description of the match between 'RegEx.InputData' & RegEx.ExtendedRegEx'; this function extracts a POSIX-conformant list from it.
-
-	* The major differences are, that:
-
-		Only data from parenthesized sub-expressions ('RegEx.Alternatives') is captured.
-
-		Only the /last/ repetition of a repeated sub-expression is returned.
-		<http://www.opengroup.org/onlinepubs/009695399/functions/regcomp.html>.
-
-		The data captured within each parenthesized sub-expression, is summarised as a single 'DataSpan.DataSpan'.
-
-		POSIX specifies a 'Span.Span'-offset of @-1@, for sub-expressions which match zero times; cf sub-expressions which consume nothing, once.
-		<http://www.opengroup.org/onlinepubs/009695399/functions/regcomp.html>.
-		@
-			("ace" Text.Regex.Posix.=~ "a(b)*c(d)?e") :: Text.Regex.Base.RegexLike.MatchArray
-			array (0,2) [(0,(0,3)),(1,(-1,0)),(2,(-1,0))]
-
-			("ace" Text.Regex.Posix.=~ "a(b*)c(d?)e") :: Text.Regex.Base.RegexLike.MatchArray
-			array (0,2) [(0,(0,3)),(1,(1,0)),(2,(2,0))]
-		@
-		I consider this a poor convention, resulting from the focus of POSIX on C, which makes subsequent calculation from the list of 'DataSpan's difficult & error-prone.
--}
-extractCaptureGroups
-	:: Bool			-- ^ Whether to strictly comply with /POSIX/.
-	-> DataSpanTreeList a	-- ^ The tree-structure from which to extract the capture-groups.
-	-> [DataSpan.DataSpan a]
-extractCaptureGroups complyStrictlyWithPosix	= extractCaptureGroups' 0	where
-	extractCaptureGroups' :: ConsumptionBounds.DataLength -> DataSpanTreeList a -> [DataSpan.DataSpan a]
-	extractCaptureGroups' _ []			= []
-	extractCaptureGroups' offset (tree : treeList)	= let
---		recurseHorizontallyFrom :: ConsumptionBounds.DataLength -> [DataSpan.DataSpan a]
-		recurseHorizontallyFrom	= (`extractCaptureGroups'` treeList)
-	 in case tree of
-		Tree.Leaf dataSpan	-> recurseHorizontallyFrom $ DataSpan.after dataSpan
-		Tree.Node []		-> DataSpan.empty (if complyStrictlyWithPosix then -1 else offset) : recurseHorizontallyFrom offset	-- POSIX specifies an Span-offset of -1, for sub-expressions which match 0 times; cf sub-expressions which consumes nothing, once.
-		Tree.Node treeLists	-> joinedFlattenedTreeList : (extractCaptureGroups' offset lastMatch {-recurse vertically-} ++ recurseHorizontallyFrom (DataSpan.after joinedFlattenedTreeList))	where
---			lastMatch :: DataSpanTreeList a
-			lastMatch	= last treeLists	-- <http://www.opengroup.org/onlinepubs/009695399/functions/regcomp.html>.
-
---			joinedFlattenedTreeList :: DataSpan.DataSpan a
-			joinedFlattenedTreeList	= DataSpan.join offset $ flattenTreeList offset lastMatch
-
diff --git a/src/RegExDot/ExecutionOptions.hs b/src/RegExDot/ExecutionOptions.hs
deleted file mode 100644
--- a/src/RegExDot/ExecutionOptions.hs
+++ /dev/null
@@ -1,102 +0,0 @@
-{-
-	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@]
-
-	* Defines those options relating to the "RegExDot.RegEx"-runtime.
-
-	* These tend to be options which don't affect the result, only the means by which it is achieved.
-
-	* Whilst similar structures are present in other regex-implementations, there's no standardisation of the fields.
--}
-
-module RegExDot.ExecutionOptions(
--- * Types
--- ** Data-types
-	ExecutionOptions(..),
--- * Functions
--- ** Mutators
-	setVerbose
-) where
-
-import qualified	ToolShed.Defaultable
-import qualified	ToolShed.Options
-
--- | The switches used to control execution of the /regex/-engine.
-data ExecutionOptions	= MkExecutionOptions {
-	abortTrialRepetitionsOnInherentFailure	:: Bool,	-- ^ If an /alternative/ can't match, irrespective of the subsequent /RegExDot.RegEx.Concatenation/, then avoid futile trial /RegExDot.Repeatable.Repetitions/. The converse of 'checkForUnconsumableData'.
-	abortTrialRepetitionsOnZeroConsumption	:: Bool,	-- ^ Check for zero data-consumption by the @n@-th /RegExDot.Repeatable.Repeatable RegExDot.RegEx.CaptureGroup/, before attempting @n+1@.
-	bypassInputDataForLiberalConsumer	:: Bool,	-- ^ Whether to bypass reading of the input data, if the mapping to specific /RegExDot.RegEx.RepeatablePattern/s isn't required, & the /RegExDot.RegEx.ExtendedRegEx/ can consume the required quantity of anything.
-	catchIncompatibleAnchors		:: Bool,	-- ^ Avoid futile trial solutions, involving repetitions of anchored alternatives, which must consume data.
-	checkExistenceOfInelasticTail		:: Bool,	-- ^ If the /RegExDot.RegEx.ExtendedRegEx/ ends in an inelastic (zero /Star-height/) tail, confirm its existence at the end of the /RegExDot.RegEx.InputData/.
-	checkForUnconsumableData		:: Bool,	-- ^ Check whether there's no possibility of consuming some of the input data. The converse of 'abortTrialRepetitionsOnInherentFailure'.
-	moderateGreed				:: Bool,	-- ^ Greedily consume data, only up to the limit beyond which, future requirements would be compromised.
-	permitReorderingOfAlternatives		:: Bool,	-- ^ Permit /RegExDot.RegEx.Alternatives/ to be re-ordered, in an attempt to more quickly locate a result.
-	preferAlternativesWhichFeedTheGreedy	:: Bool,	-- ^ Within the /RegExDot.RegEx.MatchedData/ from which each candidate /RegExDot.RegEx.Match/ amongst sequences of /RegExDot.RegEx.Alternatives/, is ultimately composed, prefer /RegExDot.ConsumptionBounds.ConsumptionBounds/ of /RegExDot.RegEx.InputData/, beyond /RegExDot.Repeatable.getFewest/, by /RegExDot.Repeatable.isGreedy RegExDot.RegEx.RepeatablePattern/s.
-	preferAlternativesWhichMimickUnrolling	:: Bool,	-- ^ Compare /RegExDot.ConsumptionBounds.ConsumptionBounds/ on successive /RegExDot.Repeatable.Repetitions/ of /RegExDot.RegEx.CaptureGroup/, between candidate /RegExDot.RegEx.Match/es, to mimic the behaviour of the unrolled /RegExDot.Repeatable.Repetitions/.
-	preferFewerRepeatedAlternatives		:: Bool,	-- ^ Prefer fewer /RegExDot.Repeatable.Repetitions/ of /RegExDot.RegEx.Alternatives/, to discourage the capture of null lists of /RegExDot.RegEx.InputData/.
-	requireMatchList			:: Bool,	-- ^ If merely interested in a 'Bool' result, rather than the optimal mapping of input data to /RegExDot.RegEx.RepeatablePattern/s, avoid unnecessary evaluation of the /RegEx.Match/.
-	unrollRepeatedSingletonAlternative	:: Bool,	-- ^ Check whether /RegExDot.RegEx.Alternatives/ consists of just a singleton /RegExDot.RegEx.ExtendedRegEx/, & has therefore been used merely as a capture-group. Though this doesn't affect the result, it vastly improves efficiency.
-	useFirstMatchAmongAlternatives		:: Bool,	-- ^ Rather than performing an exhaustive search for the optimal choice amongst /RegExDot.RegEx.Alternatives/, merely select the first that matches; conform to /Perl/ rather than /POSIX/.
-	validateMinConsumptionOfAlternatives	:: Bool		-- ^ When the number of repetitions of a /RegExDot.RegEx.CaptureGroup/ is precisely specified, check whether the resulting minimum data-requirement is available.
-} deriving (Eq, Show)
-
-instance ToolShed.Defaultable.Defaultable ExecutionOptions	where
-	defaultValue	= setVerbose False $ ToolShed.Options.blankValue {
-		abortTrialRepetitionsOnInherentFailure	= True,		-- Regrettably, this slightly reduces performance for most non-pathological patterns.
-		catchIncompatibleAnchors		= True,
-		checkExistenceOfInelasticTail		= True,
-		checkForUnconsumableData		= True,		-- Expensive, particularly when (not requireMatchList), & only typically useful in failure-scenarios.
-		moderateGreed				= True,		-- Cost may exceed benefit. TODO: confirm.
-		preferAlternativesWhichFeedTheGreedy	= True,
-		preferAlternativesWhichMimickUnrolling	= True,
-		preferFewerRepeatedAlternatives		= True,
-		unrollRepeatedSingletonAlternative	= True,		-- Affects only efficiency, not the result.
-		useFirstMatchAmongAlternatives		= False,	-- Perl-style matching may be faster, but may also yield a sub-optimal Match.
-		validateMinConsumptionOfAlternatives	= False		-- The cost outweighs the small infrequent dividend.
-	}
-
-instance ToolShed.Options.Options ExecutionOptions	where
-	blankValue	= MkExecutionOptions {
-		abortTrialRepetitionsOnInherentFailure	= undefined,
-		abortTrialRepetitionsOnZeroConsumption	= undefined,
-		bypassInputDataForLiberalConsumer	= undefined,
-		catchIncompatibleAnchors		= undefined,
-		checkExistenceOfInelasticTail		= undefined,
-		checkForUnconsumableData		= undefined,
-		moderateGreed				= undefined,
-		permitReorderingOfAlternatives		= undefined,
-		preferAlternativesWhichFeedTheGreedy	= undefined,
-		preferAlternativesWhichMimickUnrolling	= undefined,
-		preferFewerRepeatedAlternatives		= undefined,
-		requireMatchList			= undefined,
-		unrollRepeatedSingletonAlternative	= undefined,
-		useFirstMatchAmongAlternatives		= undefined,
-		validateMinConsumptionOfAlternatives	= undefined
-	}
-
--- | Sets those fields which depend crucially on whether the caller wants to retrieve any /RegExDot.RegEx.MatchList/ from the /RegExDot.RegEx.Result/, or just query whether there is one.
-setVerbose :: Bool -> ExecutionOptions -> ExecutionOptions
-setVerbose verbose e	= e {
-	abortTrialRepetitionsOnZeroConsumption	= verbose,	-- The corresponding check, involves evaluation of a /RegExDot.RegEx.MatchList/, which is too expensive if the /RegExDot.RegEx.Matchlist/ isn't otherwise required.
-	bypassInputDataForLiberalConsumer	= not verbose,	-- Potentially bypasses reading of /RegExDot.RegEx.InputData/, which is inappropriate if the mapping into a /RegExDot.RegEx.Result/ is required.
-	permitReorderingOfAlternatives		= not verbose,	-- Doesn't help when 'requireMatchList', since an exhaustive search of /RegExDot.RegEx.Alternatives/, for the optimal solution, is performed.
-	requireMatchList			= verbose
-}
-
diff --git a/src/RegExDot/InstanceInt.hs b/src/RegExDot/InstanceInt.hs
deleted file mode 100644
--- a/src/RegExDot/InstanceInt.hs
+++ /dev/null
@@ -1,43 +0,0 @@
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-{-
-	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@]	Provides a default implementation of the type-classes, required for 'RegEx.ExtendedRegEx' Int.
-
- [@CAVEATS@]
-
-	In contrast to the traditional regex, there's no reason to escape a 'Char', other than when referring to a /shortcut/.
-	Since no /shortcuts/ are defined in this minimal definition, it's always an error to escape a character.
--}
-
-module RegExDot.InstanceInt() where
-
-import qualified	RegExDot.BracketExpressionMember	as BracketExpressionMember
-import qualified	RegExDot.Meta				as Meta
-import qualified	RegExDot.RegEx				as RegEx
-
-instance BracketExpressionMember.ShortcutExpander Int	where
-	findPredicate _	= Nothing
-
-instance Meta.ShortcutExpander Int	where
-	expand c	= error $ "RegExDot.Meta.ShortcutExpander.expand RegExDot.InstanceInt:\tunrecognised shortcut '" ++ show c ++ "'."	-- A shortcut is the only legitimate reason to escape a character.
-
-instance RegEx.ShortcutExpander Int	where
-	expand c	= error $ "RegExDot.RegEx.ShortcutExpander.expand RegExDot.InstanceInt:\tunrecognised shortcut '" ++ show c ++ "'."	-- A shortcut is the only legitimate reason to escape a character.
-
diff --git a/src/RegExDot/Meta.hs b/src/RegExDot/Meta.hs
deleted file mode 100644
--- a/src/RegExDot/Meta.hs
+++ /dev/null
@@ -1,144 +0,0 @@
-{-
-	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@]
-
-	* Describes the set of polymorphic data, which can be matched.
-
-	* Only permits a match against exactly one polymorphic datum, which distinguishes it from a /zero-width assertion/, like an /anchor/, /word-boundary/, or /look-ahead assertion/.
-
-	* Designed to be used by a polymorphic /regex/-engine, to implement the traditional meta-characters; @. [] [^]@.
-
-	* Permits /Perl-style shortcuts/ for commonly used 'Meta'-data, to be canned & assigned a single-'Char' mnemonic for subsequent reference;
-	the implementation of 'Read' looks for a back-slashed 'Char', for which it expects there to be a corresponding canned 'Meta'.
-	Since this class is polymorphic, it has no knowledge of what shortcuts might be appropriate for the chosen type-parameter,
-	so the expansion from the back-slashed 'Char' to corresponding 'Meta'-data, is performed through the 'expand' interface of the 'ShortcutExpander' class, which should be implemented elsewhere.
--}
-
-module RegExDot.Meta(
--- * Type-classes
-	ShortcutExpander(..),
--- * Types
--- ** Data-types
-	Meta(..),
--- * Constants
-	shortcutToken,
-	anyToken,
-	tokens,
--- * Functions
--- ** Predicates
-	isMatch
-) where
-
-import qualified	Control.Arrow
-import qualified	Control.DeepSeq
-import qualified	RegExDot.BracketExpression		as BracketExpression
-import qualified	RegExDot.BracketExpressionMember	as BracketExpressionMember
-import qualified	RegExDot.Consumer			as Consumer
-import qualified	RegExDot.ConsumptionProfile		as ConsumptionProfile
-import qualified	RegExDot.ShowablePredicate		as ShowablePredicate
-import qualified	ToolShed.SelfValidate
-
-{- |
-	* The interface via which /Perl-style shortcut/s are expanded, in a manner appropriate to the chosen type-parameter.
-
-	* Since the expansion of /Perl-style shortcut/s, is more restricted inside than outside a 'BracketExpression.BracketExpression',
-	the former is considered to be a superclass, providing a base from which to build alternative implementations.
--}
-class BracketExpressionMember.ShortcutExpander m => ShortcutExpander m	where
-	expand	:: Char -> Meta m	-- ^ Expand a /Perl-style shortcut/.
-
--- | Declares a polymorphic data-type.
-data Meta m =
-	Any							-- ^ Any datum matches. Equivalent to @NoneOf []@, but more efficient. CAVEAT: independent of the type-parameter @a@.
-	| Literal m						-- ^ The datum matches, if it's equal to the specified value. Equivalent to @AnyOf [BracketExpression.Literal x]@, but more efficient.
-	| AnyOf (BracketExpression.BracketExpression m)		-- ^ The datum matches, if 'BracketExpression.containsMatch'.
-	| NoneOf (BracketExpression.BracketExpression m)	-- ^ The datum matches, if @not BracketExpression.containsMatch@.
-	| Predicate (ShowablePredicate.ShowablePredicate m)	-- ^ The datum matches if 'ShowablePredicate.ShowablePredicate'.
-	deriving (
-		Eq
---		Read,	-- Specialised below.
---		Show	-- Specialised below.
-	)
-
-instance ToolShed.SelfValidate.SelfValidator (Meta m)	where
-	getErrors _	= []
-
-instance Show m => Show (Meta m)	where
-	showsPrec _ Any					= showChar anyToken
-	showsPrec _ (Literal m)				= shows m
-	showsPrec _ (AnyOf bracketExpression)		= shows bracketExpression
-	showsPrec _ (NoneOf bracketExpression)		= showChar x . showChar BracketExpression.negationToken . showString xs	where (x : xs)	= show $ AnyOf bracketExpression
-	showsPrec _ (Predicate showablePredicate)	= shows showablePredicate
-
-instance (ShortcutExpander m, Read m) => Read (Meta m)	where
-	readsPrec _ []				= []		-- No parse.
-	readsPrec _ (' ' : s)			= reads s	-- Consume white-space.
-	readsPrec _ ('\t' : s)			= reads s	-- Consume white-space.
-	readsPrec _ ('.' : s)			= [(Any, s)]
-	readsPrec _ ('[' : '^' : noneOf)	= Control.Arrow.first NoneOf `map` reads (fst BracketExpression.delimiterTokens : noneOf) {-Reconstruct without negation, & recurse-}
-	readsPrec _ anyOf@('[' : _)		= Control.Arrow.first AnyOf `map` reads anyOf {-singleton-}
-	readsPrec _ ('\\' : c : s)		= [(expand c, s)]
-	readsPrec _ literal			= Control.Arrow.first Literal `map` reads literal {-singleton-}
-
-instance Consumer.Consumer (Meta m)	where
-	consumptionProfile meta	= let
-		hasSpecificDataRequirement :: Bool
-		hasSpecificDataRequirement	= case meta of
-			Any		-> False
-			NoneOf []	-> False
-			_		-> True
-	 in ConsumptionProfile.MkConsumptionProfile {
-		ConsumptionProfile.consumptionBounds		= (1, Just 1),
-		ConsumptionProfile.hasSpecificRequirement	= hasSpecificDataRequirement,
-		ConsumptionProfile.canConsumeAnything		= not hasSpecificDataRequirement
-	 }
-
-	starHeight _	= 0
-
-instance Control.DeepSeq.NFData m => Control.DeepSeq.NFData (Meta m)	where
-	rnf Any					= ()
-	rnf (Literal m)				= Control.DeepSeq.rnf m
-	rnf (AnyOf bracketExpression)		= Control.DeepSeq.rnf bracketExpression
-	rnf (NoneOf bracketExpression)		= Control.DeepSeq.rnf bracketExpression
-	rnf (Predicate showablePredicate)	= Control.DeepSeq.rnf showablePredicate
-
--- | True if the specified datum matches.
-isMatch :: Eq m
-	=> m		-- ^ The input datum.
-	-> Meta m	-- ^ The meta-entity against which the input datum is to be matched.
-	-> Bool		-- ^ The result of the match-operation.
-isMatch _ Any					= True
-isMatch datum (Literal literal)			= datum == literal
-isMatch datum (AnyOf bracketExpression)		= datum `BracketExpression.containsMatch` bracketExpression
-isMatch datum (NoneOf bracketExpression)	= not $ datum `isMatch` AnyOf bracketExpression	-- This implementation leverages future enhancements to 'AnyOf'.
-isMatch datum (Predicate showablePredicate)	= ShowablePredicate.predicate showablePredicate datum
-
--- | The token used to precede a /Perl-style shortcut/, when in the 'String'-form.
-shortcutToken :: Char
-shortcutToken	= '\\'
-
--- | The token used to denote 'Any', when in the 'String'-form.
-anyToken :: Char
-anyToken	= '.'
-
--- | The set of 'Char' to which a specific meaning is attributed, when reading from 'String'.
-tokens :: String
-tokens	= [shortcutToken, anyToken] ++ BracketExpression.tokens
-
diff --git a/src/RegExDot/RegEx.hs b/src/RegExDot/RegEx.hs
deleted file mode 100644
--- a/src/RegExDot/RegEx.hs
+++ /dev/null
@@ -1,1198 +0,0 @@
-{-
-	Copyright (C) 2010-2015 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@]
-
-	* 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@.
-
-	* 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.
-	Each element of this 'Concatenation' is a 'RepeatablePattern', which describes a permissible match against 'InputData'.
-
-	* 'RepeatablePattern' can take one of two forms.
-	In the simplest case, it matches just a single item of the underlying polymorphic type, perhaps literally, though looser specifications also exist:
-	@.@ matches any input datum; @[x, y, z]@ matches any of @x@, @y@, or @z@; @[^x, y, z]@ matches anything but @x@, @y@, or @z@.
-	To support POSIX /ERE/s, 'RepeatablePattern' can also be a list 'Alternatives', each of which is recursively defined as an 'ExtendedRegEx', to form a tree-structure.
-
-	* Each 'Pattern', can optionally be /quantified/ by either a traditional /greedy/, or a /Perl/-style /non-greedy/, suffix, e.g.; @[*, +, ?, {n, m}, {n,}, {n}, *?, +?, ??, {n, m}?, {n,}?]@.
-
-	* For convenience, common specifications can be canned & assigned a single 'Char' mnemonic, for subsequent reference.
-	Since 'ExtendedRegEx' is polymorphic, the set of abbreviations appropriate in the context of the unspecified base-type,
-	must be implemented externally through the 'Meta.ShortcutExpander' interface.
-	This permits the use, when the type-parameter is 'Char', of /Perl-style shortcuts/ @[\\d\\D\\s\\S\\w\\W]@.
-
-	* The algorithm, is the classic /back-tracking/ one, rather than either a /DFA/ or /NFA/.
-	This permits construction of 'Result' via which one can discover the deep mapping of 'InputData' into 'ExtendedRegEx',
-	& provides the flexibility to add the features now expected by modern /regex/-engines.
-	Since the type-parameter is unknown, & may represent a large object, the exponential space-complexity of creating a /DFA/ may present additional problems.
-	The exponential time-complexity of the /back-tracking/ algorithm is partially tamed by targeting obvious inefficiencies with specific optimisations.
-
-	* Char-based regexen, traditionally overload the delimiters of a set of 'Alternatives' (parentheses), as a request for data-capture.
-	Here, in contrast, all 'RepeatablePattern's capture data, & repeated sub-expressions capture a list of data,
-	rather than arbitrarily recording just the last (<http://www.opengroup.org/onlinepubs/009695399/functions/regcomp.html>) item.
-
- [@REFERENCES@]
-
-	* <http://en.wikipedia.org/wiki/Regular_expression>
-
-	* <http://swtch.com/~rsc/regexp/regexp1.html>
-
-	* <http://docstore.mik.ua/orelly/perl/prog/ch02_04.htm#PERL2-CH-2-SECT-4.1.2>
-
-	* <http://www.macs.hw.ac.uk/~dsg/gph/papers/html/Strategies/strategies.html>
-
-	* <http://hackage.haskell.org/packages/archive/regex-posix/latest/doc/html/Text-Regex-Posix.html>
-
-	* <http://www.haskell.org/haskellwiki/Regular_expressions>
-
-	* <http://www2.research.att.com/~gsf/testregex/re-interpretation.html>
-
- [@CAVEATS@]
-
-	* Because of the definition of mutually recursive data-types, it is difficult to split this annoyingly large module, & preserve compatibility across compilers,
-	but it may be possible to break this cyclic dependency, by defining an interface to which one of the data-types defined here conforms.
-
-	* Doesn't implement /Back-references/, making the definition of the 'ExtendedRegEx' context-free.
-
-	* There's no integration with the type-classes defined in "Text.Regex.Base.RegexLike", which assumes 'Char'-based 'InputData';
-	though this could be added to a specialised instance.
-
-	* When 'Alternatives' are defined, 'Result' becomes a tree-like structure.
-	Unless the alternative is a singleton, the specific alternative selected in the solution is typically unknown, & therefore the /structure/ of the branch of this tree is also unknown.
-	This lack of clarity is compounded when the 'Alternatives' are 'Repeatable.Repeatable', since a different one may be selected on each successive repetition.
-	Consequently, the user can't navigate this portion of the structure in a statically defined manner, to acquire the captured data.
-	Despite this, & in contrast to other /regex/-engines, access to the whole data-structure is available, since it doesn't seem advantage to hide it.
-	The user can then either use 'extractDataFromMatch' for that element of 'Result', thus aggregating the data from sections of unknown structure, or 'show' it, as an aid to debugging.
-
- [@TODO@]
-
-	* Test parallel-operation, on a 3 or more processor machine.
-	If 'rnf' is less effective than 'rwhnf',
-	then the 'Control.DeepSeq.NFData' context can be removed,
-	reducing the requirements imposed on the type-parameter 'a'.
-
-	* Try 'Data.List.Stream' (stream-fusion), a faster drop-in replacement for 'Data.List'; possibly integrated in GHC-6.12.
-
-	* 'ExecutionOptions.bypassInputDataForLiberalConsumer' is too restrictive.
-	More generally, we can test whether the set of different 'a' in 'InputData', is a subset of those common to all remaining terms in the 'ExtendedRegEx'.
-	Using this rule, we can infer @"aaa ..." =~ MkExtendedRegEx [a,a+,a?,[ab]{2,3}]@, given compatible 'ConsumptionProfile.consumptionBounds'.
-
-	* Nested repetitions, where nothing has been added to the expression, result in repeated trials of the same expression,
-	e.g.; @"(x{i,}){j,}"@ results in the same expansion for @(i, j) in [(2, 3), (3, 2), (6, 1), (1, 6)]@.
-	The resulting 'MatchList' may be different, but if the first such trial fails, so will all the remainder.
-
-	* Should cope with empty sets of 'Alternatives' & zero repetitions, neither of which can ever match, but the wider pattern can, e.g. @(()|x{0}|y)@.
-
-	* By removing 'RepeatablePattern' from 'Match', it can be isolated in a new module.
-	This would result in a significant loss of discoverability.
-
-	* Expand repeated 'Anchor.Bow' with @fewest - 1@ null matches followed by recursive 'findMatch'-call with @repetitions = 1@.
--}
-
-module RegExDot.RegEx(
--- * Type-classes
-	ShortcutExpander(..),
--- * Types
--- ** Type-synonyms
---	BasicRegEx,
-	Concatenation,
-	ExternalMatch,
-	InputData,
-	MatchedData,
-	MatchList,
---	MetaDataList,
-	RepeatablePattern,
---	Transformation,
--- ** Data-types
-	Alternatives(..),
-	Match,
-	ExtendedRegEx(..),
-	Pattern(..),
-	Result,
--- * Constants
-	alternativeExtendedRegExSeparatorToken,
---	anyDatum,
-	captureGroupDelimiters,
-	tokens,
--- * Functions
---	accumulateDistinctInputData,
---	accumulateDistinctMetaDataFrom,
-	dock,
---	drift,
---	findMatch,
-	captureGroup,
---	mkNullMatchFromConcatenation,
---	mkNullMatchFromExtendedRegEx,
---	mkNullMatchFromRepeatablePattern,
---	safeReciprocal,
---	shiftMatchedData,
---	shiftMatch,
-	shiftMatchList,
-	showsMaybeAnchor,
-	simply,
-	transformExtendedRegEx,
--- ** Accessors (Deconstructors)
-	deconstructAlternatives,
---	getInputData,
--- ** Operators
-	(+~),
-	(=~),
-	(/~),
-	(.*),
-	(.*?),
---	(/+)
--- ** Predicates
---	hasBowAnchor,
---	hasSternAnchor,
-	isDefined,
-	isCaptureGroup,
-	isSingletonAlternatives,
---	isUnconsumableByAnyOf,
--- ** Query
---	getDistinctMetaDataFromAlternatives,
---	getDistinctMetaDataFromConcatenation,
---	getDistinctMetaDataFromExtendedRegEx,
---	getDistinctMetaDataFromPattern,
---	getDistinctMetaDataFromRepeatablePattern,
-	externalMatchLength,
-	extractDataFromMatch,
-	extractDataFromMatch',
-	extractDataFromMatchList
-) where
-
-import			Control.Arrow((&&&))
-import qualified	Control.Arrow
-import qualified	Control.DeepSeq
-import qualified	Control.Parallel.Strategies
-import qualified	Data.Char
-import qualified	Data.Foldable
-import qualified	Data.List
-import qualified	Data.Maybe
-import qualified	Data.Ord
-import qualified	RegExDot.Anchor			as Anchor
-import qualified	RegExDot.Consumer		as Consumer
-import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
-import qualified	RegExDot.ConsumptionProfile	as ConsumptionProfile
-import qualified	RegExDot.ExecutionOptions	as ExecutionOptions
-import qualified	RegExDot.Meta			as Meta
-import qualified	RegExDot.RegExOpts		as RegExOpts
-import qualified	RegExDot.Repeatable		as Repeatable
-import			RegExDot.Repeatable((^#->))
-import qualified	RegExDot.Tree			as Tree
-import qualified	ToolShed.Data.List
-import qualified	ToolShed.Data.List.Splits
-import qualified	ToolShed.SelfValidate
-
-infix 4 +~, =~, /~	-- Same as (==) & (/=).
-
--- | The type of a /regex/, in which there's no provision for either 'Alternatives' or 'Anchor.Anchor's.
-type BasicRegEx m	= [Repeatable.Repeatable (Meta.Meta m)]
-
-{- |
-	* Defines the method required to expand a mnemonic into an 'ExtendedRegEx'.
-
-	* CAVEAT: this interface must be declared locally, since it references 'ExtendedRegEx', & 'ExtendedRegEx' references it.
--}
-class ShortcutExpander m	where
-	expand	:: Char -> ExtendedRegEx m	-- ^ Expand a single-'Char' mnemonic into the corresponding 'ExtendedRegEx'.
-
-{- |
-	* Represents the /alternation/ feature of 'ExtendedRegEx's.
-
-	* One could amalgamate this with 'Pattern', since it seems to exist merely as a peg to hang /instance/-declarations from.
--}
-newtype Alternatives m	= MkAlternatives [ExtendedRegEx m]	deriving Eq
-
--- | Accessor, to expose the guts.
-deconstructAlternatives :: Alternatives m -> [ExtendedRegEx m]
-deconstructAlternatives (MkAlternatives extendedRegExList)	= extendedRegExList
-
--- | Similar to 'fmap', but operates on ['ExtendedRegEx'], rather than just @a@.
-transformAlternatives
-	:: ([ExtendedRegEx m] -> [ExtendedRegEx m])	-- ^ The transformation function to apply to the list of data behind the constructor.
-	-> Alternatives m
-	-> Alternatives m
-transformAlternatives f	= MkAlternatives . f . deconstructAlternatives
-
-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
-		[(extendedRegEx, s1)]	-> case dropWhile Data.Char.isSpace s1 of
-			('|' : s2)	-> Control.Arrow.first (transformAlternatives (extendedRegEx :)) `map` reads s2 {-singleton-}
-			_		-> [(MkAlternatives [extendedRegEx], s1)]
-		_			-> []	-- No parse.
-
-instance Show m => Show (Alternatives m)	where
-	showsPrec _	= foldl (.) (showString "") . Data.List.intersperse (showChar alternativeExtendedRegExSeparatorToken) . map shows . deconstructAlternatives	-- Replace the default list-format, with 'egrep'-syntax.
-
-instance Consumer.Consumer (Alternatives m)	where
-	consumptionProfile	= Consumer.aggregateConsumptionProfilesFromAlternatives . deconstructAlternatives
-	starHeight		= Consumer.starHeight . deconstructAlternatives	-- Must evaluate all Alternatives to determine best.
-
-instance ToolShed.SelfValidate.SelfValidator (Alternatives m)	where
-	getErrors	= ToolShed.SelfValidate.getErrors . deconstructAlternatives
-
-instance Control.DeepSeq.NFData m => Control.DeepSeq.NFData (Alternatives m)	where
-	rnf	= Control.DeepSeq.rnf . deconstructAlternatives
-
--- | 'Alternatives' can be employed as a simple /capture-group/ as well as a switch, under which circumstances there's no choice amongst multiple 'Alternatives'.
-isSingletonAlternatives :: Alternatives m -> Bool
-isSingletonAlternatives	= (== 1) . length . deconstructAlternatives
-
--- | A set of 'Meta.Meta' which can be consumed.
-type MetaDataList m	= [Meta.Meta m]
-
-{- |
-	* '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,
-	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.
-	-> MetaDataList m	-- ^ The list of meta-data against any of which a match can occur.
-	-> Bool
-isUnconsumableByAnyOf i	= not . any (Meta.isMatch i)
-
--- | The set of distinct 'Meta.Meta', in the specified 'Alternatives'.
-getDistinctMetaDataFromAlternatives :: Eq m => Alternatives m -> MetaDataList m
-getDistinctMetaDataFromAlternatives	= foldr (Data.List.union . getDistinctMetaDataFromExtendedRegEx) [] . deconstructAlternatives
-
--- | Defines either a simple 'Meta.Meta', which can match exactly one datum, or a set of 'Alternatives', each of which is recursively defined above, as an 'ExtendedRegEx'.
-data Pattern m	=
-	Require (Meta.Meta m)		-- ^ Describes a requirement for a simple scalar datum of the polymorphic type.
-	| CaptureGroup (Alternatives m)	-- ^ A sub-expression containing a selection of recursively defined alternatives, thus forming a tree-structure.
-	deriving Eq
-
-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
-		[(alternatives, s1)]	-> case dropWhile Data.Char.isSpace s1 of
-			(')' : s2)	-> [(CaptureGroup alternatives, s2)]
-			_		-> []	-- No parse.
-		_			-> []	-- No parse.
-	readsPrec _ s		= case reads s of
-		[pair]	-> [Control.Arrow.first Require pair]
-		_	-> []	-- No parse.
-
-instance Show m => Show (Pattern m)	where
-	showsPrec _ (Require meta)		= shows meta
-	showsPrec _ (CaptureGroup alternatives)	= showChar (fst captureGroupDelimiters) . shows alternatives . showChar (snd captureGroupDelimiters)
-
-instance Consumer.Consumer (Pattern m)	where
-	consumptionProfile (Require meta)		= Consumer.consumptionProfile meta
-	consumptionProfile (CaptureGroup alternatives)	= Consumer.consumptionProfile alternatives
-
-	starHeight (Require meta)		= Consumer.starHeight meta
-	starHeight (CaptureGroup alternatives)	= Consumer.starHeight alternatives
-
-instance ToolShed.SelfValidate.SelfValidator (Pattern m)	where
-	getErrors (Require meta)		= ToolShed.SelfValidate.getErrors meta
-	getErrors (CaptureGroup alternatives)	= ToolShed.SelfValidate.getErrors alternatives
-
-instance Control.DeepSeq.NFData m => Control.DeepSeq.NFData (Pattern m)	where
-	rnf (Require meta)		= Control.DeepSeq.rnf meta
-	rnf (CaptureGroup alternatives)	= Control.DeepSeq.rnf alternatives
-
--- | Convenience-function to build a 'CaptureGroup' from a list of alternative 'ExtendedRegEx's.
-captureGroup :: [ExtendedRegEx m] -> Pattern m
-captureGroup	= CaptureGroup . MkAlternatives
-
--- | True if the 'Pattern' was constructed via 'CaptureGroup'.
-isCaptureGroup :: Pattern m -> Bool
-isCaptureGroup (CaptureGroup _)	= True
-isCaptureGroup _		= False
-
--- | The set of distinct 'Meta.Meta', in the specified 'Pattern'.
-getDistinctMetaDataFromPattern :: Eq m => Pattern m -> MetaDataList m
-getDistinctMetaDataFromPattern pattern	= case pattern of
-	Require meta			-> [meta]
-	CaptureGroup alternatives	-> getDistinctMetaDataFromAlternatives alternatives
-
--- | Constant pattern, representing a lax 'Require'ment.
-anyDatum :: Pattern a
-anyDatum	= Require Meta.Any
-
--- | Make 'Pattern's, 'Repeatable.Repeatable'.
-type RepeatablePattern m	= Repeatable.Repeatable (Pattern m)
-
--- | Construct a null 'Match' by assuming that the specified 'RepeatablePattern' consumes zero 'InputData'; of which the caller should ensure it's capable.
-mkNullMatchFromRepeatablePattern
-	:: ConsumptionBounds.DataLength	-- ^ The offset into the list of input data at which the zero-length match occurred.
-	-> RepeatablePattern m		-- ^ The pattern that the input data matched.
-	-> Match m			-- ^ The resulting match-structure.
-mkNullMatchFromRepeatablePattern offset r	= case Repeatable.base r of
-	Require _	-> Tree.Leaf (r, offset, [])
-	CaptureGroup _	-> Tree.Node $ Repeatable.getFewest r `replicate` []
-
--- | The set of distinct 'Meta.Meta', in the specified 'RepeatablePattern'.
-getDistinctMetaDataFromRepeatablePattern :: Eq m => RepeatablePattern m -> MetaDataList m
-getDistinctMetaDataFromRepeatablePattern	= getDistinctMetaDataFromPattern . Repeatable.base
-
-{- |
-	* Represents a black hole, which will greedily consume all data.
-
-	* CAVEAT: nullary, i.e. a constant.
--}
-(.*) :: RepeatablePattern m
-(.*)	= Repeatable.zeroOrMore anyDatum
-
--- | A /non-greedy/ version of '.*'.
-(.*?) :: RepeatablePattern m
-(.*?)	= Repeatable.zeroOrMore' anyDatum
-
--- | Convenience-function, to build a 'RepeatablePattern' from an unrepeated instance of the specified 'Meta.Meta'-datum.
-simply :: Meta.Meta m -> RepeatablePattern m
-simply	= Repeatable.one . Require
-
--- | Represents the /concatenation/ aspect of 'ExtendedRegEx's.
-type Concatenation m	= [RepeatablePattern m]
-
--- | Construct a null 'Match' by assuming that the specified 'Concatenation' consumes zero 'InputData'.
-mkNullMatchFromConcatenation
-	:: ConsumptionBounds.DataLength	-- ^ The offset into the list of input data at which the zero-length match occurred.
-	-> Concatenation m		-- ^ The list of repeatable patterns that the input data matched.
-	-> MatchList m			-- ^ The resulting match-structure.
-mkNullMatchFromConcatenation offset	= map $ mkNullMatchFromRepeatablePattern offset
-
--- | The set of distinct 'Meta.Meta', in the specified 'Concatenation'.
-getDistinctMetaDataFromConcatenation :: Eq m => Concatenation m -> MetaDataList m
-getDistinctMetaDataFromConcatenation	= foldr (Data.List.union . getDistinctMetaDataFromRepeatablePattern) []
-
--- | The accumulating set of 'MetaDataList', resulting from each successive 'RepeatablePattern' in the specified 'Concatenation'.
-accumulateDistinctMetaDataFrom :: Eq m => MetaDataList m -> Concatenation m -> [MetaDataList m]
-accumulateDistinctMetaDataFrom	= scanr (Data.List.union . getDistinctMetaDataFromRepeatablePattern)
-
--- | Constructs an 'ExtendedRegEx', by surrounding a 'Concatenation' with optional 'Anchor.Anchor's.
-data ExtendedRegEx m	= MkExtendedRegEx {
-	bowAnchor	:: Maybe Anchor.Anchor,	-- ^ An option to anchor the /regex/ to the start of the 'InputData'.
-	concatenation	:: Concatenation m,	-- ^ The sequence of 'RepeatablePattern's defining the 'Require'ments that the 'InputData' must meet.
-	sternAnchor	:: Maybe Anchor.Anchor	-- ^ An option to anchor the /regex/ to the end of the 'InputData'.
-} deriving Eq
-
--- | The type of a function which transforms an 'ExtendedRegEx'.
-type Transformation m	= ExtendedRegEx m -> ExtendedRegEx m
-
--- | Similar to 'fmap', but operates on 'Concatenation', rather than just @a@.
-transformExtendedRegEx
-	:: (Concatenation m -> Concatenation m)	-- ^ The function used to transform the data behind the constructor.
-	-> Transformation m
-transformExtendedRegEx f extendedRegEx	= extendedRegEx { concatenation	= f $ concatenation extendedRegEx }
-
-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.
-	readsPrec _ ('\\' : c : s)	= [(expand c, s)]
-	readsPrec _ s			= case singleton of
-		[(extendedRegEx, _)]
-			| ToolShed.SelfValidate.isValid extendedRegEx	-> singleton
-			| otherwise					-> error $ ToolShed.SelfValidate.getFirstError extendedRegEx	-- Parsed OK, but invalid.
-		_							-> []								-- No parse.
-		where
---			singleton :: (Eq m, Meta.ShortcutExpander m, Read m, ShortcutExpander m) => [(ExtendedRegEx m, String)]
-			singleton = [
-				(
-					MkExtendedRegEx {
-						bowAnchor	= maybeBowAnchor,
-						concatenation	= concatenation',
-						sternAnchor	= maybeSternAnchor
-					},
-					remainder
-				) |
-					(maybeBowAnchor, s1)		<- readsMaybeAnchor s,
-					(concatenation', s2)		<- reads s1,
-					(maybeSternAnchor, remainder)	<- readsMaybeAnchor s2
-			 ] {-list-comprehension-} where
-				readsMaybeAnchor :: ReadS (Maybe Anchor.Anchor)
-				readsMaybeAnchor s'	= return {-to List-monad-} $ case reads s' of
-					[pair]	-> Control.Arrow.first Just pair
-					_	-> (Nothing, s')
-
--- | Shows either the specified 'Anchor.Anchor', or a null string where 'Nothing' is specified.
-showsMaybeAnchor :: Maybe Anchor.Anchor -> String -> String
-showsMaybeAnchor maybeAnchor
-	| Data.Maybe.isJust maybeAnchor	= shows $ Data.Maybe.fromJust maybeAnchor
-	| otherwise			= id
-
-instance Show m => Show (ExtendedRegEx m)	where
-	showsPrec _ MkExtendedRegEx {
-		bowAnchor	= maybeBowAnchor,	-- CAVEAT: this could be 'Nothing' or perversely an 'Anchor.Stern'.
-		concatenation	= concatenation',
-		sternAnchor	= maybeSternAnchor	-- CAVEAT: this could be 'Nothing' or perversely an 'Anchor.Bow'.
-	} = showsMaybeAnchor maybeBowAnchor . shows concatenation' . showsMaybeAnchor maybeSternAnchor
-
-instance Consumer.Consumer (ExtendedRegEx m)	where
-	consumptionProfile	= Consumer.aggregateConsumptionProfilesFromConcatenation . concatenation
-	starHeight		= Consumer.starHeight . concatenation
-
-instance ToolShed.SelfValidate.SelfValidator (ExtendedRegEx m)	where
-	getErrors	= ToolShed.SelfValidate.getErrors . concatenation
-
-instance Control.DeepSeq.NFData m => Control.DeepSeq.NFData (ExtendedRegEx m)	where
-	rnf MkExtendedRegEx {
-		bowAnchor	= maybeBowAnchor,
-		concatenation	= concatenation',
-		sternAnchor	= maybeSternAnchor
-	} = Control.DeepSeq.rnf (maybeBowAnchor, concatenation', maybeSternAnchor)
-
--- | Drop 'Anchor.Anchor's at both bow & stern of the specified 'ExtendedRegEx'.
-dock :: Transformation m
-dock e	= e {
-	bowAnchor	= Just Anchor.Bow,
-	sternAnchor	= Just Anchor.Stern
-}
-
--- | Amend the 'Concatenation' in the specified 'ExtendedRegEx', by prepending '.*' where there's a missing top-level 'Anchor.Bow' & appending '.*?' where there's a missing top-level 'Anchor.Stern'.
-drift :: Transformation m
-drift extendedRegEx	= transformExtendedRegEx (
-	(
-		if hasBowAnchor extendedRegEx then id else {-no anchor-} ((.*?) :)
-	) . (
-		if hasSternAnchor extendedRegEx then id else {-no anchor-} (++ [(.*)])
-	)
- ) extendedRegEx
-
--- | True if the specified 'ExtendedRegEx' has an initial 'Anchor.Bow'. CAVEAT: though typically the alternative is no 'Anchor.Anchor', there may perversely be an initial 'Anchor.Stern', but neither qualify.
-hasBowAnchor :: ExtendedRegEx m -> Bool
-hasBowAnchor	= (== Just Anchor.Bow) . bowAnchor
-
--- | True if the specified 'ExtendedRegEx' has a terminal 'Anchor.Stern'. CAVEAT: though typically the alternative is no 'Anchor.Anchor', there may perversely be a terminal 'Anchor.Bow', but neither qualify.
-hasSternAnchor :: ExtendedRegEx m -> Bool
-hasSternAnchor	= (== Just Anchor.Stern) . sternAnchor
-
--- | 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
-
--- | Construct a null 'Match' by assuming that the specified 'ExtendedRegEx' consumes zero 'InputData'.
-mkNullMatchFromExtendedRegEx :: ConsumptionBounds.DataLength -> ExtendedRegEx m -> MatchList m
-mkNullMatchFromExtendedRegEx offset	= mkNullMatchFromConcatenation offset . concatenation
-
--- | The set of distinct (i.e. unique) 'Meta.Meta', in the specified 'ExtendedRegEx'.
-getDistinctMetaDataFromExtendedRegEx :: Eq m => ExtendedRegEx m -> MetaDataList m
-getDistinctMetaDataFromExtendedRegEx	= getDistinctMetaDataFromConcatenation . concatenation
-
-{- |
-	* The input-data is just a list.
-
-	* Whilst typically this list is also a 'String', & could therefore be more efficiently implemented using "Data.ByteString",
-	we can't assume that the polymorphic base-type is always 'Char'.
--}
-type InputData m = [m]
-
--- | The accumulating sets of distinct input data.
-accumulateDistinctInputData :: Eq m => InputData m -> [InputData m]
-accumulateDistinctInputData	= scanr (Data.List.union . return) []
-
--- | Tag the 'InputData' with the 'RepeatablePattern' it matched (which unfortunately confines the definition to this (bloated) module), & the offset from the start of the data;
-type MatchedData m	= (RepeatablePattern m, ConsumptionBounds.DataLength, InputData m)
-
--- | Shifts the offset of the specified 'MatchedData'.
-shiftMatchedData
-	:: ConsumptionBounds.DataLength	-- ^ The offset by which to shift the position into the input-data at which a match occurred.
-	-> MatchedData m		-- ^ The match-structure whose offset is to be shifted.
-	-> MatchedData m
-shiftMatchedData i (r, offset, d)	= (r, offset + i, d)
-
--- | Accessor.
-getInputData :: MatchedData m -> InputData m
-getInputData (_, _, inputData)	= inputData
-
--- | Describes the manner in which a 'RepeatablePattern' successfully consumed 'InputData'.
-type Match m	= Tree.Tree (MatchedData m)
-
--- | Shifts the offsets of all the 'MatchedData' contained in the specified 'Match'.
-shiftMatch
-	:: ConsumptionBounds.DataLength	-- ^ The offset by which to shift the position into the input-data at which a match occurred.
-	-> Match m			-- ^ The match-structure whose offset is to be shifted.
-	-> Match m
-shiftMatch i	= (shiftMatchedData i `fmap`)
-
--- | Extract & concatenate, the 'InputData' from a 'Match'.
-extractDataFromMatch :: Match m -> InputData m
-extractDataFromMatch	= Data.Foldable.foldMap getInputData	-- Uses the List-monoid's associative binary operator (++), to concatenate the values returned by the specified function.
-
--- | Extract & concatenate, the 'InputData' from a 'Match'; null if it didn't match any.
-extractDataFromMatch' :: Maybe (Match m) -> InputData m
-extractDataFromMatch' (Just match)	= extractDataFromMatch match
-extractDataFromMatch' _			= []
-
--- | Describes the manner in which a 'Concatenation' successfully consumed 'InputData'.
-type MatchList m	= [Match m]
-
--- | Shifts the offsets of all the 'MatchedData' contained in the specified 'MatchList'.
-shiftMatchList
-	:: ConsumptionBounds.DataLength	-- ^ The offset by which to shift the position into the input-data at which a each listed match occurred.
-	-> MatchList m			-- ^ The list of match-structures, each of whose offsets are to be shifted.
-	-> MatchList m
-shiftMatchList i	= map (shiftMatch i)
-
--- | Extract & concatenate, the 'InputData', from the 'MatchList'.
-extractDataFromMatchList :: MatchList m -> InputData m
-extractDataFromMatchList	= concatMap extractDataFromMatch	-- CAVEAT: too fine-grain for effective data-parallelism.
-
--- | At the top-level of an 'ExtendedRegEx', the lack of an 'Anchor.Anchor' allows the 'ExtendedRegEx' to drift away from the corresponding end of the input-data; this data-gap is captured here.
-type ExternalMatch m	= Maybe (Match m)
-
--- | Captures the list of input-data consumed by the 'Concatenation', bracketed by any data-prefix or data-suffix.
-type Result m	= (ExternalMatch m, Maybe (MatchList m), ExternalMatch m)
-
--- | Returns the length of data consumed by the specified 'ExternalMatch'.
-externalMatchLength :: ExternalMatch m -> ConsumptionBounds.DataLength
-externalMatchLength	= length . extractDataFromMatch'
-
-{- |
-	* Similar to '+~', but exposes 'ExecutionOptions.ExecutionOptions', permitting greater control; & enough rope to hang yourself.
-
-	* The parameter-order facilitates partial application, to acquire a matcher-function for a specific 'ExtendedRegEx', which can be applied repeatedly to different 'InputData'.
-
-	* Performs some one-off @O(n)@ time-complexity preparation, then delegates the grunt-work to a private recursive function.
-
-	* 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, Control.DeepSeq.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)
-findMatch regExOpts@RegExOpts.MkRegExOpts {
-	RegExOpts.executionOptions	= executionOptions,
-	RegExOpts.regEx			= extendedRegEx
-} originalInputData
-	| let
-		extractLowStarHeightTail :: ExtendedRegEx m -> Concatenation m
-		extractLowStarHeightTail	= {-#SCC "extractLowStarHeightTail" #-} fromConcatenation . reverse . concatenation	where
-			fromConcatenation :: Concatenation m -> Concatenation m
-			fromConcatenation []					= []
-			fromConcatenation (repeatablePattern : concatenation')
-				| Consumer.starHeight repeatablePattern == 0	= repeatablePattern : fromConcatenation {-recurse-} concatenation'
-				| Repeatable.getFewest repeatablePattern > 0	= case Repeatable.base repeatablePattern of
-					CaptureGroup alternatives
-						| isSingletonAlternatives alternatives	-> extractLowStarHeightTail {-recurse-} . head $ deconstructAlternatives alternatives
-						| otherwise				-> {-non-singleton-} []
-					_				-> []	-- Zero 'Consumer.StarHeight' would have been detected by 'fromConcatenation'.
-				| otherwise					= []
-
---		lowStarHeightTail :: Concatenation a
-		lowStarHeightTail	= extractLowStarHeightTail extendedRegEx
-	in and [
-		ExecutionOptions.checkExistenceOfInelasticTail executionOptions,
-		not $ null lowStarHeightTail,	-- Prevent infinite recursion.
-		reverse originalInputData /~ RegExOpts.mkRegEx MkExtendedRegEx {
-			bowAnchor	= Just Anchor.Bow,
-			concatenation	= lowStarHeightTail,
-			sternAnchor	= Nothing
-		} -- Check for mismatch with the corresponding tail of 'InputData'.
-	]		= Nothing
-	| otherwise	= findMatchSlave originalConcatenation (
-		Consumer.accumulateConsumptionProfiles originalConcatenation
-	) (
-		accumulateDistinctMetaDataFrom [] originalConcatenation
-	) originalInputData originalInputDataLength (
-		accumulateDistinctInputData originalInputData
-	)
-	where
---		originalConcatenation :: Concatenation a
-		originalConcatenation	= concatenation extendedRegEx
-
-		originalInputDataLength :: ConsumptionBounds.DataLength
-		originalInputDataLength	= length originalInputData
-{-
- This beast takes a lot of parameters.
- 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, Control.DeepSeq.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 [] _ _ [] _ _	= 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	= 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.
-				not $ ExecutionOptions.requireMatchList executionOptions,				-- Otherwise the precise mapping of the 'inputData' to 'RepeatablePattern's must be determined.
-				not $ ConsumptionProfile.hasSpecificRequirement accumulatedConsumptionProfileHead	-- Otherwise a match for the specific 'Meta'-data must be found.
-			] = Just undefined {-shouldn't be evaluated according to 'ExecutionOptions.requireMatchList'-}
-			| and [
-				ExecutionOptions.checkForUnconsumableData executionOptions,
-				not $ ConsumptionProfile.canConsumeAnything accumulatedConsumptionProfileHead,	-- Otherwise the subsequent test will always fail.
-				(`isUnconsumableByAnyOf` distinctMetaDataHead) `any` distinctInputDataHead	-- Occasionally failure is both inevitable & obvious.
-			] = Nothing
-			| otherwise	= {-#SCC "findMatchSlave" #-} let
-				tailConsumptionProfile :: ConsumptionProfile.ConsumptionProfile
-				tailConsumptionProfile@(
-					ConsumptionProfile.MkConsumptionProfile {
-						ConsumptionProfile.consumptionBounds	= (minConsumptionConcatenationTail, maybeMaxConsumptionConcatenationTail)
-					}
-				 ) = 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 Nothing
-				else {-inputData is sufficient for concatenationTail-} let
-					Repeatable.MkRepeatable {
-						Repeatable.base			= base,
-						Repeatable.repetitionBounds	= (fewest, most),
-						Repeatable.isGreedy		= isGreedy
-					} = 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 (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'.
- The resulting 'BasicRegEx', with /Kleene Star/s weeded-out & 'Alternatives' pruned, can be matched in O(n)-time, to verify minimal requirements.
--}
-						extractMinimumRequirementFromConcatenation :: Concatenation m -> BasicRegEx m
-						extractMinimumRequirementFromConcatenation	= concatMap (
-							\repeatablePattern -> case Repeatable.base repeatablePattern of
-								Require datum	-> return {-to List-monad-} repeatablePattern { Repeatable.base = datum }
-								CaptureGroup a
-									| isSingletonAlternatives a	-> concat . replicate (Repeatable.getFewest repeatablePattern) . extractMinimumRequirementFromConcatenation {-recurse-} . concatenation . head $ deconstructAlternatives a
-									| otherwise			-> []
-						 ) . filter ((> 0) . Repeatable.getFewest)
-
-						maximumDataAfterPegs :: Eq m => BasicRegEx m -> InputData m -> Maybe (InputData m)
-						maximumDataAfterPegs pegList@(
-							Repeatable.MkRepeatable {
-								Repeatable.base			= metaPeg,
-								Repeatable.repetitionBounds	= (fewestPeg, _)
-							} : pegListTail
-						 ) inputData'
-							| null remainingInputData && length candidateMatchedInputData < fewestPeg		= Nothing							-- Insufficient data to ever match.
-							| fewestPeg == 1 || (`Meta.isMatch` metaPeg) `all` tail candidateMatchedInputData	= pegListTail `maximumDataAfterPegs` remainingInputData		-- Success => recurse.
-							| otherwise										= pegList `maximumDataAfterPegs` tail candidateInputData	-- Failed candidate => recurse.
-							where
---								candidateInputData, candidateMatchedInputData, remainingInputData :: InputData a
-								candidateInputData				= dropWhile (not . (`Meta.isMatch` metaPeg)) inputData'
-								(candidateMatchedInputData, remainingInputData)	= fewestPeg `splitAt` candidateInputData
-						maximumDataAfterPegs [] inputData'	= Just inputData'	-- All the pegs have been matched.
-{-
- Each 'repeatablePatternHead' can either be a 'Require' or a 'CaptureGroup'.
- The former case needs further reduction & we can proceed to construct a 'Tree.Leaf' from any matching 'inputData'.
- We attempt to reduce the latter case to an instance of the former, by expanding all combinations of repetitions of various 'Alternatives', constructing a new 'ExtendedRegEx' from each, & recursing.
--}
-				in case base of
-					Require meta
-						| null maybeMatchList	-> Nothing
-						| otherwise		-> head {-most suitable-} maybeMatchList
-						where
-{-
- Attempt to narrow the repetition-range, from the potentially unbounded specification, to that which is possible according to,
- the 'inputDataLength', & the specified consumption-bounds of the remainder of the /regex/.
- 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 . map (
-								\(consumedInputData, unconsumedInputData)	-> let
-									consumedInputDataLength :: ConsumptionBounds.DataLength
-									consumedInputDataLength	= length consumedInputData
-								in (
-									Tree.Leaf (repeatablePatternHead, inputDataOffset, consumedInputData) :
-								) `fmap` {-apply to Maybe Functor-} findMatchSlave concatenationTail accumulatedConsumptionProfilesTail distinctMetaDataTail unconsumedInputData (
-									inputDataLength - consumedInputDataLength
-								) (
-									consumedInputDataLength `drop` distinctInputData
-								) -- Recurse, to check whether the 'unconsumedInputData' tail also matches.
-							 ) $ let
-								fewestData, mostData, mostData' :: Repeatable.Repetitions
-								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" #-} 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.
-										_		-> maxDataAvailable
-
---									measureUnmatchableTail :: InputData m -> ConsumptionBounds.DataLength -> ConsumptionBounds.DataLength
-									measureUnmatchableTail _ 0	= 0						-- Have matched all the data.
-									measureUnmatchableTail (a : as) unmatched
-										| a `Meta.isMatch` meta	= measureUnmatchableTail as $ pred unmatched	-- Recurse.
-										| otherwise		= unmatched					-- Return the unmatchable tail-length.
-									measureUnmatchableTail [] _	= error "RegExDot.RegEx.findMatch.findMatchSlave.maybeMatchList.mostData.measureUnmatchableTail:\tdata unexpectedly exhausted."
-{-
- 'most' has been extracted from 'repeatablePatternHead',
- & reduced according to the length of 'inputData' which actually matches, to form 'mostData',
- but if it still exceeds 'fewestData', the resulting repetition-range may trigger backtracking.
- So, attempt to further reduce this ill-defined repetition-range, according to the competing requirements of 'concatenationTail'.
--}
-								mostData'
-									| and [
-										ExecutionOptions.moderateGreed executionOptions,
-										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'	-> 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.
-							 ) `take` (
-								if isGreedy
-									then ToolShed.Data.List.Splits.splitsLeftFrom mostData'
-									else ToolShed.Data.List.Splits.splitsRightFrom fewestData
-							 ) inputData
-
-					CaptureGroup alternatives
-						| and [
-							not isGreedy,
-							fewest <= 0,	-- Zero repetitions permissible.
-							Data.Maybe.isJust tailMatch
-						] -> zeroRepetitions	-- Zero repetitions is the optimal solution, rendering the choice of Alternative irrelevant.
-						| and [
-							ExecutionOptions.catchIncompatibleAnchors executionOptions,
-							fewest > 1,			-- Multiple repetitions.
-							minConsumptionAlternatives > 0,	-- InputData required.
-							($ extendedRegExAlternatives) `any` [(hasBowAnchor `all`), (hasSternAnchor `all`)]
-						]							-> Nothing	-- 'extendedRegExFromAlternative' requires 'InputData', therefore 'Anchor.Bow' can only pass on the 1st repetition & 'Anchor.Stern' can only pass on the last.
-						| otherwise						-> let
-{-
- We're about to try all repetitions of one Alternative before progressing to the next.
- One could alternatively transpose this search-pattern, & investigate all 'Alternatives' permissible at n repetitions, before trying (n + 1); I've not pursued this option.
- 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 . concat . Control.Parallel.Strategies.parMap Control.Parallel.Strategies.rseq {-Particularly effective when 'not ExecutionOptions.requireMatchList' -} (
---								:: ExtendedRegEx m -> [Maybe (Match m, MatchList m)]
-								\extendedRegExFromAlternative@MkExtendedRegEx {
-									concatenation	= concatenationFromAlternative
-								} -> let
-									components :: Int
-									components	= length concatenationFromAlternative
-
-									consumptionProfileConcatenationFromAlternative :: [ConsumptionProfile.ConsumptionProfile]
-									consumptionProfileConcatenationFromAlternative	= map Consumer.consumptionProfile concatenationFromAlternative
-
-									minConsumptionConcatenationFromAlternative	:: ConsumptionBounds.DataLength
-									maybeMaxConsumptionConcatenationFromAlternative	:: Maybe ConsumptionBounds.DataLength
-									(minConsumptionConcatenationFromAlternative, maybeMaxConsumptionConcatenationFromAlternative)	= ConsumptionProfile.consumptionBounds $ ConsumptionProfile.aggregateFromConcatenation consumptionProfileConcatenationFromAlternative
-								in (
-									if ExecutionOptions.abortTrialRepetitionsOnZeroConsumption executionOptions && Data.Maybe.isNothing most {-constrained only by 'inputDataLength'-}
-										then {-#SCC "abortTrialRepetitionsOnZeroConsumption" #-} ToolShed.Data.List.takeUntil $ \maybeMatchPair -> case maybeMatchPair of
-											Just (match, _)	-> ($ Tree.pop match) `all` [
-												(>= fewest) . length,			-- Must achieve 'Repeatable.getFewest', regardless of data-consumption.
-												null . extractDataFromMatchList . last	-- If the n-th repetition consumed nothing, so will the (n + 1)-th.
-											 ]
-											_		-> False			-- Failure with n repetitions, doesn't preclude success with n + 1.
-										else {-optimisation not required-} id
-								) . (
---									:: Maybe (Match m, MatchList m) -> Maybe (Match m, MatchList m)
-									\maybeMatchPairList	-> if ExecutionOptions.abortTrialRepetitionsOnInherentFailure executionOptions
-{-
- We're iterating through the identified range of possible repetitions, of one possible 'concatenationFromAlternative'.
- If failure can be proven, for an arbitrary number of repetitions, then we can bypass the futile remainder.
- If the first trial succeeded, then clearly there's no such inherent problem with 'concatenationFromAlternative', & it's necessary to evaluate all subsequent trial-repetitions.
- Otherwise, assuming there're subsequent trials to be bypassed, attempt to prove that failure is inevitable, by launching a pilot-study,
- using a single repetition of 'concatenationFromAlternative' followed by a replacement infallible 'concatenationTail'.
--}
-										then {-#SCC "abortTrialRepetitionsOnInherentFailure" #-} case maybeMatchPairList of
-											(Nothing {-failed attempt-} : _ {-subsequent attempt worth bypassing-} : _)	-> if (
-												minConsumptionConcatenationFromAlternative == 0	-- Can delegate consumption of unconsumable data to the infallible tail => unprovable culpability.
-											 ) || inputData =~ RegExOpts.mkRegEx MkExtendedRegEx {
-												bowAnchor	= Just Anchor.Bow,
-												concatenation	= concatenationFromAlternative ++ [anyDatum ^#-> minConsumptionConcatenationTail],	-- Infallible tail.
-												sternAnchor	= Just Anchor.Stern
-											 }
-												then maybeMatchPairList
-												else []	-- Abandon further repetitions of 'Alternatives'.
-											_ {-Alternative is OK, or there's no subsequent attempt to bypass-}		-> maybeMatchPairList
-										else {-optimisation not required-} maybeMatchPairList
-								) . map (
---									:: Repeatable.Repetitions -> Maybe (Match m, MatchList m)
-									\repetitions	-> if hasSternAnchor extendedRegExFromAlternative
-										then if (repetitions == 1 || minConsumptionConcatenationFromAlternative == 0) && minConsumptionConcatenationTail == 0
-											then (
-												shiftMatch inputDataOffset . Tree.Node . (
-													: replicate (
-														pred repetitions	-- Typically degenerates to zero, since anchored sub-expressions aren't normally repeatable.
-													) (
-														mkNullMatchFromExtendedRegEx 0 extendedRegExFromAlternative	-- Other Alternatives may be available & suitable.
-													) -- Repeated null match may, lacking other suitable Alternatives, correspond to this stern-anchored ExtendedRegEx, so data must be consumed before them.
-												) &&& const (mkNullMatchFromConcatenation inputDataOffset concatenationTail)
-											) `fmap` findMatch regExOpts { RegExOpts.regEx = extendedRegExFromAlternative } inputData	-- Recurse, either consuming all inputData or failing.
-											else Nothing
-										else {-no Anchor.Stern-} let
-{-
- Expand the 'Repeatable CaptureGroup', so that after recursion it is ultimately reduced in complexity, to just a 'Concatenation' of 'Repeatable Require', & can be handled above as a POSIX BRE.
-
- There're two special cases; one repetition of n 'Alternatives' & n repetitions of one Alternative.
- If there's only one repetition, we can reduce the implementation-logic substantially, to the point where the implementation's independent of whether there's a choice of 'Alternatives'.
- If there only one Alternative, then the entire repetition-sequence can be immediately expanded, vastly reducing the required number of recursions,
- otherwise we can only expand the first repetition, leaving the option of matching a different Alternative on subsequent repetitions.
-
- In all cases, we must subsequently re-compose any 'MatchList' resulting of the recursive call, into one corresponding to the structure of original ExtendedRegEx.
- The expansion-process & corresponding subsequent collation, are associated in a tuple, in which the consumption-profile of the expansion is also contained.
--}
---											collater					:: MatchList m -> (Match m, MatchList m)
-											consumptionProfileExpandedConcatenationPrefix	:: [ConsumptionProfile.ConsumptionProfile]
---											expandedConcatenationPrefix			:: Concatenation a
-											(collater, consumptionProfileExpandedConcatenationPrefix, expandedConcatenationPrefix)
-												| repetitions == 1	= (
-													Control.Arrow.first (
-														Tree.Node . return {-to List-monad-}
-													) . splitAt components,	-- Bisect the 'MatchList', into the part resulting from the Alternative, & that for 'concatenationTail'.
-													consumptionProfileConcatenationFromAlternative,
-													concatenationFromAlternative
-												) -- Both tuples below, can degenerate to this simple case; it isn't a fundamentally different algorithm.
-												| and [
-													ExecutionOptions.unrollRepeatedSingletonAlternative executionOptions,
-													isSingletonAlternative,
-													not $ hasBowAnchor extendedRegExFromAlternative
-												] = (
-													Control.Arrow.first (
-														Tree.Node . ToolShed.Data.List.chunk components
-													) . splitAt (
-														components * repetitions
-													), -- Bisect the 'MatchList', into the part resulting from (Alternative){n}, & that for 'concatenationTail'.
-													concat $ replicate repetitions consumptionProfileConcatenationFromAlternative,
-													concat $ replicate repetitions concatenationFromAlternative	-- Expand all repetitions of the single alternative.
-												)
-												| otherwise {-choice of Alternatives or has Anchor.Bow-}	=  let
-													remainingRepetitions :: Repeatable.Repetitions
-													remainingRepetitions	= pred repetitions	-- Expand just the first repetition of the set of 'Alternatives'.
-
---													singletonRepeatable :: RepeatablePattern a
-													singletonRepeatable	= Repeatable.toSingleton repeatablePatternHead
-												in (
-													Control.Arrow.first (
-														Tree.Node . uncurry (:) . Control.Arrow.second (
-															concatMap Tree.pop		-- Amalgamate the repeated singleton 'MatchList's.
-														) . splitAt components			-- Bisect first 'MatchList', into the part resulting from 'concatenationFromAlternative', & that for 'replicate remainingRepetitions'.
-													) . splitAt (
-														components + remainingRepetitions	-- Bisect the 'MatchList', into the part resulting from (Alternatives){n}, & that for 'concatenationTail'.
-													),
-													consumptionProfileConcatenationFromAlternative ++ replicate remainingRepetitions (Consumer.consumptionProfile singletonRepeatable),
-													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 `fmap` {-apply to Maybe Functor-} findMatchSlave (
-										expandedConcatenationPrefix ++ concatenationTail
-									) (
-										ConsumptionProfile.accumulateFrom tailConsumptionProfile {-initial value-} consumptionProfileExpandedConcatenationPrefix ++ tail accumulatedConsumptionProfilesTail
-									) (
-										accumulateDistinctMetaDataFrom (head distinctMetaDataTail) {-initial value-} expandedConcatenationPrefix ++ tail distinctMetaDataTail
-									) inputData inputDataLength distinctInputData	-- Recurse to get 'Maybe (MatchList a)'.
-								) $ 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 []	-- Failure is inevitable.
-										else [fewest]
-									else {-imprecise range-} let
-{-
- Attempt to narrow the repetition-range, from the potentially unbounded specification, to that which is possible according to (data available / consumption-requirement),
- where there're bounds for both numerator & denominator.
- Additionally, one must account for the possibility of the denominator being zero, & if so, select the optimal value if the numerator is also zero.
- 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" #-} 1 {-zero is handled later-} `max` if any Data.Maybe.isNothing [maybeMaxConsumptionConcatenationTail, maybeMaxConsumptionAlternatives]
-											then fewest
-											else {-no unlimited capacities-} let
-												minDataAvailable, maxConsumptionAlternatives :: ConsumptionBounds.DataLength
-												minDataAvailable		= inputDataLength - Data.Maybe.fromJust maybeMaxConsumptionConcatenationTail	-- CAVEAT: can be negative.
-												maxConsumptionAlternatives	= Data.Maybe.fromJust maybeMaxConsumptionAlternatives
-											in if isSingletonAlternative
-												then if maxConsumptionAlternatives == 0							-- Denominator.
-													then {-sole Alternative can't consume anything ?!-} if minDataAvailable <= 0	-- Numerator.
-														then {-tail may consume all data-} fewest	-- Repeat to meet the minimum requirement.
-														else {-unconsumable data-} maxBound		-- Failure is inevitable.
-													else {-non-zero => can divide-} max fewest $ minDataAvailable /+ maxConsumptionAlternatives
-												else {-choice of Alternatives-} let
-													minDataAvailable' :: ConsumptionBounds.DataLength
-													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-} 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" #-} case most of
-											Just cap	-> cap `min` mostPermissibleRepetitions	-- Create a ceiling above which the calculated number of permissible repetitions can't rise.
-											_		-> mostPermissibleRepetitions
-											where
-												mostPermissibleRepetitions :: Repeatable.Repetitions
-												mostPermissibleRepetitions
-													| isSingletonAlternative		= if minConsumptionAlternatives == 0							-- Denominator.
-														then {-sole Alternative can consume zero data-} if maxDataAvailable == 0	-- Numerator.
-															then {-zero data available-} fewest		-- Repeat to meet the minimum requirement.
-															else {-data available-} maxDataAvailable	-- Either each repetition consumes something, or (n - 1) repetitions is a better solution.
-														else {-non-zero => can divide-} maxDataAvailable `div` minConsumptionAlternatives	-- Divide & round down.
-													| otherwise {-choice of Alternatives-}	= 1 {-account for instance expanded as 'concatenationFromAlternative'-} + let
-														maxDataAvailable' :: ConsumptionBounds.DataLength
-														maxDataAvailable'	= maxDataAvailable - minConsumptionConcatenationFromAlternative	-- CAVEAT: potentially negative.
-													in if minConsumptionAlternatives == 0							-- Denominator.
-														then {-@ least one Alternative can consume zero-} if maxDataAvailable' == 0	-- Numerator.
-															then {-zero data available $-} pred fewestAlternatives	-- Repeat as required. CAVEAT: an annoying dependency, which prevents parallel-evaluation.
-															else {-data available-} if and [
-																False,	-- The cost outweighs the small infrequent dividend.
-																minConsumptionConcatenationFromAlternative == 0,
-																maxDataAvailable > fewest
-															] -- If 'fewest' can be met, without unconsuming repetitions of 'concatenationFromAlternative', then stop short of permitting it.
-																then pred maxDataAvailable	-- Any greater, & one repetition (possibly that currently expanded) must needlessly consume nothing.
-																else maxDataAvailable'		-- Either all n repetitions consumes something, or (n - 1) is a better solution.
-														else {-non-zero => can divide-} maxDataAvailable' `div` minConsumptionAlternatives	-- Divide & round down.
-{-
- 'most' has been extracted from 'repeatablePatternHead',
- & reduced according to the number of times it can fit into the maximum available data, to form 'mostAlternatives',
- but if it still exceeds 'fewestAlternatives', the resulting repetition-range may trigger backtracking.
- So, attempt to further reduce this ill-defined repetition-range, according to the competing requirements of 'concatenationTail'.
- CAVEAT: this pays-off infrequently, but not necessarily insignificantly.
--}
-										mostAlternatives'	= {-#SCC "mostAlternatives'" #-} if and [
-											ExecutionOptions.moderateGreed executionOptions,
-											mostAlternatives > fewestAlternatives,	-- Otherwise, there's no unbridled greed to moderate.
-											minConsumptionAlternatives > 0		-- Otherwise, any number of repetitions can occur without necessarily triggering back-tracking.
-										 ]
-											then case maximumDataBeforePegs of
-												Just maximumDataBeforePegs'	-> mostAlternatives `min` (
-													length maximumDataBeforePegs' `div` minConsumptionAlternatives
-												 ) -- Cap upper bound.
-												_				-> 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.
-							 ) . (
-								if ExecutionOptions.permitReorderingOfAlternatives executionOptions
-{-
- The order in which 'Alternatives' are evaluated, should make no difference to the final result; unless 'ExecutionOptions.useFirstMatchAmongAlternatives'.
- This order can be manipulated in an attempt to more quickly locate any 'Just MatchList', though if 'ExecutionOptions.requireMatchList', an exhaustive search for the optimal solution must be performed anyway.
- Tackling lower-complexity 'Alternatives' first makes sense, in the hope of finding any easy solution before becoming entrenched fighting some hideous monster.
- Preferring 'Alternatives' which require more data also makes sense, regardless of 'Repeatable.isGreedy' which just a preference for a type of solution, because fewer repetitions are then permissible;
- this is rather like trying to pack a box & preferring to try the biggest items first.
--}
-									then Data.List.sortBy $ Data.Ord.comparing (
-										Consumer.starHeight &&& safeReciprocal . (fromIntegral :: ConsumptionBounds.DataLength -> Rational) . Consumer.getFewest
-									) -- Firstly increasing complexity, then decreasing minimum data-capacity, otherwise stable.
-									else id
-							 ) $ filter (
-								\e	-> (
-									not (hasBowAnchor e) || inputDataOffset == 0			-- Necessary & sufficient.
-								) && (
-									not (hasSternAnchor e) || minConsumptionConcatenationTail == 0	-- Necessary but insufficient, since though minimum consumption is zero, maximum isn't necessarily.
-								)
-							 ) extendedRegExAlternatives
-						in if null matchPairList
-							then if fewest <= 0
-								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',
- & if the caller reduces the 'Just MatchList' to 'True', that'd be sufficient, but otherwise one must identify the optimal 'MatchList'.
- The primary selection-criterion used is the POSIX one, based on total maximum (or minimum for non-'Repeatable.isGreedy' capture-groups) data-consumption.
- /Perl/'s "first-past-the-post" policy is available as an alternative.
--}
-								if ExecutionOptions.useFirstMatchAmongAlternatives executionOptions || length matchPairList == 1
-									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.
-									) . map (
-										(
-{-
- If the primary selection-criterion doesn't resolve the choice between candidate 'Match'es, I employ these ad-hoc criteria.
-
-	* Fewer repetitions are preferred, which discourages the capture of null lists of 'InputData'.
-
-	* Within the 'MatchedData', from which a candidate 'Match' is ultimately composed, consumption of 'InputData' beyond 'Repeatable.getFewest' by 'Repeatable.isGreedy' 'RepeatablePattern's, is preferred to non-greedy ones.
-
-	* The consumption on each successive repetition is compared between candidate 'Match'es (which are now known to have used an equal number of repetitions);
-	this causes the data-consumption to flow towards earlier repetitions for greedy capture-groups, & towards later repetitions in non-greedy ones,
-	thus mimicking the behaviour of the unrolled repetition.
-
-	* PS: more precise criteria are defined in <http://www2.research.att.com/~gsf/testregex/re-interpretation.html>.
--}
-											\match -> let
-												dataLengthCriterion :: InputData m -> Rational
-												dataLengthCriterion	= (
-													if isGreedy
-														then id
-														else safeReciprocal	-- Prefer less data.
-												 ) . fromIntegral . length
-
---												matchLists :: [MatchList m]
-												matchLists	= Tree.pop match
-											in (
-												dataLengthCriterion $ extractDataFromMatch match,
-												if ExecutionOptions.preferFewerRepeatedAlternatives executionOptions
-													then safeReciprocal . toRational $ length matchLists
-													else 0,
-												if ExecutionOptions.preferAlternativesWhichFeedTheGreedy executionOptions
-													then let
-														excessConsumption :: MatchedData m -> ConsumptionBounds.DataLength
-														excessConsumption (
-															Repeatable.MkRepeatable {
-																Repeatable.repetitionBounds	= (f, _),
-																Repeatable.isGreedy		= g
-															},
-															_,
-															consumedInputData
-														 )
-															| g		= l - f
-															| otherwise	= f - l
-															where
-																l :: ConsumptionBounds.DataLength
-																l	= length consumedInputData
-													in Data.Foldable.foldl' (\l -> (l +) . excessConsumption) 0 match
-													else 0,
-												if ExecutionOptions.preferAlternativesWhichMimickUnrolling executionOptions
-													then map (dataLengthCriterion . extractDataFromMatchList) matchLists
-													else []
-											) -- Create a tuple of selection-criteria, for simultaneous assessment.
-										) . fst {-focus the choice on the Alternatives-} &&& id	-- Prepend a selection-criterion to each result.
-									)
-							) matchPairList
-						where
---							tailMatch, zeroRepetitions :: Maybe (MatchList m)
-							tailMatch	= findMatchSlave concatenationTail accumulatedConsumptionProfilesTail distinctMetaDataTail inputData inputDataLength distinctInputData	-- Recurse.
-							zeroRepetitions	= (Tree.Node [] :) `fmap` {-apply to Maybe Functor-} tailMatch	-- Prepend a null 'MatchList'.
-
---							extendedRegExAlternatives :: [ExtendedRegEx m]
-							extendedRegExAlternatives	= Data.List.nub $ deconstructAlternatives alternatives
-
-							isSingletonAlternative :: Bool
-							isSingletonAlternative	= length extendedRegExAlternatives == 1
-
-							minConsumptionAlternatives	:: ConsumptionBounds.DataLength
-							maybeMaxConsumptionAlternatives	:: Maybe ConsumptionBounds.DataLength
-							(minConsumptionAlternatives, maybeMaxConsumptionAlternatives)	= Consumer.getConsumptionBounds alternatives	-- Independent of the choice of Alternative.
-			where
-				inputDataOffset :: ConsumptionBounds.DataLength
-				inputDataOffset	= originalInputDataLength - inputDataLength
-		findMatchSlave _ _ _ _ _ _	= error "RegExDot.RegEx.findMatch.findMatchSlave:\tunexpected parameter-pattern."
-
-{- |
-	* Operator's name was chosen to suggest something more than '=~'.
-
-	* 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, Control.DeepSeq.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
-inputData +~ regExOpts	= (
-	if hasBowAnchor' then Nothing else fmap head maybeMatchList,	-- Record the first 'Match', consumed in the absence of a top-level 'Anchor.Bow'.
-	fmap (
-		(
-			if hasBowAnchor' then id else tail			-- Remove the first 'Match', since this wasn't consumed by the 'Concatenation'.
-		) . (
-			if hasSternAnchor' then id else init			-- Remove the last 'Match', since this wasn't consumed by the 'Concatenation'.
-		)
-	) maybeMatchList,
-	if hasSternAnchor' then Nothing else fmap last maybeMatchList	-- Record the last 'Match', consumed in the absence of a top-level 'Anchor.Stern'.
- ) where
---	extendedRegEx :: ExtendedRegEx a
-	extendedRegEx	= RegExOpts.regEx regExOpts
-
-	hasBowAnchor', hasSternAnchor' :: Bool
-	hasBowAnchor'	= hasBowAnchor extendedRegEx
-	hasSternAnchor'	= hasSternAnchor extendedRegEx
-
---	maybeMatchList :: Maybe (MatchList m)
-	maybeMatchList	= fmap drift (RegExOpts.setVerbose True regExOpts) `findMatch` inputData
-
-{- |
-	* Pattern-match operator.
-
-	* Identifier & parameter-order follow the lead of /Perl/'s pattern-match operator.
-
-	* Considerably more efficient than '+~', since even though they are both implemented via 'findMatch',
-	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, Control.DeepSeq.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, Control.DeepSeq.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	= not . (inputData =~)
-
--- | The delimiters of 'Alternatives', when in the 'String'-form.
-captureGroupDelimiters :: (Char, Char)
-captureGroupDelimiters	= ('(', ')')
-
--- | The token used to separate alternative 'ExtendedRegEx's, when in the 'String'-form.
-alternativeExtendedRegExSeparatorToken :: Char
-alternativeExtendedRegExSeparatorToken	= '|'
-
--- | The set of 'Char' to which a specific meaning is attributed, when reading from 'String'.
-tokens :: String
-tokens	= [fst captureGroupDelimiters, snd captureGroupDelimiters, alternativeExtendedRegExSeparatorToken]
-
-{- |
-	* Invert the specified fraction, but return 'maxBound' if the result would otherwise be infinite.
-
-	* CAVEAT: this is an awful concept, and therefore intended for internal use only.
--}
-safeReciprocal :: (Eq f, Fractional f) => f -> f
-safeReciprocal 0	= fromIntegral (maxBound :: Int)	-- Handle divide-by-zero error.
-safeReciprocal f	= recip f
-
-infixl 7 /+	-- Same as (/).
-
-{- |
-	* Integral division, with any fractional remainder rounded-up.
-
-	* A rather dubious requirement, so internal use only.
--}
--- (/+) :: Integral i => i -> i -> i
-(/+)
-	:: Int	-- ^ Numerator.
-	-> Int	-- ^ Denominator.
-	-> Int	-- 10% faster in unoptimised code, & more in optimised.
-_ /+ 0				= error "RegExDot.RegEx.(/+):\tzero denominator => infinity"
--- numerator /+ denominator	= ceiling ((fromIntegral numerator / fromIntegral denominator) :: Double)
-numerator /+ denominator	= uncurry (+) . Control.Arrow.second signum $ quotRem numerator denominator	-- Slightly faster.
diff --git a/src/RegExDot/RegExOpts.hs b/src/RegExDot/RegExOpts.hs
deleted file mode 100644
--- a/src/RegExDot/RegExOpts.hs
+++ /dev/null
@@ -1,65 +0,0 @@
-{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
-{-
-	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@]
-
-	* Provides a complete job-specification.
-
-	* 'regEx' is polymorphic, allowing use of either /RegExDot.RegEx.ExtendedRegEx/ (which is also polymorphic) or /RegExChar.ExtendedRegExChar.ExtendedRegExChar/.
--}
-
-module RegExDot.RegExOpts(
--- * Types
--- ** Data-types
-	RegExOpts(..),
--- * Functions
-	setVerbose,
--- ** Constructors
-	mkRegEx
-) where
-
-import qualified	RegExDot.CompilationOptions	as CompilationOptions
-import qualified	RegExDot.ExecutionOptions	as ExecutionOptions
-import qualified	ToolShed.Defaultable
-
--- | Aggregates both 'ExecutionOptions.ExecutionOptions' & 'CompilationOptions.CompilationOptions' with a polymorphic /regex/, to form a complete job-description.
-data RegExOpts a	= MkRegExOpts {
-	compilationOptions	:: CompilationOptions.CompilationOptions,	-- ^ Parameters governing the result, rather than the implementation.
-	executionOptions	:: ExecutionOptions.ExecutionOptions,		-- ^ Parameters governing the implementation, rather than the result.
-	regEx			:: a						-- ^ Polymorphic, to permit specialisation either of the type of /regex/ or the type of input-data.
-} deriving Show
-
-instance Functor RegExOpts	where
-	fmap f regExOpts	= regExOpts { regEx = f $ regEx regExOpts }
-
--- | Smart constructor using 'ToolShed.Defaultable.defaultValue'.
-mkRegEx :: a -> RegExOpts a
-mkRegEx	r	= MkRegExOpts {
-	compilationOptions	= ToolShed.Defaultable.defaultValue,
-	executionOptions	= ToolShed.Defaultable.defaultValue,
-	regEx			= r
-}
-
--- | Mutator, which sets an appropriate 'ExecutionOptions.ExecutionOptions', for the depth to which the caller wants to probe the resulting match.
-setVerbose :: Bool -> RegExOpts a -> RegExOpts a
-setVerbose verbose regExOpts	= regExOpts { executionOptions = ExecutionOptions.setVerbose verbose $ executionOptions regExOpts }
-
diff --git a/src/RegExDot/Repeatable.hs b/src/RegExDot/Repeatable.hs
deleted file mode 100644
--- a/src/RegExDot/Repeatable.hs
+++ /dev/null
@@ -1,397 +0,0 @@
-{-
-	Copyright (C) 2010-2015 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 data-type, which represents the permissible range of instances, of the underlying polymorphic datum.
-
-	* Designed for use in a polymorphic /regex/-engine, which specifies patterns composed of repeated /greedy/ & /non-greedy/ sequences of /Meta/-data;
-
- >		*	+	?	{fewest, most}	{fewest,}	{fewest}
- >		*?	+?	??	{fewest, most}?	{fewest,}?
-
-	* In the context of /regex/es, this concept is known as /Quantification/.
-
-	* /regex/es evolved from the minimal ability to optionally qualify the datum with a <http://en.wikipedia.org/wiki/Kleene_star> suffix.
-	More exotic repetition-specifications could be composed by concatenating these atomic building-blocks.
-	Here, I've taken the contrary top-down view, & assumed that all data are qualified by a full 'RepetitionBounds', which in most cases will degenerate into a simpler form.
-
-	* The type of entity which is being repeated, isn't the domain of this data-type; it's polymorphic.
--}
-
-module RegExDot.Repeatable(
--- * Types
--- ** Type-synonyms
-	Repetitions,
-	RepetitionBounds,
--- ** Data-types
-	Repeatable(..),
--- * Constants
---	nonGreedyToken,
-	oneOrMoreToken,
-	rangeDelimiters,
-	rangeSeparatorToken,
-	tokens,
-	zeroOrMoreToken,
-	zeroOrOneToken,
--- * Functions
-	one,
-	oneOrMore,
-	oneOrMore',
-	zeroOrMore,
-	zeroOrMore',
-	zeroOrOne,
-	zeroOrOne',
---	precisely,
-	repeatableParser,
-	showSuffix,
--- ** Accessors
-	getFewest,
-	getMost,
--- ** Mutators
-	focus,
---	setNonGreedy,
-	toSingleton,
--- ** Operators
-	(^#->#),
-	(^#->#?),
-	(^#->),
-	(^#->?),
-	(^#),
--- ** Predicates
-	isPrecise,
-	hasPreciseBounds
-) where
-
-import Prelude hiding ((<$>), (<*>))	-- The "Prelude" from 'base-4.8' exports this symbol.
-import			Control.Applicative((<$>), (<*>))
-import			Control.Arrow((***))
-import qualified	Control.DeepSeq
-import qualified	Data.List
-import qualified	RegExDot.Consumer		as Consumer
-import qualified	RegExDot.ConsumptionProfile	as ConsumptionProfile
-import qualified	Text.ParserCombinators.Parsec	as Parsec
-import			Text.ParserCombinators.Parsec((<?>))
-import qualified	ToolShed.Data.Pair
-import qualified	ToolShed.SelfValidate
-
-infix 6 ^#->#, ^#->#?, ^#->, ^#->?, ^#	-- A notch tighter than "DSL"s binary operators.
-
--- | A number of repetitions.
-type Repetitions	= Int
-
--- | Defines the bounds of a range of permissible repetitions.
-type RepetitionBounds	= (Repetitions, Maybe Repetitions)
-
--- | Creates a precise 'RepetitionBounds', i.e. both lower & upper bounds on the number of 'Repetitions' are equal to the same value.
-precisely :: Repetitions -> RepetitionBounds
-precisely i	= (i, Just i)
-
--- | Predicate which is 'True' if exactly one value is permissible, ie lower & upper bounds on the number of 'Repetitions' are identical.
-hasPreciseBounds :: RepetitionBounds -> Bool
-hasPreciseBounds (fewest, most)	= Just fewest == most
-
--- | Declares a polymorphic data-type, which augments the underlying 'base' datum, with the range of times it may be used.
-data Repeatable a	= MkRepeatable {
-	base			:: a,			-- ^ The underlying polymorphic datum.
-	repetitionBounds	:: RepetitionBounds,	-- ^ The bounds delimiting the range of permissible repetitions, of 'base'.
-	isGreedy		:: Bool			-- ^ Whether to demand as many matching instances of 'base' as possible; or as few (AKA /lazy quantification/).
-} deriving Eq
-
-instance Functor Repeatable	where
-	fmap f repeatable	= repeatable { base = f $ base repeatable }
-
--- | True if there's no choice in the number of repetitions; implemented via 'isPrecise'.
-isPrecise :: Repeatable a -> Bool
-isPrecise	= hasPreciseBounds . repetitionBounds
-
--- | Builds a parser for a specification of the number of permissible instances of the specified polymorphic parameter.
-repeatableParser :: a -> Parsec.Parser (Repeatable a)
-repeatableParser b	= Parsec.option (
-	one b	-- The default; there's no concept of greediness here.
- ) $ do
-	repeatable	<- Parsec.choice [
-		(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")
-				most	<- Parsec.spaces >> Parsec.option (
-					Just fewest	-- The default.
-				 ) (
-					do
-						i	<- (
-							Parsec.char rangeSeparatorToken			<?> "Repeatable.rangeSeparatorToken " ++ show rangeSeparatorToken
-						 ) >> Parsec.spaces >> Parsec.option Nothing {-default to open-ended range-} (
-							Just . read <$> Parsec.many1 Parsec.digit	<?> "Repetition-range maximum"
-						 )
-
-						Parsec.spaces >> return {-to ParsecT-monad-} i
-				 )
-
-				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 ParsecT-monad-} False
-
-	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
-		[(base', s1)]	-> (error . ("readsPrec Repeatable:\tparse-error; " ++) . show) `either` return $ Parsec.parse ((,) <$> repeatableParser base' <*> Parsec.getInput) "Repeatable" s1
-		_		-> []	-- No parse.
-
-{- |
-	* A 'ShowS'-function for the suffix, denoting the permissible repetitions, of 'base'.
-
-	* This function converts the internal, into the tradition /greedy/ & /non-greedy/ quantifiers of various specific varieties.
--}
-showSuffix :: Repeatable a -> ShowS
-showSuffix repeatable	= let
-	showRange :: ShowS -> ShowS
-	showRange x	= (\(begin, end) -> begin . x . end) $ ToolShed.Data.Pair.mirror showChar rangeDelimiters
- in (
-	case repetitionBounds repeatable of
-		(0, Nothing)		-> showChar zeroOrMoreToken
-		(1, Nothing)		-> showChar oneOrMoreToken
-		(fewest, Nothing)	-> showRange $ shows fewest . showChar rangeSeparatorToken
-		(0, Just 1)		-> showChar zeroOrOneToken
-		(1, Just 1)		-> id	-- CAVEAT: since there's no explicit repetition-operator, the non-greedy modifier can't be appended.
-		(fewest, Just most)	-> showRange $ if fewest == most
-			then shows fewest	-- Single-valued range.
-			else shows fewest . showChar rangeSeparatorToken . shows most
- ) . if ($ repeatable) `any` [isGreedy, isPrecise] {-without a range of possibilities, non-greediness is irrelevant-}
-	then id
-	else showChar nonGreedyToken	-- This can only be appended, if there a previous repetition-operator for it to modify.
-
--- Replicate the syntax, for repetition, as used in a POSIX-standard /regex/.
-instance Show a => Show (Repeatable a)	where
-	showsPrec _ repeatable	= shows (base repeatable) . showSuffix repeatable
-
-instance Consumer.Consumer a => Consumer.Consumer (Repeatable a)	where
-	consumptionProfile MkRepeatable {
-		base			= b,
-		repetitionBounds	= (fewest, most)
-	} = baseConsumptionProfile {
-		ConsumptionProfile.consumptionBounds	= (fewest *) *** ((*) <$> most <*>) $ ConsumptionProfile.consumptionBounds baseConsumptionProfile	-- CAVEAT: special cases exist, where one or both halves of this calculation degenerate to a simpler form, but special treatment, in an attempt to improve performance, proved counterproductive.
-	} where
-		baseConsumptionProfile :: ConsumptionProfile.ConsumptionProfile
-		baseConsumptionProfile	= Consumer.consumptionProfile b
-
-	starHeight MkRepeatable {
-		base			= b,
-		repetitionBounds	= r
-	} = Consumer.starHeight b + if hasPreciseBounds r then 0 else 1
-
-instance ToolShed.SelfValidate.SelfValidator a => ToolShed.SelfValidate.SelfValidator (Repeatable a)	where
-	getErrors MkRepeatable {
-		base			= b,
-		repetitionBounds	= (fewest, most),
-		isGreedy		= g
-	}
-		| not $ ToolShed.SelfValidate.isValid b	= ToolShed.SelfValidate.getErrors b	-- Delegate.
-		| otherwise				= ToolShed.SelfValidate.extractErrors [
-			(fewest < 0, "Negative fewest=" ++ show fewest ++ "."),
-			(
-				case most of
-					Just m	-> m < fewest
-					_	-> False,
-				"Invalid repetition-range; '" ++ show (fewest, most) ++ "'."
-			), (
-				not g && case most of
-					Just m	-> fewest >= m	-- There ought to be potential for non-greediness, where specified: the converse isn't true, since greediness isn't explicit, & may not have been wanted.
-					_	-> False,
-				"Invalid non-greedy repetition-range; '" ++ show (fewest, most) ++ "'."
-			)
-		]
-
-instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Repeatable a)	where
-	rnf MkRepeatable {
-		base			= b,
-		repetitionBounds	= r,
-		isGreedy		= g
-	} = Control.DeepSeq.rnf (b, r, g)
-
--- | Mutator.
-setNonGreedy :: Repeatable a -> Repeatable a
-setNonGreedy r	= r { isGreedy = False }
-
-{- |
-	* Construct a greedy 'Repeatable', from a polymorphic datum, with the specified range of permissible instances.
-
-	* The /#/s in the identifier represent the two bounds.
-
-	* /a{f, m}/
--}
-(^#->#)
-	:: a			-- ^ The polymorphic payload from which to construct the 'Repeatable'.
-	-> RepetitionBounds	-- ^ The permissible repetition-bounds for the polymorphic data.
-	-> Repeatable a
-b ^#-># bounds	= MkRepeatable {
-	base			= b,
-	repetitionBounds	= bounds,
-	isGreedy		= True
-}
-
-{- |
-	* Construct a non-greedy version of '^#->#'.
-
-	* /a{f, m}?/
--}
-(^#->#?)
-	:: a			-- ^ The polymorphic payload from which to construct the 'Repeatable'.
-	-> RepetitionBounds	-- ^ The permissible repetition-bounds for the polymorphic data.
-	-> Repeatable a
-b ^#->#? bounds	= setNonGreedy (b ^#-># bounds)
-
-{- |
-	* Construct a greedy 'Repeatable', tailored for data repeated at least the specified number of times.
-
-	* The /#/ in the identifier represents the single bound.
-
-	* /a{f,}/
--}
-(^#->)
-	:: a		-- ^ The polymorphic payload from which to construct the 'Repeatable'.
-	-> Repetitions	-- ^ The minimum permissible repetitions of the polymorphic data.
-	-> Repeatable a
-b ^#-> fewest	= b ^#-># (fewest, Nothing)
-
-{- |
-	* Construct a non-greedy version of '^#->'.
-
-	* /a{f,}?/
--}
-(^#->?)
-	:: a		-- ^ The polymorphic payload from which to construct the 'Repeatable'.
-	-> Repetitions	-- ^ The minimum permissible repetitions of the polymorphic data.
-	-> Repeatable a
-b ^#->? fewest	= setNonGreedy (b ^#-> fewest)
-
-{- |
-	* Construct a 'Repeatable', tailored for data repeated a precise number of times.
-
-	* The /#/ in the identifier represents the single bound.
-
-	* /a{f}/
--}
-(^#)
-	:: a		-- ^ The polymorphic payload from which to construct the 'Repeatable'.
-	-> Repetitions	-- ^ The precise number of repetitions of the polymorphic data which is required.
-	-> Repeatable a
-b ^# r	= b ^#-># precisely r
-
-{- |
-	* Construct a 'Repeatable', tailored for unrepeated data.
-
-	* A degenerate case of '^#'.
--}
-one :: a -> Repeatable a
-one	= (^# 1)
-
-{- |
-	* Construct a greedy 'Repeatable', from a polymorphic datum, with 'fewest' == 0 & 'most' == 1.
-
-	* A specific case of '^#->#'.
--}
-zeroOrOne :: a -> Repeatable a
-zeroOrOne	= (^#-># (0, Just 1))
-
--- | Construct a non-greedy version of 'zeroOrOne'.
-zeroOrOne' :: a -> Repeatable a
-zeroOrOne'	= setNonGreedy . zeroOrOne
-
-{- |
-	* Construct a greedy 'Repeatable', from a polymorphic datum, with 'fewest' == 0.
-
-	* A specific case of '^#->'.
--}
-zeroOrMore :: a -> Repeatable a
-zeroOrMore	= (^#-> 0)
-
--- | Construct a non-greedy version of 'zeroOrMore'.
-zeroOrMore' :: a -> Repeatable a
-zeroOrMore'	= setNonGreedy . zeroOrMore
-
-{- |
-	* Construct a greedy 'Repeatable', from a polymorphic datum, with lower 'RepetitionBounds' == one.
-
-	* A specific case of '^#->'.
--}
-oneOrMore :: a -> Repeatable a
-oneOrMore	= (^#-> 1)
-
--- | Construct a non-greedy version of 'oneOrMore'.
-oneOrMore' :: a -> Repeatable a
-oneOrMore'	= setNonGreedy . oneOrMore
-
--- | Reduces a 'Repeatable', with a range of 'RepetitionBounds', to a precise number of repetitions.
-focus :: Repeatable a -> Repetitions -> Repeatable a
-focus r i	= r { repetitionBounds = precisely i }
-
-{- |
-	* Reduces a 'Repeatable', with a range of 'RepetitionBounds', to a singleton.
-
-	* A degenerate case of 'focus'.
--}
-toSingleton :: Repeatable a -> Repeatable a
-toSingleton	= (`focus` 1)
-
--- | Accessor.
-getFewest :: Repeatable a -> Repetitions
-getFewest MkRepeatable { repetitionBounds = (f, _) }	= f
-
--- | Accessor.
-getMost :: Repeatable a -> Maybe Repetitions
-getMost MkRepeatable { repetitionBounds = (_, m) }	= m
-
--- | The token used to denote /non-greedy/, when in the 'String'-form.
-nonGreedyToken :: Char
-nonGreedyToken	= '?'
-
-{- |
-	* The token used to denote 'zeroOrMore', when in the 'String'-form.
-
-	* AKA /Kleene Star/.
--}
-zeroOrMoreToken :: Char
-zeroOrMoreToken	= '*'
-
--- | The token used to denote 'zeroOrOne', when in the 'String'-form.
-zeroOrOneToken :: Char
-zeroOrOneToken	= '?'
-
--- | The token used to denote 'oneOrMore', when in the 'String'-form.
-oneOrMoreToken :: Char
-oneOrMoreToken	= '+'
-
--- | The delimiters of '^#->#', when in the 'String'-form.
-rangeDelimiters :: (Char, Char)
-rangeDelimiters	= ('{', '}')
-
--- | The token used to separate 'RepetitionBounds', when in the 'String'-form.
-rangeSeparatorToken :: Char
-rangeSeparatorToken	= ','
-
--- | The set of 'Char' to which a specific meaning is attributed, when reading from 'String'.
-tokens :: String
-tokens	= Data.List.nub [nonGreedyToken, zeroOrMoreToken, zeroOrOneToken, oneOrMoreToken, fst rangeDelimiters, snd rangeDelimiters, rangeSeparatorToken]
-
diff --git a/src/RegExDot/Result.hs b/src/RegExDot/Result.hs
deleted file mode 100644
--- a/src/RegExDot/Result.hs
+++ /dev/null
@@ -1,60 +0,0 @@
-{-
-	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@]	Tools to manipulate a 'RegEx.Result'.
-
- [@CAVEAT@]	The data-definition remains in "RegEx", since it references 'RegEx.Match'.
--}
-
-module RegExDot.Result(
--- * Functions
--- ** Accessors (Deconstructors)
-	getMatchList,
-	getPreMatch,
-	getPostMatch,
--- ** Predicates
-	isMatch,
--- ** Query
-	countMatches
-) where
-
-import qualified	Data.Maybe
-import qualified	RegExDot.RegEx	as RegEx
-
--- | Accessor.
-getPreMatch :: RegEx.Result a -> RegEx.ExternalMatch a
-getPreMatch (externalMatch, _, _)	= externalMatch
-
--- | Accessor.
-getPostMatch :: RegEx.Result a -> RegEx.ExternalMatch a
-getPostMatch (_, _, externalMatch)	= externalMatch
-
--- | Accessor.
-getMatchList :: RegEx.Result a -> Maybe (RegEx.MatchList a)
-getMatchList (_, maybeMatchList, _)	= maybeMatchList
-
--- | True if the 'RegEx.InputData' matched the 'RegEx.ExtendedRegEx'.
-isMatch :: RegEx.Result a -> Bool
-isMatch	= Data.Maybe.isJust . getMatchList
-
--- | Counts the number of top-level 'RegEx.Match'es.
-countMatches :: RegEx.Result a -> Int
-countMatches (_, Just matchList, _)	= length matchList
-countMatches _				= 0
-
diff --git a/src/RegExDot/ShowablePredicate.hs b/src/RegExDot/ShowablePredicate.hs
deleted file mode 100644
--- a/src/RegExDot/ShowablePredicate.hs
+++ /dev/null
@@ -1,53 +0,0 @@
-{-
-	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@]	Used to implement /Perl-shortcut/s, /BracketExpression/-ranges & /POSIX Character-classes/.
--}
-
-module RegExDot.ShowablePredicate(
--- * Types
-	Predicate,
--- ** Data-types
-	ShowablePredicate(
-		MkShowablePredicate,
-		name,
-		predicate
-	)
-) where
-
-import qualified	Control.DeepSeq
-
--- | An arbitrary polymorphic predicate function.
-type Predicate a	= a -> Bool
-
--- | Container for both the /predicate/, & the name used in the implementation of 'Show'.
-data ShowablePredicate a	= MkShowablePredicate {
-	name		:: String,	-- ^ The identifier of this predicate when in string-form.
-	predicate	:: Predicate a	-- ^ The function used to determine whether an input datum matches.
-}
-
-instance Show (ShowablePredicate a)	where
-	showsPrec _	= showString . name
-
-instance Eq (ShowablePredicate a)	where
-	l == r	= name l == name r	-- Ignore 'predicate'.
-
-instance Control.DeepSeq.NFData (ShowablePredicate a)	where
-	rnf	= Control.DeepSeq.rnf . name	-- Ignore 'predicate'.
-
diff --git a/src/RegExDot/Span.hs b/src/RegExDot/Span.hs
deleted file mode 100644
--- a/src/RegExDot/Span.hs
+++ /dev/null
@@ -1,64 +0,0 @@
-{-
-	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@]	Delimits a data-sequence, via its offset & length, within a wider list.
--}
-
-module RegExDot.Span(
--- * Types
--- ** Type-synonyms
-	Span,
--- * Functions
-	after,
-	empty,
-	join
-) where
-
-import			Control.Arrow((***))
-import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
-
-{- |
-	* The offset & length of a specific data-sequence, within a wider list.
-
-	* Similar to <http://hackage.haskell.org/packages/archive/regex-base/latest/doc/html/Text-Regex-Base-RegexLike.html#t%3AMatchArray>.
--}
-type Span	= (ConsumptionBounds.DataLength {-offset-}, ConsumptionBounds.DataLength)
-
--- | An empty instance, located at the specified offset.
-empty :: ConsumptionBounds.DataLength -> Span
-empty offset	= (offset, 0)
-
--- | Returns the furthest extent, i.e. the offset just after the end.
-after :: Span -> ConsumptionBounds.DataLength
-after	= uncurry (+)
-
-{- |
-	* Condenses a list into a single value.
-
-	* Expects a gap-free, sorted list.
--}
-join
-	:: ConsumptionBounds.DataLength	-- ^ The offset into the list of input-data to use when a null list of spans is received.
-	-> [Span]
-	-> Span
-join offset []		= empty offset		-- The offset can't be deduced from a null list, so use the value provided.
-join _ [singleton]	= singleton		-- Merely for efficiency.
-join _ spanList		= head *** sum $ unzip spanList
-
-
diff --git a/src/RegExDot/Tree.hs b/src/RegExDot/Tree.hs
deleted file mode 100644
--- a/src/RegExDot/Tree.hs
+++ /dev/null
@@ -1,80 +0,0 @@
-{-
-	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@]
-
-	* Defines a specific type of tree-structure, which is composed from either a datum, or a list of Tree-lists; <http://en.wikipedia.org/wiki/Rose_Tree>.
-
-	* This more general tree-structure has the shape of a regular-expression match.
-
-	* This contrasts with the typical binary-tree, which is either empty, or contains a (left Tree, datum, right Tree).
--}
-
-module RegExDot.Tree(
--- * Types
--- ** Type-synonyms
---	TreeList,
--- ** Data-types
-	Tree(..),
--- * Functions
-	pop
-) where
-
-import qualified	Control.Arrow
-import qualified	Control.DeepSeq
-import qualified	Data.Foldable
-import qualified	Data.List
-import qualified	Data.Monoid
-
--- | A general purpose tree-type structure.
-data Tree a	=
-	Leaf a			-- ^ The payload.
-	| Node [TreeList a]	-- ^ Recurse. NB: a list of lists is required to contain the /MatchLists/ resulting from repeated /Alternatives/.
-	deriving Eq
-
--- | A list of 'Tree's; significant only because it is the essence of the recursive nature of 'Tree'.
-type TreeList a	= [Tree a]
-
-instance Show a => Show (Tree a)	where
-	showsPrec _ (Leaf a)		= shows a
-	showsPrec _ (Node treeLists)	= showList treeLists
-
-instance Read a => Read (Tree a)	where
-	readsPrec _ node@('[' : _)	= Control.Arrow.first Node `map` readList node {-singleton-}
-	readsPrec _ leaf		= Control.Arrow.first Leaf `map` reads leaf {-singleton-}
-
-instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Tree a)	where
-	rnf (Leaf a)	= Control.DeepSeq.rnf a
-	rnf (Node l)	= Control.DeepSeq.rnf l
-
-instance Functor Tree	where
-	fmap f (Leaf a)		= Leaf $ f a
-	fmap f (Node treeLists)	= Node $ map (fmap {-recurse-} f `map`) treeLists
-
-instance Data.Foldable.Foldable Tree where
-	foldMap f (Leaf a)		= f a	-- CAVEAT: 'f' should be Associative, as required by a Monoid.
-	foldMap f (Node treeLists)	= Data.List.foldl' (Data.List.foldl' (\monoid -> (monoid `Data.Monoid.mappend`) . Data.Foldable.foldMap f)) Data.Monoid.mempty treeLists
-
--- | Deconstruct the specified 'Node'; i.e. lop the apex from the 'Tree', leaving a flat top.
-pop
-	:: Tree a	-- ^ The tree from which to extract the list of trees hanging immediately beneath its apex.
-	-> [TreeList a]
-pop (Node treeLists)	= treeLists
-pop _			= error "RegExDot.Tree.pop:\tunexpected Leaf"
-
