diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,675 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,5 @@
+#!/usr/bin/env runhaskell
+
+import qualified	Distribution.Simple
+
+main	= Distribution.Simple.defaultMain
diff --git a/changelog b/changelog
new file mode 100644
--- /dev/null
+++ b/changelog
@@ -0,0 +1,25 @@
+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".
diff --git a/copyright b/copyright
new file mode 100644
--- /dev/null
+++ b/copyright
@@ -0,0 +1,11 @@
+Author:
+	Dr. Alistair Ward <regexdot at functionalley dot eu>.
+
+Copyright:
+	Copyright (C) 2010-2011 Dr. Alistair Ward. All Rights Reserved.
+
+Home-page:
+	http://functionalley.eu
+
+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
new file mode 100644
--- /dev/null
+++ b/makefile
@@ -0,0 +1,55 @@
+# 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/>.
+ 
+.PHONY: all build 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.hs $@ $$CABAL_INSTALL_OPTIONS
+
+prof:
+	CABAL_CONFIGURE_OPTIONS="--enable-library-profiling $$CABAL_CONFIGURE_OPTIONS" make install
+
+copy: build
+	@[ -z "$$CABAL_COPY_OPTIONS" ] || echo "INFO: CABAL_COPY_OPTIONS='$$CABAL_COPY_OPTIONS'"
+	runhaskell Setup.hs $@ $$CABAL_COPY_OPTIONS
+
+build: configure
+	@[ -z "$$CABAL_BUILD_OPTIONS" ] || echo "INFO: CABAL_BUILD_OPTIONS='$$CABAL_BUILD_OPTIONS'"
+	runhaskell Setup.hs $@ $$CABAL_BUILD_OPTIONS
+
+configure: regexdot.cabal Setup.hs
+	@[ -z "$$CABAL_CONFIGURE_OPTIONS" ] || echo "INFO: CABAL_CONFIGURE_OPTIONS='$$CABAL_CONFIGURE_OPTIONS'"
+	runhaskell Setup.hs $@ $$CABAL_CONFIGURE_OPTIONS	#--user
+
+haddock: configure
+	PATH=~/.cabal/bin:$$PATH runhaskell Setup.hs $@ --hyperlink-source	#Amend path to find 'HsColour', as required for 'hyperlink-source'.
+
+hlint:
+	@$@ src/
+
+sdist: configure
+	runhaskell Setup.hs $@
+
+clean:
+	runhaskell Setup.hs $@
+
+help:
+	@grep '^[a-zA-Z].*:' makefile | sed -e 's/:.*//'
+
+rpm: regexdot.rpm build
+
diff --git a/regexdot.cabal b/regexdot.cabal
new file mode 100644
--- /dev/null
+++ b/regexdot.cabal
@@ -0,0 +1,80 @@
+--Package-properties
+Name:			regexdot
+Version:		0.10.2.1
+Cabal-Version:		>= 1.6
+Copyright:		(C) 2010 Dr. Alistair Ward
+License:		GPL
+License-file:		LICENSE
+Author:			Dr. Alistair Ward
+Stability:		Unstable interface, incomplete features.
+Synopsis:		A /polymorphic/, POSIX, extended regular-expression 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
+Homepage:		http://functionalley.eu
+Maintainer:		regexdot <at> functionalley <dot> eu
+Bug-reports:		regexdot <at> functionalley <dot> eu
+Extra-Source-Files:	changelog, copyright, makefile
+
+flag haveDeepSeq
+    Description:	Use 'Control.DeepSeq' rather than the older module 'Control.Parallel.Strategies'.
+    Default:		True
+
+flag llvm
+    Description:	Whether the 'llvm' backend has been installed and is required for code-generation.
+    manual:		True
+    default:		False
+
+flag threaded
+    Description:	Enable parallelized code.
+    default:		True
+
+Library
+    hs-source-dirs:	src
+
+    Exposed-modules:
+        RegExDot.Anchor
+        RegExDot.BracketExpression
+        RegExDot.BracketExpressionMember
+        RegExDot.CompilationOptions
+        RegExDot.Consumer
+        RegExDot.ConsumptionBounds
+        RegExDot.ConsumptionProfile
+        RegExDot.DataSpan
+        RegExDot.DataSpanTree
+        RegExDot.DSL
+        RegExDot.ExecutionOptions
+        RegExDot.InstanceInt
+        RegExDot.Meta
+        RegExDot.RegEx
+        RegExDot.RegExOpts
+        RegExDot.Repeatable
+        RegExDot.Result
+        RegExDot.ShowablePredicate
+        RegExDot.Span
+        RegExDot.Tree
+
+    Build-depends:
+        base == 4.*,
+        parsec == 3.*,
+        toolshed == 0.11.*
+
+    GHC-options:	-Wall -O2
+    GHC-prof-options:	-prof -auto-all -caf-all
+
+    if flag(haveDeepSeq)
+        Build-depends:	deepseq >= 1.1
+        CPP-options:	-DHAVE_DEEPSEQ
+    else
+        Build-depends:	parallel == 1.*
+
+    if flag(threaded)
+        Build-depends:	parallel >= 3.0
+        GHC-options:	-feager-blackholing
+    else
+        Build-depends:	parallel
+
+    if impl(ghc >= 7.0) && flag(llvm)
+        GHC-options:	-fllvm
+
diff --git a/src/RegExDot/Anchor.hs b/src/RegExDot/Anchor.hs
new file mode 100644
--- /dev/null
+++ b/src/RegExDot/Anchor.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE CPP #-}
+{-
+	Copyright (C) 2010 Dr. Alistair Ward
+
+	This program is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+{- |
+ [@AUTHOR@]	Dr. Alistair Ward
+
+ [@DESCRIPTION@]
+
+	* A type of /zero-width assertion/:
+	the 'Bow'-predicate is 'True' if no input-data has yet been consumed; the 'Stern'-predicate is 'True' if no input-data remains to be consumed.
+
+	* Whilst at the top-level of the regex, the /absence/ of an anchor is equivalent to a non-capturing @.*?@,
+	tempting one to implement them using this property,
+	it doesn't apply to those anchors encountered at either end of a sub-expression.
+	So in all cases, an anchor constrains the permissible consumption of input-data,
+	but at the top level it also prevents the regex drifting away from either end of the input-data.
+-}
+
+module RegExDot.Anchor(
+-- * Types
+-- ** Data-types
+	Anchor(..),
+-- * Constants
+	bowToken,
+	sternToken,
+	tokens
+) where
+
+#ifdef HAVE_DEEPSEQ
+import	Control.DeepSeq(NFData, rnf)
+#else
+import	Control.Parallel.Strategies(NFData, rnf)
+#endif
+
+-- | Defines the types on /anchor/ by which a /regex/ can be moored to a part of the input-data.
+data Anchor =
+	Bow	-- ^ Matches only if no input data has yet been consumed. Can only exist at the start of the entire regex, or (in theory) the start of any /alternative/.
+	| Stern	-- ^ Matches only if no input data remains to be consumed. Can only exist at the end of the entire regex, or (in theory) the end of any /alternative/.
+	deriving (
+		Eq
+--		Read,	--See specialisation below.
+--		Show	--See specialisation below.
+	)
+
+instance Show Anchor	where
+	showsPrec _ Bow		= showChar bowToken
+	showsPrec _ Stern	= showChar sternToken
+
+instance Read Anchor	where
+	readsPrec _ []		= []	--No parse.
+	readsPrec _ (' ' : s)	= reads s	--Consume white-space.
+	readsPrec _ ('\t' : s)	= reads s	--Consume white-space.
+	readsPrec _ (c : s)	= case c `lookup` [(bowToken, Bow), (sternToken, Stern)] of
+		Just anchor	-> [(anchor, s)]
+		_		-> []	--No parse.
+
+instance NFData Anchor	where
+	rnf _	= ()
+
+-- | The conventional token used to denote a 'Bow'-anchor, when in 'String'-form.
+bowToken :: Char
+bowToken	= '^'
+
+-- | The conventional token used to denote a 'Stern'-anchor, when in 'String'-form.
+sternToken :: Char
+sternToken	= '$'
+
+-- | The set of 'Char' to which a specific meaning is attributed, when reading from 'String'.
+tokens :: String
+tokens	= [bowToken, sternToken]
+
diff --git a/src/RegExDot/BracketExpression.hs b/src/RegExDot/BracketExpression.hs
new file mode 100644
--- /dev/null
+++ b/src/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/RegExDot/BracketExpressionMember.hs b/src/RegExDot/BracketExpressionMember.hs
new file mode 100644
--- /dev/null
+++ b/src/RegExDot/BracketExpressionMember.hs
@@ -0,0 +1,99 @@
+{-# LANGUAGE CPP #-}
+{-
+	Copyright (C) 2010 Dr. Alistair Ward
+
+	This program is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+{- |
+ [@AUTHOR@]	Dr. Alistair Ward
+
+ [@DESCRIPTION@]
+
+	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	RegExDot.ShowablePredicate	as ShowablePredicate
+
+#ifdef HAVE_DEEPSEQ
+import			Control.DeepSeq(NFData, rnf)
+#else
+import			Control.Parallel.Strategies(NFData, rnf)
+#endif
+
+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 NFData m => NFData (Member m)	where
+	rnf (Predicate showablePredicate)	= rnf showablePredicate
+	rnf (Literal literal)			= 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
new file mode 100644
--- /dev/null
+++ b/src/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	as Defaultable
+import qualified	ToolShed.Options	as 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 Defaultable.Defaultable CompilationOptions	where
+	defaultValue	= Options.blankValue { complyStrictlyWithPosix	= True }
+
+instance Options.Options CompilationOptions	where
+	blankValue	= MkCompilationOptions { complyStrictlyWithPosix = undefined }
+
diff --git a/src/RegExDot/Consumer.hs b/src/RegExDot/Consumer.hs
new file mode 100644
--- /dev/null
+++ b/src/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/RegExDot/ConsumptionBounds.hs b/src/RegExDot/ConsumptionBounds.hs
new file mode 100644
--- /dev/null
+++ b/src/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/RegExDot/ConsumptionProfile.hs b/src/RegExDot/ConsumptionProfile.hs
new file mode 100644
--- /dev/null
+++ b/src/RegExDot/ConsumptionProfile.hs
@@ -0,0 +1,146 @@
+{-
+	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 '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.Applicative((<$>), (<*>))
+import qualified	Data.List
+import qualified	RegExDot.ConsumptionBounds	as ConsumptionBounds
+import qualified	ToolShed.SelfValidate		as 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 SelfValidate.SelfValidator ConsumptionProfile	where
+	isValid c@(
+		MkConsumptionProfile {
+			consumptionBounds	= (fewest, most),
+			hasSpecificRequirement	= hasSpecificRequirement',
+			canConsumeAnything	= canConsumeAnything'
+		}
+	 ) = and [
+		fewest >= 0,
+		case most of
+			Nothing	-> True
+			Just m	-> m >= fewest,
+		or [c == zero, hasSpecificRequirement', canConsumeAnything']
+	 ]
+
+{-
+-- | '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 MkConsumptionProfile {
+	consumptionBounds	= (minConsumption, maxConsumption)
+} = dataLength >= minConsumption && case maxConsumption of
+	Nothing	-> True
+	Just m	-> dataLength <= m
+
+-- | 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
new file mode 100644
--- /dev/null
+++ b/src/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.
+-}
+(<~>) ::
+	(Maybe Anchor.Anchor, Maybe Anchor.Anchor)	-- ^ A specification for the anchors required around the expression.
+	-> RegEx.Concatenation a			-- ^ The bare list of repeatable patterns to anchor.
+	-> RegEx.ExtendedRegEx a			-- ^ The completed regex.
+(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
new file mode 100644
--- /dev/null
+++ b/src/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/RegExDot/DataSpanTree.hs b/src/RegExDot/DataSpanTree.hs
new file mode 100644
--- /dev/null
+++ b/src/RegExDot/DataSpanTree.hs
@@ -0,0 +1,109 @@
+{-
+	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 transformation of 'RegEx.MatchList', to facilitate standardisation.
+-}
+
+module RegExDot.DataSpanTree(
+-- * Types
+-- ** Type-synonyms
+--	DataSpanTree,
+--	DataSpanTreeList,
+-- * Functions
+	extractCaptureGroups,
+	flattenTreeList,
+	toTreeList
+) where
+
+import			Control.Applicative((<$>))
+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	= (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
new file mode 100644
--- /dev/null
+++ b/src/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	as Defaultable
+import qualified	ToolShed.Options	as 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 Defaultable.Defaultable ExecutionOptions	where
+	defaultValue	= setVerbose False $ 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 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
new file mode 100644
--- /dev/null
+++ b/src/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/RegExDot/Meta.hs b/src/RegExDot/Meta.hs
new file mode 100644
--- /dev/null
+++ b/src/RegExDot/Meta.hs
@@ -0,0 +1,150 @@
+{-# LANGUAGE CPP #-}
+{-
+	Copyright (C) 2010 Dr. Alistair Ward
+
+	This program is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+{- |
+ [@AUTHOR@]	Dr. Alistair Ward
+
+ [@DESCRIPTION@]
+
+	* 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	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			as SelfValidate
+
+#ifdef HAVE_DEEPSEQ
+import			Control.DeepSeq(NFData, rnf)
+#else
+import			Control.Parallel.Strategies(NFData, rnf)
+#endif
+
+{- |
+	* 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 SelfValidate.SelfValidator (Meta m)	where
+	isValid _	= True
+
+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
+	readsPrec _ ('\\' : c : s)		= [(expand c, s)]
+	readsPrec _ literal			= Control.Arrow.first Literal `map` reads literal
+
+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 NFData m => NFData (Meta m)	where
+	rnf Any					= ()
+	rnf (Literal m)				= rnf m
+	rnf (AnyOf bracketExpression)		= rnf bracketExpression
+	rnf (NoneOf bracketExpression)		= rnf bracketExpression
+	rnf (Predicate showablePredicate)	= 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
new file mode 100644
--- /dev/null
+++ b/src/RegExDot/RegEx.hs
@@ -0,0 +1,1194 @@
+{-# LANGUAGE CPP #-}
+{-
+	Copyright (C) 2010 Dr. Alistair Ward
+
+	This program is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+{- |
+ [@AUTHOR@]	Dr. Alistair Ward
+
+ [@DESCRIPTION@]
+
+	* This implementation of extended /regex/es, generalises the familiar concept of pattern-matching of character-strings, to matching lists composed from an arbitrary data-type.
+	The polymorphic data, from which the input data-list is composed, need only support @Eq@ & @Show@.
+
+	* 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 '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.Applicative((<$>))
+import			Control.Arrow((&&&))
+import			RegExDot.Repeatable((^#->))
+import qualified	Control.Arrow
+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 qualified	RegExDot.Tree			as Tree
+import qualified	ToolShed.ListPlus		as ListPlus
+import qualified	ToolShed.SelfValidate		as SelfValidate
+
+#if MIN_VERSION_parallel(3,0,0)
+import qualified	Control.Parallel.Strategies
+#endif
+
+#ifdef HAVE_DEEPSEQ
+import			Control.DeepSeq(NFData, rnf)
+#else
+import			Control.Parallel.Strategies(NFData, rnf)
+#endif
+
+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
+			_		-> [(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 SelfValidate.SelfValidator (Alternatives m)	where
+	isValid	= SelfValidate.isValid . deconstructAlternatives
+
+instance NFData m => NFData (Alternatives m)	where
+	rnf	= 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,
+	ie @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 (ShortcutExpander m, Meta.ShortcutExpander m, Eq m, Read 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 SelfValidate.SelfValidator (Pattern m)	where
+	isValid (Require meta)			= SelfValidate.isValid meta
+	isValid (CaptureGroup alternatives)	= SelfValidate.isValid alternatives
+
+instance NFData m => NFData (Pattern m)	where
+	rnf (Require meta)		= rnf meta
+	rnf (CaptureGroup alternatives)	= 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, ie 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 (ShortcutExpander m, Meta.ShortcutExpander m, Eq m, Read 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			= (SelfValidate.isValid . fst) `filter` [
+		(
+			MkExtendedRegEx {
+				bowAnchor	= maybeBowAnchor,
+				concatenation	= concatenation',
+				sternAnchor	= maybeSternAnchor
+			},
+			remainder
+		) |
+			(maybeBowAnchor, s1)		<- readsMaybeAnchor s,
+			(concatenation', s2)		<- reads s1,
+			(maybeSternAnchor, remainder)	<- readsMaybeAnchor s2
+
+	 ] 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 SelfValidate.SelfValidator (ExtendedRegEx m)	where
+	isValid	= SelfValidate.isValid {-delegate-} . concatenation	--NB: null 'Concatenation' is OK.
+
+instance NFData m => NFData (ExtendedRegEx m)	where
+	rnf MkExtendedRegEx {
+		bowAnchor	= maybeBowAnchor,
+		concatenation	= concatenation',
+		sternAnchor	= maybeSternAnchor
+	} = 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', ie 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 (ie 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 <$>)
+
+-- | 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, NFData m, Show 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'.
+	]		= {-Unsafe.printShow "Tail-mismatch:\t"-} 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,
+			NFData m,
+			Show m
+		 )	=> Concatenation m					--The list of 'RepeatablePattern's from which the regex is constructed.
+			-> ConsumptionProfile.AccumulatedConsumptionProfiles	--The capacity-bounds for the consumption of 'InputData', that the 'Concatenation' extending right from any given 'RepeatablePattern', can consume.
+			-> [MetaDataList m]					--The set of distinct 'Meta.Meta'-data, in the 'Concatenation extending right from any given 'RepeatablePattern'.
+			-> InputData m						--The input data, which will be fed to the 'Concatenation'.
+			-> ConsumptionBounds.DataLength				--The length of the previously specified 'InputData'.
+			-> [InputData m]					--The set of distinct input data, extending right from any given point.
+			-> Maybe (MatchList m)
+		findMatchSlave [] _ _ [] _ _	= {-Unsafe.printShow "Dead heat:\t" $-} Just []	--Simultaneous exhaustion of the 'Concatenation' of 'RepeatablePattern's & the 'InputData' => success.
+		findMatchSlave [] _ _ _ _ _	= {-Unsafe.printShow "Excess data:\t"-} Nothing
+		findMatchSlave concatenation'@(repeatablePatternHead : concatenationTail) (accumulatedConsumptionProfileHead : accumulatedConsumptionProfilesTail) (distinctMetaDataHead : distinctMetaDataTail) inputData inputDataLength distinctInputData@(distinctInputDataHead : _)
+			| not $ inputDataLength `ConsumptionProfile.withinConsumptionBounds` accumulatedConsumptionProfileHead	= {-Unsafe.printShow "outside ConsumptionBounds:\t"-} 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.
+			] = {-Unsafe.printShow ("Unconsumable data=" ++ show inputData ++ ":\t")-} Nothing
+			| otherwise	= {-#SCC "findMatchSlave" #-} let
+				tailConsumptionProfile :: ConsumptionProfile.ConsumptionProfile
+				tailConsumptionProfile@(
+					ConsumptionProfile.MkConsumptionProfile {
+						ConsumptionProfile.consumptionBounds	= (minConsumptionConcatenationTail, maybeMaxConsumptionConcatenationTail)
+					}
+				 ) = {-Unsafe.printShow "tailConsumptionProfile:\t" $-} head accumulatedConsumptionProfilesTail	--Extract the aggregate consumption-profile, of the tail of the 'Concatenation'.
+
+				maxDataAvailable :: ConsumptionBounds.DataLength
+				maxDataAvailable	= inputDataLength - minConsumptionConcatenationTail	--The maximum data available to match 'repeatablePatternHead'.
+			in if maxDataAvailable < 0
+				then {-Unsafe.printShow ("Excess Concatenation=" ++ show concatenation' ++ ":\t")-} Nothing
+				else {-inputData is sufficient for concatenationTail-} let
+					Repeatable.MkRepeatable {
+						Repeatable.base			= base,
+						Repeatable.repetitionBounds	= (fewest, most),
+						Repeatable.isGreedy		= isGreedy
+					} = {-Unsafe.printShow "repeatablePatternHead:\t"-} repeatablePatternHead	--Completely deconstruct the 'Repeatable' at the head of the 'Concatenation'.
+{-
+ Find the maximum sequence of inputData, preceding the first of the mandatory requirements of 'concatenationTail'.
+ This enables one to more tightly constrain the maximum number of repetitions of a 'RepeatablePattern',
+ which consequently reduces the subsequent requirement to back-track.
+-}
+--					maximumDataBeforePegs :: Maybe (InputData m)
+					maximumDataBeforePegs	= {-#SCC "maximumDataBeforePegs" #-} reverse (
+						{-Unsafe.printShow "minimumRequirement:\t" $-} extractMinimumRequirementFromConcatenation concatenationTail
+					 ) `maximumDataAfterPegs` reverse inputData	where
+{-
+ 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 . {-Unsafe.printShow "maybeMatchList:\t" .-} map (
+								\(consumedInputData, unconsumedInputData)	-> let
+									consumedInputDataLength :: ConsumptionBounds.DataLength
+									consumedInputDataLength	= {-Unsafe.printShow "consumedInputDataLength:\t" $-} length consumedInputData
+								in (
+									Tree.Leaf (repeatablePatternHead, inputDataOffset, {-Unsafe.printShow "consumedInputData:\t"-} consumedInputData) :
+								) <$> {-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" #-} {-Unsafe.printShow "fewestData:\t" $-} case maybeMaxConsumptionConcatenationTail of
+									Just m	-> (inputDataLength - m) {- :: ConsumptionBounds.DataLength-} `max` fewest {- :: Repeatable.Repetitions-}	--CAVEAT: conceptually different types.
+									_	-> fewest
+
+--								mostData	= length . takeWhile (~= meta) $ (`take` inputData) maxData	--As slow as it is concise.
+								mostData	= {-#SCC "mostData" #-} {-Unsafe.printShow "mostData:\t" $-} maxData - measureUnmatchableTail inputData maxData	where
+									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 $ unmatched - 1	--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'	-> {-Unsafe.printShow ("Reducing mostData=" ++ show mostData ++ " ->\t") $-} mostData `min` length maximumDataBeforePegs'	--Cap upper bound.
+										_				-> {-Unsafe.printShow "Peg match-failure:\t" $-} negate 1	--Guaranteed to be < 'fewestData'.
+									| otherwise {-no requirement for this optimisation-}	= mostData
+							 in (
+								1 + {-fence-post-} mostData' - fewestData	--CAVEAT: possibly <= 0.
+							 ) `take` (
+								if isGreedy
+									then ListPlus.splitsLeftFrom mostData'
+									else ListPlus.splitsRightFrom fewestData
+							 ) inputData
+
+					CaptureGroup alternatives
+						| and [
+							not isGreedy,
+							fewest <= 0,	--Zero repetitions permissible.
+							Data.Maybe.isJust tailMatch
+						] {-Unsafe.printShow "Trying zero alternatives:\t"-}	-> zeroRepetitions	--Zero repetitions is the optimal solution, rendering the choice of Alternative irrelevant.
+						| 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 . {-Unsafe.printShow "matchPairList:\t" .-}
+#if MIN_VERSION_parallel(3,0,0)
+							 concat . Control.Parallel.Strategies.parMap Control.Parallel.Strategies.rseq	--Particularly effective when 'not ExecutionOptions.requireMatchList'.
+#else
+							 concatMap
+#endif
+							 (
+--								:: 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" #-} ListPlus.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 {-Unsafe.printShow ("Bypassing " ++ show (length maybeMatchPairList) ++ " repetitions; ")-} []	--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 (
+														repetitions - 1	--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)
+											) <$> 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 . ListPlus.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	= repetitions - 1	--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 <$> {-apply to Maybe Functor-} findMatchSlave (
+										{-Unsafe.printShow ("Expanded Alternatives for repetitions=" ++ show repetitions ++ ":\t") $-} expandedConcatenationPrefix ++ concatenationTail
+									) (
+										ConsumptionProfile.accumulateFrom tailConsumptionProfile {-initial value-} consumptionProfileExpandedConcatenationPrefix ++ tail accumulatedConsumptionProfilesTail
+									) (
+										{-Unsafe.printShow "MetaDataList:\t" $-} accumulateDistinctMetaDataFrom (head distinctMetaDataTail) {-initial value-} expandedConcatenationPrefix ++ tail distinctMetaDataTail
+									) inputData inputDataLength distinctInputData	--Recurse to get 'Maybe (MatchList a)'.
+								) {-. Unsafe.printShow ("Range for " ++ show concatenationFromAlternative ++ ":\t")-} $ if Repeatable.isPrecise repeatablePatternHead	--These are frequently generated by the previous recursion, as a trial expansion of an Alternative.
+									then if ExecutionOptions.validateMinConsumptionOfAlternatives executionOptions && maxDataAvailable < fewest * minConsumptionAlternatives
+										then {-Unsafe.printShow "Insufficient data:\t"-} []	--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" #-} {-Unsafe.printShow "fewestAlternatives:\t" $-} 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-} {-Unsafe.printShow "0/0 => fewestAlternatives:\t"-} fewest	--Repeat to meet the minimum requirement.
+														else {-unconsumable data-} maxBound	--Failure is inevitable.
+													else {-non-zero => can divide-} max fewest . succ {-account for expanded instance-} $ minDataAvailable' /+ maxConsumptionAlternatives
+
+										mostAlternatives	= {-#SCC "mostAlternatives" #-} {-Unsafe.printShow "mostAlternatives:\t" $-} case most of
+											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 $-} fewestAlternatives - 1	--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 maxDataAvailable - 1	--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'	-> {-Unsafe.printShow ("Reducing mostAlternatives=" ++ show mostAlternatives ++ "\t-> ") $-} mostAlternatives `min` (
+													length maximumDataBeforePegs' `div` minConsumptionAlternatives
+												 ) --Cap upper bound.
+												_				-> {-Unsafe.printShow "Peg match-failure:\t" $-} negate 1	--Guaranteed to be < 'fewestAlternatives'.
+											else {-no requirement for this optimisation-} mostAlternatives
+									in [fewestAlternatives .. mostAlternatives']	--The permissible repetition-range of any Alternative, constrained by the amount of data available, after subtracting fixed consumption-requirements.
+							 ) $ {-Unsafe.printShow "extendedRegExList:\t" .-} (
+								if ExecutionOptions.permitReorderingOfAlternatives executionOptions
+{-
+ The order in which 'Alternatives' are evaluated, should make no difference to the final result; unless 'ExecutionOptions.useFirstMatchAmongAlternatives'.
+ 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 {-Unsafe.printShow "Trying zero Alternatives:\t"-} zeroRepetitions	--Which might still fail, depending on 'tailMatch'.
+								else {-zero repetitions isn't permissible-} {-Unsafe.printShow "Alternatives-mismatch:\t"-} Nothing
+							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.
+									) . {-Unsafe.printShow "Ranked matchPairList:\t" .-} 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 . fromIntegral $ length matchLists :: Rational
+													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 [] :) <$> {-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, NFData m, Show 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 head <$> maybeMatchList,	--Record the first 'Match', consumed in the absence of a top-level 'Anchor.Bow'.
+	(
+		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 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, NFData m, Show m)
+	=> InputData m					-- ^ The input data within which to locate a match.
+	-> RegExOpts.RegExOpts (ExtendedRegEx m)	-- ^ The match-options parameterised by the regex against which to match the input data.
+	-> Bool
+inputData =~ regExOpts	= Data.Maybe.isJust $ fmap drift (RegExOpts.setVerbose False regExOpts) `findMatch` inputData
+
+-- | Pattern-mismatch operator.
+(/~) :: (Eq m, NFData m, Show m)
+	=> 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 :: 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
new file mode 100644
--- /dev/null
+++ b/src/RegExDot/RegExOpts.hs
@@ -0,0 +1,64 @@
+{-# 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
+	mkRegEx,
+	setVerbose
+) where
+
+import qualified	RegExDot.CompilationOptions	as CompilationOptions
+import qualified	RegExDot.ExecutionOptions	as ExecutionOptions
+import qualified	ToolShed.Defaultable		as 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 }
+
+-- | Build using 'Defaultable.defaultValue'.
+mkRegEx :: a -> RegExOpts a
+mkRegEx	r	= MkRegExOpts {
+	compilationOptions	= Defaultable.defaultValue,
+	executionOptions	= 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
new file mode 100644
--- /dev/null
+++ b/src/RegExDot/Repeatable.hs
@@ -0,0 +1,398 @@
+{-# LANGUAGE CPP #-}
+{-
+	Copyright (C) 2010 Dr. Alistair Ward
+
+	This program is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+{- |
+ [@AUTHOR@]	Dr. Alistair Ward
+
+ [@DESCRIPTION@]
+
+	* A 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.Applicative((<$>), (<*>))
+import			Control.Arrow((***))
+import			Text.ParserCombinators.Parsec((<?>))
+import qualified	Control.Monad
+import qualified	Data.List
+import qualified	RegExDot.Consumer		as Consumer
+import qualified	RegExDot.ConsumptionProfile	as ConsumptionProfile
+import qualified	Text.ParserCombinators.Parsec	as Parsec
+import qualified	ToolShed.SelfValidate		as SelfValidate
+
+#ifdef HAVE_DEEPSEQ
+import			Control.DeepSeq(NFData, rnf)
+#else
+import			Control.Parallel.Strategies(NFData, rnf)
+#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 GenParser-monad-} (oneOrMore b),
+		(Parsec.char zeroOrOneToken <?> "Repeatable.zeroOrOneToken " ++ show zeroOrOneToken)	>> return {-to GenParser-monad-} (zeroOrOne b),
+		(Parsec.char zeroOrMoreToken <?> "Repeatable.zeroOrMoreToken " ++ show zeroOrMoreToken)	>> return {-to GenParser-monad-} (zeroOrMore b),
+		(b ^#->#) {-arbitrarily greedy for now-} <$> uncurry Parsec.between (
+			Parsec.char *** Parsec.char $ rangeDelimiters
+		) (
+			do
+				fewest	<- Parsec.skipMany Parsec.space >> (read <$> Parsec.many1 Parsec.digit <?> "Repetition-range minimum")
+				most	<- Parsec.skipMany Parsec.space >> Parsec.option (
+					Just fewest	--The default.
+				 ) (
+					do
+						i	<- (
+							Parsec.char rangeSeparatorToken			<?> "Repeatable.rangeSeparatorToken " ++ show rangeSeparatorToken
+						 ) >> Parsec.skipMany Parsec.space >> Parsec.option Nothing {-default to open-ended range-} (
+							Just . read <$> Parsec.many1 Parsec.digit	<?> "Repetition-range maximum"
+						 )
+
+						Parsec.skipMany Parsec.space >> return {-to GenParser-monad-} i
+				 )
+
+				return {-to GenParser-monad-} (fewest, most)
+		) <?> "Repeatable.rangeDelimiters " ++ show rangeDelimiters
+	 ]
+
+	g	<- Parsec.option True {-the default-} $ (Parsec.char nonGreedyToken <?> "Repeatable.nonGreedyToken " ++ show nonGreedyToken) >> return {-to GenParser-monad-} False
+
+	return {-to GenParser-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 (Control.Monad.liftM2 (,) (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) $ (showChar *** 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 SelfValidate.SelfValidator a => SelfValidate.SelfValidator (Repeatable a)	where
+	isValid MkRepeatable {
+		base			= b,
+		repetitionBounds	= (fewest, most),
+		isGreedy		= g
+	} = and [
+		SelfValidate.isValid b,	--Delegate.
+		fewest >= 0,
+		case most of
+			Just m	-> m >= fewest	--Exactly zero instances is perverse, but legal.
+			_	-> True,
+		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.
+			_	-> True
+	 ]
+
+instance NFData a => NFData (Repeatable a)	where
+	rnf MkRepeatable {
+		base			= b,
+		repetitionBounds	= r,
+		isGreedy		= g
+	} = 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
new file mode 100644
--- /dev/null
+++ b/src/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/RegExDot/ShowablePredicate.hs b/src/RegExDot/ShowablePredicate.hs
new file mode 100644
--- /dev/null
+++ b/src/RegExDot/ShowablePredicate.hs
@@ -0,0 +1,58 @@
+{-# LANGUAGE CPP #-}
+{-
+	Copyright (C) 2010 Dr. Alistair Ward
+
+	This program is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+{- |
+ [@AUTHOR@]	Dr. Alistair Ward
+
+ [@DESCRIPTION@]	Used to implement /Perl-shortcut/s, /BracketExpression/-ranges & /POSIX Character-classes/.
+-}
+
+module RegExDot.ShowablePredicate (
+-- * Types
+	Predicate,
+-- ** Data-types
+	ShowablePredicate(
+		MkShowablePredicate,
+		name,
+		predicate
+	)
+) where
+
+#ifdef HAVE_DEEPSEQ
+import	Control.DeepSeq(NFData, rnf)
+#else
+import	Control.Parallel.Strategies(NFData, rnf)
+#endif
+
+-- | 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 NFData (ShowablePredicate a)	where
+	rnf	= rnf . name	--Ignore 'predicate'.
+
diff --git a/src/RegExDot/Span.hs b/src/RegExDot/Span.hs
new file mode 100644
--- /dev/null
+++ b/src/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/RegExDot/Tree.hs b/src/RegExDot/Tree.hs
new file mode 100644
--- /dev/null
+++ b/src/RegExDot/Tree.hs
@@ -0,0 +1,86 @@
+{-# LANGUAGE CPP #-}
+{-
+	Copyright (C) 2010 Dr. Alistair Ward
+
+	This program is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-}
+{- |
+ [@AUTHOR@]	Dr. Alistair Ward
+
+ [@DESCRIPTION@]
+
+	* Defines a specific type of tree-structure, which is composed from either a datum, or a list of Tree-lists.
+
+	* 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	Data.Foldable
+import qualified	Data.List
+import qualified	Data.Monoid
+
+#ifdef HAVE_DEEPSEQ
+import			Control.DeepSeq(NFData, rnf)
+#else
+import			Control.Parallel.Strategies(NFData, rnf)
+#endif
+
+-- | 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
+	readsPrec _ leaf		= Control.Arrow.first Leaf `map` reads leaf
+
+instance NFData a => NFData (Tree a)	where
+	rnf (Leaf a)	= rnf a
+	rnf (Node l)	= 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"
+
