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:
+
+    {project}  Copyright (C) {year}  {fullname}
+    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/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,43 @@
+# Harmony
+Harmony is a web service specification compiler that generates implementation (server and client) and tests.
+
+## Targets supported
+
++ Server
+  * Node.js (`-sjs`)
++ Client (and [Hypothesis](https://github.com/DRMacIver/hypothesis) based tests)
+  + Python (`-cpython`)
+
+## Usage
+
+After installing the package (`cabal install`), you will get the `harmony` executable. Afterwards:
+
+    Usage: harmony [OPTION...] input_file
+      -c[CLIENTS]     --client[=CLIENTS]         Desired output for the client
+      -s[SERVERS]     --server[=SERVERS]         Desired output for the server
+      -o[OUTPUT_DIR]  --output_dir[=OUTPUT_DIR]  Output path
+
+Check the [Targets supported](#targets-supported) section to figure out the code related to each target.
+## Syntax
+
+The input file should follow the syntax specified in `language_spec/Language.cf`. Example:
+
+    service_name: HouseworkService
+    service_version: 1.0.0
+
+    enum Color { RED, BLUE, BLACK }
+
+    struct Task {
+       // Primary key
+       @PK
+       name : String,
+       color : Color
+    }
+
+    struct Person {
+      name: String,
+      age: Int,
+      tasks: [Task]
+    }
+
+    resource Person ("/person")
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,19 @@
+#!/usr/bin/env runhaskell
+
+import Distribution.Simple
+import Distribution.Simple.Setup
+import Distribution.PackageDescription (HookedBuildInfo, emptyHookedBuildInfo)
+import System.Process (system)
+import System.Exit (ExitCode (..))
+import System.Environment (getArgs)
+
+main = defaultMainWithHooks $ simpleUserHooks { preConf = makeBnfc }
+
+-- Execute bnfc to compile the language specification (see language-spec/Language.cf) before 
+-- compiling.  
+makeBnfc :: Args -> ConfigFlags -> IO HookedBuildInfo
+makeBnfc _ _ = do 
+  bnfcOutput <- system "./make_bnfc.sh"
+  case bnfcOutput of
+       ExitSuccess -> return emptyHookedBuildInfo
+       (ExitFailure code) -> error $ "Error processing the language specification: " ++ show code
diff --git a/dist/build/Language/Lex.hs b/dist/build/Language/Lex.hs
new file mode 100644
--- /dev/null
+++ b/dist/build/Language/Lex.hs
@@ -0,0 +1,384 @@
+{-# LANGUAGE CPP,MagicHash #-}
+{-# LINE 3 "src/Language/Lex.x" #-}
+
+{-# OPTIONS -fno-warn-incomplete-patterns #-}
+{-# OPTIONS_GHC -w #-}
+module Language.Lex where
+
+
+
+import qualified Data.Bits
+import Data.Word (Word8)
+
+#if __GLASGOW_HASKELL__ >= 603
+#include "ghcconfig.h"
+#elif defined(__GLASGOW_HASKELL__)
+#include "config.h"
+#endif
+#if __GLASGOW_HASKELL__ >= 503
+import Data.Array
+import Data.Char (ord)
+import Data.Array.Base (unsafeAt)
+#else
+import Array
+import Char (ord)
+#endif
+#if __GLASGOW_HASKELL__ >= 503
+import GHC.Exts
+#else
+import GlaExts
+#endif
+alex_base :: AlexAddr
+alex_base = AlexA# "\xf8\xff\xff\xff\x5b\x00\x00\x00\xac\x00\x00\x00\x2c\x01\x00\x00\xac\x01\x00\x00\xd8\xff\xff\xff\xd7\xff\xff\xff\xac\x02\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x9d\x02\x00\x00\xe3\xff\xff\xff\x73\x03\x00\x00\x00\x00\x00\x00\xdf\x02\x00\x00\xf3\x03\x00\x00\x33\x04\x00\x00\x46\x00\x00\x00\xf3\x04\x00\x00\xb3\x04\x00\x00\x00\x00\x00\x00\xa9\x05\x00\x00\x00\x00\x00\x00\x77\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x06\x00\x00\xcb\x06\x00\x00"#
+
+alex_table :: AlexAddr
+alex_table = AlexA# "\x00\x00\x17\x00\x17\x00\x17\x00\x17\x00\x17\x00\x06\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x0b\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x18\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x01\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x18\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x18\x00\x00\x00\x18\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x19\x00\x17\x00\x17\x00\x17\x00\x17\x00\x17\x00\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x16\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x07\x00\x08\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x12\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x03\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x0e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x02\x00\x13\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x07\x00\x08\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x00\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x00\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x00\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x00\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x12\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x14\x00\x13\x00\x03\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0d\x00\x0e\x00\x04\x00\x09\x00\x09\x00\x09\x00\x0a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x00\x10\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#
+
+alex_check :: AlexAddr
+alex_check = AlexA# "\xff\xff\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x2e\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x2e\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\x22\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x28\x00\x29\x00\xff\xff\xff\xff\x2c\x00\xff\xff\xff\xff\x2f\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x40\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x5b\x00\xff\xff\x5d\x00\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\xff\xff\x7d\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x2a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x2f\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x20\x00\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc3\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x2a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x2f\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\xff\xff\xff\xff\xc3\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\x27\x00\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\x3b\x00\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x5b\x00\x5c\x00\x5d\x00\x5e\x00\x5f\x00\x60\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x2a\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\xff\xff\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xff\xff\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\xff\xff\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xff\xff\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x0c\x00\x0d\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00\x1a\x00\x1b\x00\x1c\x00\x1d\x00\x1e\x00\x1f\x00\x20\x00\x21\x00\x22\x00\x23\x00\x24\x00\x25\x00\x26\x00\x27\x00\x28\x00\x29\x00\x2a\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\x3a\x00\x3b\x00\x3c\x00\x3d\x00\x3e\x00\x3f\x00\x40\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\x5b\x00\x5c\x00\x5d\x00\x5e\x00\x5f\x00\x60\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\x7b\x00\x7c\x00\x7d\x00\x7e\x00\x7f\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x0a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x81\x00\x82\x00\x83\x00\x84\x00\x85\x00\x86\x00\x87\x00\x88\x00\x89\x00\x8a\x00\x8b\x00\x8c\x00\x8d\x00\x8e\x00\x8f\x00\x90\x00\x91\x00\x92\x00\x93\x00\x94\x00\x95\x00\x96\x00\x97\x00\x98\x00\x99\x00\x9a\x00\x9b\x00\x9c\x00\x9d\x00\x9e\x00\x9f\x00\xa0\x00\xa1\x00\xa2\x00\xa3\x00\xa4\x00\xa5\x00\xa6\x00\xa7\x00\xa8\x00\xa9\x00\xaa\x00\xab\x00\xac\x00\xad\x00\xae\x00\xaf\x00\xb0\x00\xb1\x00\xb2\x00\xb3\x00\xb4\x00\xb5\x00\xb6\x00\xb7\x00\xb8\x00\xb9\x00\xba\x00\xbb\x00\xbc\x00\xbd\x00\xbe\x00\xbf\x00\xc0\x00\xc1\x00\xc2\x00\xc3\x00\xc4\x00\xc5\x00\xc6\x00\xc7\x00\xc8\x00\xc9\x00\xca\x00\xcb\x00\xcc\x00\xcd\x00\xce\x00\xcf\x00\xd0\x00\xd1\x00\xd2\x00\xd3\x00\xd4\x00\xd5\x00\xd6\x00\xd7\x00\xd8\x00\xd9\x00\xda\x00\xdb\x00\xdc\x00\xdd\x00\xde\x00\xdf\x00\xe0\x00\xe1\x00\xe2\x00\xe3\x00\xe4\x00\xe5\x00\xe6\x00\xe7\x00\xe8\x00\xe9\x00\xea\x00\xeb\x00\xec\x00\xed\x00\xee\x00\xef\x00\xf0\x00\xf1\x00\xf2\x00\xf3\x00\xf4\x00\xf5\x00\xf6\x00\xf7\x00\xf8\x00\xf9\x00\xfa\x00\xfb\x00\xfc\x00\xfd\x00\xfe\x00\xff\x00\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x27\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00\x38\x00\x39\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x41\x00\x42\x00\x43\x00\x44\x00\x45\x00\x46\x00\x47\x00\x48\x00\x49\x00\x4a\x00\x4b\x00\x4c\x00\x4d\x00\x4e\x00\x4f\x00\x50\x00\x51\x00\x52\x00\x53\x00\x54\x00\x55\x00\x56\x00\x57\x00\x58\x00\x59\x00\x5a\x00\xff\xff\xff\xff\xff\xff\xff\xff\x5f\x00\xc3\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00\x6c\x00\x6d\x00\x6e\x00\x6f\x00\x70\x00\x71\x00\x72\x00\x73\x00\x74\x00\x75\x00\x76\x00\x77\x00\x78\x00\x79\x00\x7a\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc3\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"#
+
+alex_deflt :: AlexAddr
+alex_deflt = AlexA# "\xff\xff\xff\xff\x0c\x00\xff\xff\xff\xff\xff\xff\xff\xff\x0c\x00\x0c\x00\x0d\x00\x0d\x00\xff\xff\x0c\x00\x14\x00\x14\x00\xff\xff\xff\xff\xff\xff\x15\x00\x15\x00\x15\x00\x15\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"#
+
+alex_accept = listArray (0::Int,27) [AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccNone,AlexAccSkip,AlexAccSkip,AlexAccSkip,AlexAcc (alex_action_3),AlexAcc (alex_action_4),AlexAcc (alex_action_5),AlexAcc (alex_action_6)]
+{-# LINE 40 "src/Language/Lex.x" #-}
+
+
+tok :: (Posn -> String -> Token) -> (Posn -> String -> Token)
+tok f p s = f p s
+
+share :: String -> String
+share = id
+
+data Tok =
+   TS !String !Int    -- reserved words and symbols
+ | TL !String         -- string literals
+ | TI !String         -- integer literals
+ | TV !String         -- identifiers
+ | TD !String         -- double precision float literals
+ | TC !String         -- character literals
+ | T_VerIdent !String
+ | T_RouteIdent !String
+
+ deriving (Eq,Show,Ord)
+
+data Token =
+   PT  Posn Tok
+ | Err Posn
+  deriving (Eq,Show,Ord)
+
+tokenPos :: [Token] -> String
+tokenPos (PT (Pn _ l _) _ :_) = "line " ++ show l
+tokenPos (Err (Pn _ l _) :_) = "line " ++ show l
+tokenPos _ = "end of file"
+
+tokenPosn :: Token -> Posn
+tokenPosn (PT p _) = p
+tokenPosn (Err p) = p
+
+tokenLineCol :: Token -> (Int, Int)
+tokenLineCol = posLineCol . tokenPosn
+
+posLineCol :: Posn -> (Int, Int)
+posLineCol (Pn _ l c) = (l,c)
+
+mkPosToken :: Token -> ((Int, Int), String)
+mkPosToken t@(PT p _) = (posLineCol p, prToken t)
+
+prToken :: Token -> String
+prToken t = case t of
+  PT _ (TS s _) -> s
+  PT _ (TL s)   -> s
+  PT _ (TI s)   -> s
+  PT _ (TV s)   -> s
+  PT _ (TD s)   -> s
+  PT _ (TC s)   -> s
+  PT _ (T_VerIdent s) -> s
+  PT _ (T_RouteIdent s) -> s
+
+
+data BTree = N | B String Tok BTree BTree deriving (Show)
+
+eitherResIdent :: (String -> Tok) -> String -> Tok
+eitherResIdent tv s = treeFind resWords
+  where
+  treeFind N = tv s
+  treeFind (B a t left right) | s < a  = treeFind left
+                              | s > a  = treeFind right
+                              | s == a = t
+
+resWords :: BTree
+resWords = b "]" 12 (b "@" 6 (b ")" 3 (b "(" 2 (b "\"" 1 N N) N) (b ":" 5 (b "," 4 N N) N)) (b "Long" 9 (b "Int" 8 (b "Double" 7 N N) N) (b "[" 11 (b "String" 10 N N) N))) (b "service_name" 18 (b "read_only" 15 (b "modules" 14 (b "enum" 13 N N) N) (b "resource" 17 (b "require" 16 N N) N)) (b "{" 21 (b "struct" 20 (b "service_version" 19 N N) N) (b "}" 22 N N)))
+   where b s n = let bs = id s
+                  in B bs (TS bs n)
+
+unescapeInitTail :: String -> String
+unescapeInitTail = id . unesc . tail . id where
+  unesc s = case s of
+    '\\':c:cs | elem c ['\"', '\\', '\''] -> c : unesc cs
+    '\\':'n':cs  -> '\n' : unesc cs
+    '\\':'t':cs  -> '\t' : unesc cs
+    '"':[]    -> []
+    c:cs      -> c : unesc cs
+    _         -> []
+
+-------------------------------------------------------------------
+-- Alex wrapper code.
+-- A modified "posn" wrapper.
+-------------------------------------------------------------------
+
+data Posn = Pn !Int !Int !Int
+      deriving (Eq, Show,Ord)
+
+alexStartPos :: Posn
+alexStartPos = Pn 0 1 1
+
+alexMove :: Posn -> Char -> Posn
+alexMove (Pn a l c) '\t' = Pn (a+1)  l     (((c+7) `div` 8)*8+1)
+alexMove (Pn a l c) '\n' = Pn (a+1) (l+1)   1
+alexMove (Pn a l c) _    = Pn (a+1)  l     (c+1)
+
+type Byte = Word8
+
+type AlexInput = (Posn,     -- current position,
+                  Char,     -- previous char
+                  [Byte],   -- pending bytes on the current char
+                  String)   -- current input string
+
+tokens :: String -> [Token]
+tokens str = go (alexStartPos, '\n', [], str)
+    where
+      go :: AlexInput -> [Token]
+      go inp@(pos, _, _, str) =
+               case alexScan inp 0 of
+                AlexEOF                   -> []
+                AlexError (pos, _, _, _)  -> [Err pos]
+                AlexSkip  inp' len        -> go inp'
+                AlexToken inp' len act    -> act pos (take len str) : (go inp')
+
+alexGetByte :: AlexInput -> Maybe (Byte,AlexInput)
+alexGetByte (p, c, (b:bs), s) = Just (b, (p, c, bs, s))
+alexGetByte (p, _, [], s) =
+  case  s of
+    []  -> Nothing
+    (c:s) ->
+             let p'     = alexMove p c
+                 (b:bs) = utf8Encode c
+              in p' `seq` Just (b, (p', c, bs, s))
+
+alexInputPrevChar :: AlexInput -> Char
+alexInputPrevChar (p, c, bs, s) = c
+
+-- | Encode a Haskell String to a list of Word8 values, in UTF8 format.
+utf8Encode :: Char -> [Word8]
+utf8Encode = map fromIntegral . go . ord
+ where
+  go oc
+   | oc <= 0x7f       = [oc]
+
+   | oc <= 0x7ff      = [ 0xc0 + (oc `Data.Bits.shiftR` 6)
+                        , 0x80 + oc Data.Bits..&. 0x3f
+                        ]
+
+   | oc <= 0xffff     = [ 0xe0 + (oc `Data.Bits.shiftR` 12)
+                        , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)
+                        , 0x80 + oc Data.Bits..&. 0x3f
+                        ]
+   | otherwise        = [ 0xf0 + (oc `Data.Bits.shiftR` 18)
+                        , 0x80 + ((oc `Data.Bits.shiftR` 12) Data.Bits..&. 0x3f)
+                        , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)
+                        , 0x80 + oc Data.Bits..&. 0x3f
+                        ]
+
+alex_action_3 =  tok (\p s -> PT p (eitherResIdent (TV . share) s)) 
+alex_action_4 =  tok (\p s -> PT p (eitherResIdent (T_VerIdent . share) s)) 
+alex_action_5 =  tok (\p s -> PT p (eitherResIdent (T_RouteIdent . share) s)) 
+alex_action_6 =  tok (\p s -> PT p (eitherResIdent (TV . share) s)) 
+{-# LINE 1 "templates/GenericTemplate.hs" #-}
+{-# LINE 1 "templates/GenericTemplate.hs" #-}
+{-# LINE 1 "<built-in>" #-}
+{-# LINE 1 "templates/GenericTemplate.hs" #-}
+-- -----------------------------------------------------------------------------
+-- ALEX TEMPLATE
+--
+-- This code is in the PUBLIC DOMAIN; you may copy it freely and use
+-- it for any purpose whatsoever.
+
+-- -----------------------------------------------------------------------------
+-- INTERNALS and main scanner engine
+
+
+{-# LINE 21 "templates/GenericTemplate.hs" #-}
+
+
+
+
+
+-- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.
+#if __GLASGOW_HASKELL__ > 706
+#define GTE(n,m) (tagToEnum# (n >=# m))
+#define EQ(n,m) (tagToEnum# (n ==# m))
+#else
+#define GTE(n,m) (n >=# m)
+#define EQ(n,m) (n ==# m)
+#endif
+
+{-# LINE 51 "templates/GenericTemplate.hs" #-}
+
+
+data AlexAddr = AlexA# Addr#
+-- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.
+#if __GLASGOW_HASKELL__ < 503
+uncheckedShiftL# = shiftL#
+#endif
+
+{-# INLINE alexIndexInt16OffAddr #-}
+alexIndexInt16OffAddr (AlexA# arr) off =
+#ifdef WORDS_BIGENDIAN
+  narrow16Int# i
+  where
+        i    = word2Int# ((high `uncheckedShiftL#` 8#) `or#` low)
+        high = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#)))
+        low  = int2Word# (ord# (indexCharOffAddr# arr off'))
+        off' = off *# 2#
+#else
+  indexInt16OffAddr# arr off
+#endif
+
+
+
+
+
+{-# INLINE alexIndexInt32OffAddr #-}
+alexIndexInt32OffAddr (AlexA# arr) off = 
+#ifdef WORDS_BIGENDIAN
+  narrow32Int# i
+  where
+   i    = word2Int# ((b3 `uncheckedShiftL#` 24#) `or#`
+		     (b2 `uncheckedShiftL#` 16#) `or#`
+		     (b1 `uncheckedShiftL#` 8#) `or#` b0)
+   b3   = int2Word# (ord# (indexCharOffAddr# arr (off' +# 3#)))
+   b2   = int2Word# (ord# (indexCharOffAddr# arr (off' +# 2#)))
+   b1   = int2Word# (ord# (indexCharOffAddr# arr (off' +# 1#)))
+   b0   = int2Word# (ord# (indexCharOffAddr# arr off'))
+   off' = off *# 4#
+#else
+  indexInt32OffAddr# arr off
+#endif
+
+
+
+
+
+
+#if __GLASGOW_HASKELL__ < 503
+quickIndex arr i = arr ! i
+#else
+-- GHC >= 503, unsafeAt is available from Data.Array.Base.
+quickIndex = unsafeAt
+#endif
+
+
+
+
+-- -----------------------------------------------------------------------------
+-- Main lexing routines
+
+data AlexReturn a
+  = AlexEOF
+  | AlexError  !AlexInput
+  | AlexSkip   !AlexInput !Int
+  | AlexToken  !AlexInput !Int a
+
+-- alexScan :: AlexInput -> StartCode -> AlexReturn a
+alexScan input (I# (sc))
+  = alexScanUser undefined input (I# (sc))
+
+alexScanUser user input (I# (sc))
+  = case alex_scan_tkn user input 0# input sc AlexNone of
+	(AlexNone, input') ->
+		case alexGetByte input of
+			Nothing -> 
+
+
+
+				   AlexEOF
+			Just _ ->
+
+
+
+				   AlexError input'
+
+	(AlexLastSkip input'' len, _) ->
+
+
+
+		AlexSkip input'' len
+
+	(AlexLastAcc k input''' len, _) ->
+
+
+
+		AlexToken input''' len k
+
+
+-- Push the input through the DFA, remembering the most recent accepting
+-- state it encountered.
+
+alex_scan_tkn user orig_input len input s last_acc =
+  input `seq` -- strict in the input
+  let 
+	new_acc = (check_accs (alex_accept `quickIndex` (I# (s))))
+  in
+  new_acc `seq`
+  case alexGetByte input of
+     Nothing -> (new_acc, input)
+     Just (c, new_input) -> 
+
+
+
+      case fromIntegral c of { (I# (ord_c)) ->
+        let
+                base   = alexIndexInt32OffAddr alex_base s
+                offset = (base +# ord_c)
+                check  = alexIndexInt16OffAddr alex_check offset
+		
+                new_s = if GTE(offset,0#) && EQ(check,ord_c)
+			  then alexIndexInt16OffAddr alex_table offset
+			  else alexIndexInt16OffAddr alex_deflt s
+	in
+        case new_s of
+	    -1# -> (new_acc, input)
+		-- on an error, we want to keep the input *before* the
+		-- character that failed, not after.
+    	    _ -> alex_scan_tkn user orig_input (if c < 0x80 || c >= 0xC0 then (len +# 1#) else len)
+                                                -- note that the length is increased ONLY if this is the 1st byte in a char encoding)
+			new_input new_s new_acc
+      }
+  where
+	check_accs (AlexAccNone) = last_acc
+	check_accs (AlexAcc a  ) = AlexLastAcc a input (I# (len))
+	check_accs (AlexAccSkip) = AlexLastSkip  input (I# (len))
+
+{-# LINE 198 "templates/GenericTemplate.hs" #-}
+
+data AlexLastAcc a
+  = AlexNone
+  | AlexLastAcc a !AlexInput !Int
+  | AlexLastSkip  !AlexInput !Int
+
+instance Functor AlexLastAcc where
+    fmap f AlexNone = AlexNone
+    fmap f (AlexLastAcc x y z) = AlexLastAcc (f x) y z
+    fmap f (AlexLastSkip x y) = AlexLastSkip x y
+
+data AlexAcc a user
+  = AlexAccNone
+  | AlexAcc a
+  | AlexAccSkip
+
+{-# LINE 242 "templates/GenericTemplate.hs" #-}
+
+-- used by wrappers
+iUnbox (I# (i)) = i
+
diff --git a/dist/build/Language/Par.hs b/dist/build/Language/Par.hs
new file mode 100644
--- /dev/null
+++ b/dist/build/Language/Par.hs
@@ -0,0 +1,931 @@
+{-# OPTIONS_GHC -w #-}
+{-# OPTIONS -fglasgow-exts -cpp #-}
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns -fno-warn-overlapping-patterns #-}
+module Language.Par where
+import Language.Abs
+import Language.Lex
+import Language.ErrM
+import qualified Data.Array as Happy_Data_Array
+import qualified GHC.Exts as Happy_GHC_Exts
+import Control.Applicative(Applicative(..))
+import Control.Monad (ap)
+
+-- parser produced by Happy Version 1.19.5
+
+newtype HappyAbsSyn  = HappyAbsSyn HappyAny
+#if __GLASGOW_HASKELL__ >= 607
+type HappyAny = Happy_GHC_Exts.Any
+#else
+type HappyAny = forall a . a
+#endif
+happyIn22 :: (Ident) -> (HappyAbsSyn )
+happyIn22 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn22 #-}
+happyOut22 :: (HappyAbsSyn ) -> (Ident)
+happyOut22 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut22 #-}
+happyIn23 :: (VerIdent) -> (HappyAbsSyn )
+happyIn23 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn23 #-}
+happyOut23 :: (HappyAbsSyn ) -> (VerIdent)
+happyOut23 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut23 #-}
+happyIn24 :: (RouteIdent) -> (HappyAbsSyn )
+happyIn24 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn24 #-}
+happyOut24 :: (HappyAbsSyn ) -> (RouteIdent)
+happyOut24 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut24 #-}
+happyIn25 :: (Specification) -> (HappyAbsSyn )
+happyIn25 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn25 #-}
+happyOut25 :: (HappyAbsSyn ) -> (Specification)
+happyOut25 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut25 #-}
+happyIn26 :: (Name) -> (HappyAbsSyn )
+happyIn26 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn26 #-}
+happyOut26 :: (HappyAbsSyn ) -> (Name)
+happyOut26 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut26 #-}
+happyIn27 :: (Version) -> (HappyAbsSyn )
+happyIn27 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn27 #-}
+happyOut27 :: (HappyAbsSyn ) -> (Version)
+happyOut27 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut27 #-}
+happyIn28 :: (Modules) -> (HappyAbsSyn )
+happyIn28 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn28 #-}
+happyOut28 :: (HappyAbsSyn ) -> (Modules)
+happyOut28 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut28 #-}
+happyIn29 :: (EnumType) -> (HappyAbsSyn )
+happyIn29 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn29 #-}
+happyOut29 :: (HappyAbsSyn ) -> (EnumType)
+happyOut29 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut29 #-}
+happyIn30 :: (StructType) -> (HappyAbsSyn )
+happyIn30 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn30 #-}
+happyOut30 :: (HappyAbsSyn ) -> (StructType)
+happyOut30 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut30 #-}
+happyIn31 :: (Resource) -> (HappyAbsSyn )
+happyIn31 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn31 #-}
+happyOut31 :: (HappyAbsSyn ) -> (Resource)
+happyOut31 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut31 #-}
+happyIn32 :: (Mode) -> (HappyAbsSyn )
+happyIn32 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn32 #-}
+happyOut32 :: (HappyAbsSyn ) -> (Mode)
+happyOut32 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut32 #-}
+happyIn33 :: (Field) -> (HappyAbsSyn )
+happyIn33 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn33 #-}
+happyOut33 :: (HappyAbsSyn ) -> (Field)
+happyOut33 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut33 #-}
+happyIn34 :: (FType) -> (HappyAbsSyn )
+happyIn34 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn34 #-}
+happyOut34 :: (HappyAbsSyn ) -> (FType)
+happyOut34 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut34 #-}
+happyIn35 :: (Annotation) -> (HappyAbsSyn )
+happyIn35 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn35 #-}
+happyOut35 :: (HappyAbsSyn ) -> (Annotation)
+happyOut35 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut35 #-}
+happyIn36 :: (EnumVal) -> (HappyAbsSyn )
+happyIn36 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn36 #-}
+happyOut36 :: (HappyAbsSyn ) -> (EnumVal)
+happyOut36 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut36 #-}
+happyIn37 :: ([EnumType]) -> (HappyAbsSyn )
+happyIn37 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn37 #-}
+happyOut37 :: (HappyAbsSyn ) -> ([EnumType])
+happyOut37 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut37 #-}
+happyIn38 :: ([Field]) -> (HappyAbsSyn )
+happyIn38 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn38 #-}
+happyOut38 :: (HappyAbsSyn ) -> ([Field])
+happyOut38 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut38 #-}
+happyIn39 :: ([StructType]) -> (HappyAbsSyn )
+happyIn39 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn39 #-}
+happyOut39 :: (HappyAbsSyn ) -> ([StructType])
+happyOut39 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut39 #-}
+happyIn40 :: ([Resource]) -> (HappyAbsSyn )
+happyIn40 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn40 #-}
+happyOut40 :: (HappyAbsSyn ) -> ([Resource])
+happyOut40 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut40 #-}
+happyIn41 :: ([EnumVal]) -> (HappyAbsSyn )
+happyIn41 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn41 #-}
+happyOut41 :: (HappyAbsSyn ) -> ([EnumVal])
+happyOut41 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut41 #-}
+happyIn42 :: ([Annotation]) -> (HappyAbsSyn )
+happyIn42 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn42 #-}
+happyOut42 :: (HappyAbsSyn ) -> ([Annotation])
+happyOut42 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut42 #-}
+happyIn43 :: ([Ident]) -> (HappyAbsSyn )
+happyIn43 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyIn43 #-}
+happyOut43 :: (HappyAbsSyn ) -> ([Ident])
+happyOut43 x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOut43 #-}
+happyInTok :: (Token) -> (HappyAbsSyn )
+happyInTok x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyInTok #-}
+happyOutTok :: (HappyAbsSyn ) -> (Token)
+happyOutTok x = Happy_GHC_Exts.unsafeCoerce# x
+{-# INLINE happyOutTok #-}
+
+
+happyActOffsets :: HappyAddr
+happyActOffsets = HappyA# "\x86\x00\x86\x00\x87\x00\x89\x00\x8a\x00\x81\x00\x85\x00\x84\x00\x00\x00\x08\x00\x88\x00\x7d\x00\x00\x00\x00\x00\x7b\x00\x7c\x00\x7a\x00\x00\x00\x7a\x00\x7a\x00\x00\x00\x7a\x00\x78\x00\xff\xff\x00\x00\x77\x00\x76\x00\x74\x00\x72\x00\x73\x00\x75\x00\x71\x00\x70\x00\x6f\x00\x6e\x00\x06\x00\x16\x00\x6e\x00\x6e\x00\x6d\x00\x00\x00\x6c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x6c\x00\x6c\x00\x00\x00\x6c\x00\x6c\x00\x6c\x00\x6b\x00\x69\x00\x6a\x00\x66\x00\x68\x00\x65\x00\x67\x00\x44\x00\x64\x00\x62\x00\x63\x00\x61\x00\x60\x00\x5f\x00\x5a\x00\x00\x00\x00\x00\x5d\x00\x00\x00\x00\x00\x5b\x00\x00\x00\x5e\x00\x00\x00\x58\x00\x00\x00\x00\x00\x5c\x00\x00\x00\x00\x00\x08\x00\x00\x00\x57\x00\x57\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf7\xff\x55\x00\x54\x00\x00\x00\x46\x00\x42\x00\x59\x00\x00\x00\x00\x00\x00\x00\x00\x00\x52\x00\x00\x00\x56\x00\x50\x00\x00\x00\x00\x00"#
+
+happyGotoOffsets :: HappyAddr
+happyGotoOffsets = HappyA# "\x05\x00\x4f\x00\x53\x00\x51\x00\x4d\x00\x4e\x00\x4c\x00\x48\x00\x3d\x00\x27\x00\x43\x00\x14\x00\x3f\x00\x2c\x00\x3c\x00\x3a\x00\x0e\x00\x3b\x00\x03\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x34\x00\x00\x00\x4b\x00\x31\x00\x00\x00\x4a\x00\x00\x00\x00\x00\x1e\x00\x33\x00\x00\x00\x00\x00\x49\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x26\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x47\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x29\x00\x22\x00\x45\x00\x2e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x25\x00\x00\x00\x07\x00\x01\x00\x00\x00\x00\x00\x00\x00\xfb\xff\x2d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x28\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2f\x00\x00\x00\x00\x00\xfc\xff\x00\x00\x00\x00"#
+
+happyDefActions :: HappyAddr
+happyDefActions = HappyA# "\x00\x00\x00\x00\x00\x00\xe6\xff\x00\x00\x00\x00\x00\x00\xe0\xff\xcc\xff\x00\x00\x00\x00\x00\x00\xd6\xff\xcc\xff\x00\x00\x00\x00\x00\x00\xcc\xff\x00\x00\x00\x00\xec\xff\xca\xff\x00\x00\x00\x00\xd7\xff\xce\xff\x00\x00\xd0\xff\x00\x00\x00\x00\xd2\xff\x00\x00\x00\x00\xd4\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xda\xff\x00\x00\xdb\xff\xdd\xff\xdc\xff\xde\xff\x00\x00\x00\x00\x00\x00\xe1\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe6\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd8\xff\xd5\xff\x00\x00\xcb\xff\xcc\xff\x00\x00\xd1\xff\x00\x00\xcf\xff\x00\x00\xc9\xff\xcd\xff\x00\x00\xcc\xff\xd3\xff\x00\x00\xd9\xff\x00\x00\x00\x00\xe7\xff\xeb\xff\xe8\xff\xd6\xff\x00\x00\x00\x00\x00\x00\xdf\xff\x00\x00\x00\x00\x00\x00\xea\xff\xe3\xff\xe4\xff\xe5\xff\x00\x00\xe9\xff\x00\x00\xe0\xff\xe2\xff"#
+
+happyCheck :: HappyAddr
+happyCheck = HappyA# "\xff\xff\x00\x00\x00\x00\x00\x00\x0d\x00\x06\x00\x0a\x00\x00\x00\x03\x00\x04\x00\x0f\x00\x14\x00\x06\x00\x00\x00\x00\x00\x07\x00\x08\x00\x09\x00\x0a\x00\x0b\x00\x00\x00\x0e\x00\x15\x00\x15\x00\x15\x00\x1a\x00\x13\x00\x0e\x00\x0e\x00\x17\x00\x00\x00\x17\x00\x13\x00\x13\x00\x0e\x00\x0d\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x06\x00\x10\x00\x02\x00\x0d\x00\x0d\x00\x14\x00\x05\x00\x01\x00\x1a\x00\x0c\x00\x0c\x00\x0c\x00\x07\x00\x08\x00\x0b\x00\x0b\x00\x09\x00\x08\x00\x07\x00\x10\x00\x10\x00\x09\x00\x11\x00\x14\x00\x14\x00\x12\x00\x11\x00\x09\x00\x08\x00\x00\x00\x12\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x12\x00\x11\x00\x0f\x00\x14\x00\x0d\x00\x14\x00\x0a\x00\x04\x00\x07\x00\x09\x00\x08\x00\x06\x00\x05\x00\x03\x00\x01\x00\x19\x00\x16\x00\x01\x00\x1a\x00\x0f\x00\x02\x00\x0c\x00\x05\x00\x11\x00\xff\xff\xff\xff\x0c\x00\xff\xff\xff\xff\xff\xff\x16\x00\x0b\x00\x05\x00\x05\x00\x17\x00\x17\x00\x15\x00\xff\xff\x10\x00\x04\x00\x15\x00\xff\xff\xff\xff\x13\x00\x0e\x00\x18\x00\x17\x00\x04\x00\xff\xff\xff\xff\xff\xff\x1a\x00\x1a\x00\xff\xff\x17\x00\x1a\x00\x17\x00\x11\x00\x1a\x00\x17\x00\x1a\x00\x14\x00\x17\x00\x1a\x00\x1a\x00\x11\x00\x06\x00\x14\x00\x1a\x00\x17\x00\x1a\x00\x0f\x00\x17\x00\x14\x00\x11\x00\x0d\x00\x12\x00\x10\x00\x13\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"#
+
+happyTable :: HappyAddr
+happyTable = HappyA# "\x00\x00\x15\x00\x15\x00\x15\x00\x36\x00\x28\x00\x6a\x00\x18\x00\x3c\x00\x3d\x00\x5b\x00\x21\x00\x28\x00\x18\x00\x18\x00\x2b\x00\x2c\x00\x2d\x00\x2e\x00\x2f\x00\x18\x00\x19\x00\x5c\x00\x4e\x00\x16\x00\xff\xff\x5d\x00\x19\x00\x19\x00\x15\x00\x46\x00\x15\x00\x4f\x00\x1a\x00\x25\x00\x36\x00\x21\x00\x28\x00\x28\x00\x28\x00\x5a\x00\x5f\x00\x61\x00\x47\x00\x47\x00\x23\x00\x3e\x00\x57\x00\xff\xff\x5e\x00\x43\x00\x29\x00\x45\x00\x1e\x00\x21\x00\x21\x00\x1b\x00\x1e\x00\x45\x00\x52\x00\x22\x00\x1b\x00\x66\x00\x23\x00\x23\x00\x67\x00\x4a\x00\x1b\x00\x1e\x00\x59\x00\x4c\x00\x42\x00\x2f\x00\x44\x00\x49\x00\x4b\x00\x1c\x00\x1f\x00\x24\x00\x17\x00\x26\x00\x23\x00\x30\x00\x3a\x00\x34\x00\x32\x00\x33\x00\x36\x00\x38\x00\x6a\x00\x69\x00\x63\x00\x64\x00\x61\x00\xff\xff\x32\x00\x51\x00\x66\x00\x54\x00\x1e\x00\x00\x00\x00\x00\x55\x00\x00\x00\x00\x00\x00\x00\x65\x00\x57\x00\x40\x00\x41\x00\x15\x00\x15\x00\x52\x00\x00\x00\x38\x00\x49\x00\x56\x00\x00\x00\x00\x00\x3a\x00\x42\x00\x59\x00\x15\x00\x4e\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x15\x00\xff\xff\x15\x00\x1e\x00\xff\xff\x15\x00\xff\xff\x21\x00\x15\x00\xff\xff\xff\xff\x1e\x00\x28\x00\x21\x00\xff\xff\x15\x00\xff\xff\x32\x00\x15\x00\x21\x00\x1e\x00\x36\x00\x3c\x00\x38\x00\x3a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"#
+
+happyReduceArr = Happy_Data_Array.array (19, 54) [
+	(19 , happyReduce_19),
+	(20 , happyReduce_20),
+	(21 , happyReduce_21),
+	(22 , happyReduce_22),
+	(23 , happyReduce_23),
+	(24 , happyReduce_24),
+	(25 , happyReduce_25),
+	(26 , happyReduce_26),
+	(27 , happyReduce_27),
+	(28 , happyReduce_28),
+	(29 , happyReduce_29),
+	(30 , happyReduce_30),
+	(31 , happyReduce_31),
+	(32 , happyReduce_32),
+	(33 , happyReduce_33),
+	(34 , happyReduce_34),
+	(35 , happyReduce_35),
+	(36 , happyReduce_36),
+	(37 , happyReduce_37),
+	(38 , happyReduce_38),
+	(39 , happyReduce_39),
+	(40 , happyReduce_40),
+	(41 , happyReduce_41),
+	(42 , happyReduce_42),
+	(43 , happyReduce_43),
+	(44 , happyReduce_44),
+	(45 , happyReduce_45),
+	(46 , happyReduce_46),
+	(47 , happyReduce_47),
+	(48 , happyReduce_48),
+	(49 , happyReduce_49),
+	(50 , happyReduce_50),
+	(51 , happyReduce_51),
+	(52 , happyReduce_52),
+	(53 , happyReduce_53),
+	(54 , happyReduce_54)
+	]
+
+happy_n_terms = 27 :: Int
+happy_n_nonterms = 22 :: Int
+
+happyReduce_19 = happySpecReduce_1  0# happyReduction_19
+happyReduction_19 happy_x_1
+	 =  case happyOutTok happy_x_1 of { (PT _ (TV happy_var_1)) -> 
+	happyIn22
+		 (Ident happy_var_1
+	)}
+
+happyReduce_20 = happySpecReduce_1  1# happyReduction_20
+happyReduction_20 happy_x_1
+	 =  case happyOutTok happy_x_1 of { (PT _ (T_VerIdent happy_var_1)) -> 
+	happyIn23
+		 (VerIdent (happy_var_1)
+	)}
+
+happyReduce_21 = happySpecReduce_1  2# happyReduction_21
+happyReduction_21 happy_x_1
+	 =  case happyOutTok happy_x_1 of { (PT _ (T_RouteIdent happy_var_1)) -> 
+	happyIn24
+		 (RouteIdent (happy_var_1)
+	)}
+
+happyReduce_22 = happyReduce 6# 3# happyReduction_22
+happyReduction_22 (happy_x_6 `HappyStk`
+	happy_x_5 `HappyStk`
+	happy_x_4 `HappyStk`
+	happy_x_3 `HappyStk`
+	happy_x_2 `HappyStk`
+	happy_x_1 `HappyStk`
+	happyRest)
+	 = case happyOut26 happy_x_1 of { happy_var_1 -> 
+	case happyOut27 happy_x_2 of { happy_var_2 -> 
+	case happyOut28 happy_x_3 of { happy_var_3 -> 
+	case happyOut37 happy_x_4 of { happy_var_4 -> 
+	case happyOut39 happy_x_5 of { happy_var_5 -> 
+	case happyOut40 happy_x_6 of { happy_var_6 -> 
+	happyIn25
+		 (Spec happy_var_1 happy_var_2 happy_var_3 (reverse happy_var_4) happy_var_5 happy_var_6
+	) `HappyStk` happyRest}}}}}}
+
+happyReduce_23 = happySpecReduce_3  4# happyReduction_23
+happyReduction_23 happy_x_3
+	happy_x_2
+	happy_x_1
+	 =  case happyOut22 happy_x_3 of { happy_var_3 -> 
+	happyIn26
+		 (Nm happy_var_3
+	)}
+
+happyReduce_24 = happySpecReduce_3  5# happyReduction_24
+happyReduction_24 happy_x_3
+	happy_x_2
+	happy_x_1
+	 =  case happyOut23 happy_x_3 of { happy_var_3 -> 
+	happyIn27
+		 (Ver happy_var_3
+	)}
+
+happyReduce_25 = happySpecReduce_0  6# happyReduction_25
+happyReduction_25  =  happyIn28
+		 (EmptyMods
+	)
+
+happyReduce_26 = happyReduce 5# 6# happyReduction_26
+happyReduction_26 (happy_x_5 `HappyStk`
+	happy_x_4 `HappyStk`
+	happy_x_3 `HappyStk`
+	happy_x_2 `HappyStk`
+	happy_x_1 `HappyStk`
+	happyRest)
+	 = case happyOut43 happy_x_4 of { happy_var_4 -> 
+	happyIn28
+		 (Mods happy_var_4
+	) `HappyStk` happyRest}
+
+happyReduce_27 = happyReduce 5# 7# happyReduction_27
+happyReduction_27 (happy_x_5 `HappyStk`
+	happy_x_4 `HappyStk`
+	happy_x_3 `HappyStk`
+	happy_x_2 `HappyStk`
+	happy_x_1 `HappyStk`
+	happyRest)
+	 = case happyOut22 happy_x_2 of { happy_var_2 -> 
+	case happyOut41 happy_x_4 of { happy_var_4 -> 
+	happyIn29
+		 (DefEnum happy_var_2 happy_var_4
+	) `HappyStk` happyRest}}
+
+happyReduce_28 = happyReduce 5# 8# happyReduction_28
+happyReduction_28 (happy_x_5 `HappyStk`
+	happy_x_4 `HappyStk`
+	happy_x_3 `HappyStk`
+	happy_x_2 `HappyStk`
+	happy_x_1 `HappyStk`
+	happyRest)
+	 = case happyOut22 happy_x_2 of { happy_var_2 -> 
+	case happyOut38 happy_x_4 of { happy_var_4 -> 
+	happyIn30
+		 (DefStr happy_var_2 happy_var_4
+	) `HappyStk` happyRest}}
+
+happyReduce_29 = happyReduce 8# 9# happyReduction_29
+happyReduction_29 (happy_x_8 `HappyStk`
+	happy_x_7 `HappyStk`
+	happy_x_6 `HappyStk`
+	happy_x_5 `HappyStk`
+	happy_x_4 `HappyStk`
+	happy_x_3 `HappyStk`
+	happy_x_2 `HappyStk`
+	happy_x_1 `HappyStk`
+	happyRest)
+	 = case happyOut22 happy_x_2 of { happy_var_2 -> 
+	case happyOut24 happy_x_5 of { happy_var_5 -> 
+	case happyOut32 happy_x_8 of { happy_var_8 -> 
+	happyIn31
+		 (Res happy_var_2 happy_var_5 happy_var_8
+	) `HappyStk` happyRest}}}
+
+happyReduce_30 = happySpecReduce_1  10# happyReduction_30
+happyReduction_30 happy_x_1
+	 =  happyIn32
+		 (ReadOnly
+	)
+
+happyReduce_31 = happySpecReduce_0  10# happyReduction_31
+happyReduction_31  =  happyIn32
+		 (Write
+	)
+
+happyReduce_32 = happyReduce 4# 11# happyReduction_32
+happyReduction_32 (happy_x_4 `HappyStk`
+	happy_x_3 `HappyStk`
+	happy_x_2 `HappyStk`
+	happy_x_1 `HappyStk`
+	happyRest)
+	 = case happyOut42 happy_x_1 of { happy_var_1 -> 
+	case happyOut22 happy_x_2 of { happy_var_2 -> 
+	case happyOut34 happy_x_4 of { happy_var_4 -> 
+	happyIn33
+		 (FDef (reverse happy_var_1) happy_var_2 happy_var_4
+	) `HappyStk` happyRest}}}
+
+happyReduce_33 = happySpecReduce_1  12# happyReduction_33
+happyReduction_33 happy_x_1
+	 =  happyIn34
+		 (FString
+	)
+
+happyReduce_34 = happySpecReduce_1  12# happyReduction_34
+happyReduction_34 happy_x_1
+	 =  happyIn34
+		 (FInt
+	)
+
+happyReduce_35 = happySpecReduce_1  12# happyReduction_35
+happyReduction_35 happy_x_1
+	 =  happyIn34
+		 (FLong
+	)
+
+happyReduce_36 = happySpecReduce_1  12# happyReduction_36
+happyReduction_36 happy_x_1
+	 =  happyIn34
+		 (FDouble
+	)
+
+happyReduce_37 = happySpecReduce_1  12# happyReduction_37
+happyReduction_37 happy_x_1
+	 =  case happyOut22 happy_x_1 of { happy_var_1 -> 
+	happyIn34
+		 (FDefined happy_var_1
+	)}
+
+happyReduce_38 = happySpecReduce_3  12# happyReduction_38
+happyReduction_38 happy_x_3
+	happy_x_2
+	happy_x_1
+	 =  case happyOut34 happy_x_2 of { happy_var_2 -> 
+	happyIn34
+		 (FList happy_var_2
+	)}
+
+happyReduce_39 = happySpecReduce_2  13# happyReduction_39
+happyReduction_39 happy_x_2
+	happy_x_1
+	 =  case happyOut22 happy_x_2 of { happy_var_2 -> 
+	happyIn35
+		 (Ann happy_var_2
+	)}
+
+happyReduce_40 = happySpecReduce_1  14# happyReduction_40
+happyReduction_40 happy_x_1
+	 =  case happyOut22 happy_x_1 of { happy_var_1 -> 
+	happyIn36
+		 (EnVal happy_var_1
+	)}
+
+happyReduce_41 = happySpecReduce_0  15# happyReduction_41
+happyReduction_41  =  happyIn37
+		 ([]
+	)
+
+happyReduce_42 = happySpecReduce_2  15# happyReduction_42
+happyReduction_42 happy_x_2
+	happy_x_1
+	 =  case happyOut37 happy_x_1 of { happy_var_1 -> 
+	case happyOut29 happy_x_2 of { happy_var_2 -> 
+	happyIn37
+		 (flip (:) happy_var_1 happy_var_2
+	)}}
+
+happyReduce_43 = happySpecReduce_1  16# happyReduction_43
+happyReduction_43 happy_x_1
+	 =  case happyOut33 happy_x_1 of { happy_var_1 -> 
+	happyIn38
+		 ((:[]) happy_var_1
+	)}
+
+happyReduce_44 = happySpecReduce_3  16# happyReduction_44
+happyReduction_44 happy_x_3
+	happy_x_2
+	happy_x_1
+	 =  case happyOut33 happy_x_1 of { happy_var_1 -> 
+	case happyOut38 happy_x_3 of { happy_var_3 -> 
+	happyIn38
+		 ((:) happy_var_1 happy_var_3
+	)}}
+
+happyReduce_45 = happySpecReduce_1  17# happyReduction_45
+happyReduction_45 happy_x_1
+	 =  case happyOut30 happy_x_1 of { happy_var_1 -> 
+	happyIn39
+		 ((:[]) happy_var_1
+	)}
+
+happyReduce_46 = happySpecReduce_2  17# happyReduction_46
+happyReduction_46 happy_x_2
+	happy_x_1
+	 =  case happyOut30 happy_x_1 of { happy_var_1 -> 
+	case happyOut39 happy_x_2 of { happy_var_2 -> 
+	happyIn39
+		 ((:) happy_var_1 happy_var_2
+	)}}
+
+happyReduce_47 = happySpecReduce_1  18# happyReduction_47
+happyReduction_47 happy_x_1
+	 =  case happyOut31 happy_x_1 of { happy_var_1 -> 
+	happyIn40
+		 ((:[]) happy_var_1
+	)}
+
+happyReduce_48 = happySpecReduce_2  18# happyReduction_48
+happyReduction_48 happy_x_2
+	happy_x_1
+	 =  case happyOut31 happy_x_1 of { happy_var_1 -> 
+	case happyOut40 happy_x_2 of { happy_var_2 -> 
+	happyIn40
+		 ((:) happy_var_1 happy_var_2
+	)}}
+
+happyReduce_49 = happySpecReduce_1  19# happyReduction_49
+happyReduction_49 happy_x_1
+	 =  case happyOut36 happy_x_1 of { happy_var_1 -> 
+	happyIn41
+		 ((:[]) happy_var_1
+	)}
+
+happyReduce_50 = happySpecReduce_3  19# happyReduction_50
+happyReduction_50 happy_x_3
+	happy_x_2
+	happy_x_1
+	 =  case happyOut36 happy_x_1 of { happy_var_1 -> 
+	case happyOut41 happy_x_3 of { happy_var_3 -> 
+	happyIn41
+		 ((:) happy_var_1 happy_var_3
+	)}}
+
+happyReduce_51 = happySpecReduce_0  20# happyReduction_51
+happyReduction_51  =  happyIn42
+		 ([]
+	)
+
+happyReduce_52 = happySpecReduce_2  20# happyReduction_52
+happyReduction_52 happy_x_2
+	happy_x_1
+	 =  case happyOut42 happy_x_1 of { happy_var_1 -> 
+	case happyOut35 happy_x_2 of { happy_var_2 -> 
+	happyIn42
+		 (flip (:) happy_var_1 happy_var_2
+	)}}
+
+happyReduce_53 = happySpecReduce_1  21# happyReduction_53
+happyReduction_53 happy_x_1
+	 =  case happyOut22 happy_x_1 of { happy_var_1 -> 
+	happyIn43
+		 ((:[]) happy_var_1
+	)}
+
+happyReduce_54 = happySpecReduce_2  21# happyReduction_54
+happyReduction_54 happy_x_2
+	happy_x_1
+	 =  case happyOut22 happy_x_1 of { happy_var_1 -> 
+	case happyOut43 happy_x_2 of { happy_var_2 -> 
+	happyIn43
+		 ((:) happy_var_1 happy_var_2
+	)}}
+
+happyNewToken action sts stk [] =
+	happyDoAction 26# notHappyAtAll action sts stk []
+
+happyNewToken action sts stk (tk:tks) =
+	let cont i = happyDoAction i tk action sts stk tks in
+	case tk of {
+	PT _ (TS _ 1) -> cont 1#;
+	PT _ (TS _ 2) -> cont 2#;
+	PT _ (TS _ 3) -> cont 3#;
+	PT _ (TS _ 4) -> cont 4#;
+	PT _ (TS _ 5) -> cont 5#;
+	PT _ (TS _ 6) -> cont 6#;
+	PT _ (TS _ 7) -> cont 7#;
+	PT _ (TS _ 8) -> cont 8#;
+	PT _ (TS _ 9) -> cont 9#;
+	PT _ (TS _ 10) -> cont 10#;
+	PT _ (TS _ 11) -> cont 11#;
+	PT _ (TS _ 12) -> cont 12#;
+	PT _ (TS _ 13) -> cont 13#;
+	PT _ (TS _ 14) -> cont 14#;
+	PT _ (TS _ 15) -> cont 15#;
+	PT _ (TS _ 16) -> cont 16#;
+	PT _ (TS _ 17) -> cont 17#;
+	PT _ (TS _ 18) -> cont 18#;
+	PT _ (TS _ 19) -> cont 19#;
+	PT _ (TS _ 20) -> cont 20#;
+	PT _ (TS _ 21) -> cont 21#;
+	PT _ (TS _ 22) -> cont 22#;
+	PT _ (TV happy_dollar_dollar) -> cont 23#;
+	PT _ (T_VerIdent happy_dollar_dollar) -> cont 24#;
+	PT _ (T_RouteIdent happy_dollar_dollar) -> cont 25#;
+	_ -> happyError' (tk:tks)
+	}
+
+happyError_ 26# tk tks = happyError' tks
+happyError_ _ tk tks = happyError' (tk:tks)
+
+happyThen :: () => Err a -> (a -> Err b) -> Err b
+happyThen = (thenM)
+happyReturn :: () => a -> Err a
+happyReturn = (returnM)
+happyThen1 m k tks = (thenM) m (\a -> k a tks)
+happyReturn1 :: () => a -> b -> Err a
+happyReturn1 = \a tks -> (returnM) a
+happyError' :: () => [(Token)] -> Err a
+happyError' = happyError
+
+pSpecification tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 0# tks) (\x -> happyReturn (happyOut25 x))
+
+pName tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 1# tks) (\x -> happyReturn (happyOut26 x))
+
+pVersion tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 2# tks) (\x -> happyReturn (happyOut27 x))
+
+pModules tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 3# tks) (\x -> happyReturn (happyOut28 x))
+
+pEnumType tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 4# tks) (\x -> happyReturn (happyOut29 x))
+
+pStructType tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 5# tks) (\x -> happyReturn (happyOut30 x))
+
+pResource tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 6# tks) (\x -> happyReturn (happyOut31 x))
+
+pMode tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 7# tks) (\x -> happyReturn (happyOut32 x))
+
+pField tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 8# tks) (\x -> happyReturn (happyOut33 x))
+
+pFType tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 9# tks) (\x -> happyReturn (happyOut34 x))
+
+pAnnotation tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 10# tks) (\x -> happyReturn (happyOut35 x))
+
+pEnumVal tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 11# tks) (\x -> happyReturn (happyOut36 x))
+
+pListEnumType tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 12# tks) (\x -> happyReturn (happyOut37 x))
+
+pListField tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 13# tks) (\x -> happyReturn (happyOut38 x))
+
+pListStructType tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 14# tks) (\x -> happyReturn (happyOut39 x))
+
+pListResource tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 15# tks) (\x -> happyReturn (happyOut40 x))
+
+pListEnumVal tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 16# tks) (\x -> happyReturn (happyOut41 x))
+
+pListAnnotation tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 17# tks) (\x -> happyReturn (happyOut42 x))
+
+pListIdent tks = happySomeParser where
+  happySomeParser = happyThen (happyParse 18# tks) (\x -> happyReturn (happyOut43 x))
+
+happySeq = happyDontSeq
+
+
+returnM :: a -> Err a
+returnM = return
+
+thenM :: Err a -> (a -> Err b) -> Err b
+thenM = (>>=)
+
+happyError :: [Token] -> Err a
+happyError ts =
+  Bad $ "syntax error at " ++ tokenPos ts ++ 
+  case ts of
+    [] -> []
+    [Err _] -> " due to lexer error"
+    _ -> " before " ++ unwords (map (id . prToken) (take 4 ts))
+
+myLexer = tokens
+{-# LINE 1 "templates/GenericTemplate.hs" #-}
+{-# LINE 1 "templates/GenericTemplate.hs" #-}
+{-# LINE 1 "<built-in>" #-}
+{-# LINE 1 "templates/GenericTemplate.hs" #-}
+-- Id: GenericTemplate.hs,v 1.26 2005/01/14 14:47:22 simonmar Exp 
+
+
+{-# LINE 13 "templates/GenericTemplate.hs" #-}
+
+
+
+
+
+-- Do not remove this comment. Required to fix CPP parsing when using GCC and a clang-compiled alex.
+#if __GLASGOW_HASKELL__ > 706
+#define LT(n,m) ((Happy_GHC_Exts.tagToEnum# (n Happy_GHC_Exts.<# m)) :: Bool)
+#define GTE(n,m) ((Happy_GHC_Exts.tagToEnum# (n Happy_GHC_Exts.>=# m)) :: Bool)
+#define EQ(n,m) ((Happy_GHC_Exts.tagToEnum# (n Happy_GHC_Exts.==# m)) :: Bool)
+#else
+#define LT(n,m) (n Happy_GHC_Exts.<# m)
+#define GTE(n,m) (n Happy_GHC_Exts.>=# m)
+#define EQ(n,m) (n Happy_GHC_Exts.==# m)
+#endif
+
+{-# LINE 46 "templates/GenericTemplate.hs" #-}
+
+
+data Happy_IntList = HappyCons Happy_GHC_Exts.Int# Happy_IntList
+
+
+
+
+
+
+{-# LINE 67 "templates/GenericTemplate.hs" #-}
+
+
+{-# LINE 77 "templates/GenericTemplate.hs" #-}
+
+
+
+
+
+
+
+
+
+
+infixr 9 `HappyStk`
+data HappyStk a = HappyStk a (HappyStk a)
+
+-----------------------------------------------------------------------------
+-- starting the parse
+
+happyParse start_state = happyNewToken start_state notHappyAtAll notHappyAtAll
+
+-----------------------------------------------------------------------------
+-- Accepting the parse
+
+-- If the current token is 0#, it means we've just accepted a partial
+-- parse (a %partial parser).  We must ignore the saved token on the top of
+-- the stack in this case.
+happyAccept 0# tk st sts (_ `HappyStk` ans `HappyStk` _) =
+        happyReturn1 ans
+happyAccept j tk st sts (HappyStk ans _) = 
+        (happyTcHack j (happyTcHack st)) (happyReturn1 ans)
+
+-----------------------------------------------------------------------------
+-- Arrays only: do the next action
+
+
+
+happyDoAction i tk st
+        = {- nothing -}
+          
+
+          case action of
+                0#           -> {- nothing -}
+                                     happyFail i tk st
+                -1#          -> {- nothing -}
+                                     happyAccept i tk st
+                n | LT(n,(0# :: Happy_GHC_Exts.Int#)) -> {- nothing -}
+                                                   
+                                                   (happyReduceArr Happy_Data_Array.! rule) i tk st
+                                                   where rule = (Happy_GHC_Exts.I# ((Happy_GHC_Exts.negateInt# ((n Happy_GHC_Exts.+# (1# :: Happy_GHC_Exts.Int#))))))
+                n                 -> {- nothing -}
+                                     
+
+                                     happyShift new_state i tk st
+                                     where new_state = (n Happy_GHC_Exts.-# (1# :: Happy_GHC_Exts.Int#))
+   where off    = indexShortOffAddr happyActOffsets st
+         off_i  = (off Happy_GHC_Exts.+# i)
+         check  = if GTE(off_i,(0# :: Happy_GHC_Exts.Int#))
+                  then EQ(indexShortOffAddr happyCheck off_i, i)
+                  else False
+         action
+          | check     = indexShortOffAddr happyTable off_i
+          | otherwise = indexShortOffAddr happyDefActions st
+
+
+indexShortOffAddr (HappyA# arr) off =
+        Happy_GHC_Exts.narrow16Int# i
+  where
+        i = Happy_GHC_Exts.word2Int# (Happy_GHC_Exts.or# (Happy_GHC_Exts.uncheckedShiftL# high 8#) low)
+        high = Happy_GHC_Exts.int2Word# (Happy_GHC_Exts.ord# (Happy_GHC_Exts.indexCharOffAddr# arr (off' Happy_GHC_Exts.+# 1#)))
+        low  = Happy_GHC_Exts.int2Word# (Happy_GHC_Exts.ord# (Happy_GHC_Exts.indexCharOffAddr# arr off'))
+        off' = off Happy_GHC_Exts.*# 2#
+
+
+
+
+
+data HappyAddr = HappyA# Happy_GHC_Exts.Addr#
+
+
+
+
+-----------------------------------------------------------------------------
+-- HappyState data type (not arrays)
+
+
+{-# LINE 170 "templates/GenericTemplate.hs" #-}
+
+-----------------------------------------------------------------------------
+-- Shifting a token
+
+happyShift new_state 0# tk st sts stk@(x `HappyStk` _) =
+     let i = (case Happy_GHC_Exts.unsafeCoerce# x of { (Happy_GHC_Exts.I# (i)) -> i }) in
+--     trace "shifting the error token" $
+     happyDoAction i tk new_state (HappyCons (st) (sts)) (stk)
+
+happyShift new_state i tk st sts stk =
+     happyNewToken new_state (HappyCons (st) (sts)) ((happyInTok (tk))`HappyStk`stk)
+
+-- happyReduce is specialised for the common cases.
+
+happySpecReduce_0 i fn 0# tk st sts stk
+     = happyFail 0# tk st sts stk
+happySpecReduce_0 nt fn j tk st@((action)) sts stk
+     = happyGoto nt j tk st (HappyCons (st) (sts)) (fn `HappyStk` stk)
+
+happySpecReduce_1 i fn 0# tk st sts stk
+     = happyFail 0# tk st sts stk
+happySpecReduce_1 nt fn j tk _ sts@((HappyCons (st@(action)) (_))) (v1`HappyStk`stk')
+     = let r = fn v1 in
+       happySeq r (happyGoto nt j tk st sts (r `HappyStk` stk'))
+
+happySpecReduce_2 i fn 0# tk st sts stk
+     = happyFail 0# tk st sts stk
+happySpecReduce_2 nt fn j tk _ (HappyCons (_) (sts@((HappyCons (st@(action)) (_))))) (v1`HappyStk`v2`HappyStk`stk')
+     = let r = fn v1 v2 in
+       happySeq r (happyGoto nt j tk st sts (r `HappyStk` stk'))
+
+happySpecReduce_3 i fn 0# tk st sts stk
+     = happyFail 0# tk st sts stk
+happySpecReduce_3 nt fn j tk _ (HappyCons (_) ((HappyCons (_) (sts@((HappyCons (st@(action)) (_))))))) (v1`HappyStk`v2`HappyStk`v3`HappyStk`stk')
+     = let r = fn v1 v2 v3 in
+       happySeq r (happyGoto nt j tk st sts (r `HappyStk` stk'))
+
+happyReduce k i fn 0# tk st sts stk
+     = happyFail 0# tk st sts stk
+happyReduce k nt fn j tk st sts stk
+     = case happyDrop (k Happy_GHC_Exts.-# (1# :: Happy_GHC_Exts.Int#)) sts of
+         sts1@((HappyCons (st1@(action)) (_))) ->
+                let r = fn stk in  -- it doesn't hurt to always seq here...
+                happyDoSeq r (happyGoto nt j tk st1 sts1 r)
+
+happyMonadReduce k nt fn 0# tk st sts stk
+     = happyFail 0# tk st sts stk
+happyMonadReduce k nt fn j tk st sts stk =
+      case happyDrop k (HappyCons (st) (sts)) of
+        sts1@((HappyCons (st1@(action)) (_))) ->
+          let drop_stk = happyDropStk k stk in
+          happyThen1 (fn stk tk) (\r -> happyGoto nt j tk st1 sts1 (r `HappyStk` drop_stk))
+
+happyMonad2Reduce k nt fn 0# tk st sts stk
+     = happyFail 0# tk st sts stk
+happyMonad2Reduce k nt fn j tk st sts stk =
+      case happyDrop k (HappyCons (st) (sts)) of
+        sts1@((HappyCons (st1@(action)) (_))) ->
+         let drop_stk = happyDropStk k stk
+
+             off = indexShortOffAddr happyGotoOffsets st1
+             off_i = (off Happy_GHC_Exts.+# nt)
+             new_state = indexShortOffAddr happyTable off_i
+
+
+
+          in
+          happyThen1 (fn stk tk) (\r -> happyNewToken new_state sts1 (r `HappyStk` drop_stk))
+
+happyDrop 0# l = l
+happyDrop n (HappyCons (_) (t)) = happyDrop (n Happy_GHC_Exts.-# (1# :: Happy_GHC_Exts.Int#)) t
+
+happyDropStk 0# l = l
+happyDropStk n (x `HappyStk` xs) = happyDropStk (n Happy_GHC_Exts.-# (1#::Happy_GHC_Exts.Int#)) xs
+
+-----------------------------------------------------------------------------
+-- Moving to a new state after a reduction
+
+
+happyGoto nt j tk st = 
+   {- nothing -}
+   happyDoAction j tk new_state
+   where off = indexShortOffAddr happyGotoOffsets st
+         off_i = (off Happy_GHC_Exts.+# nt)
+         new_state = indexShortOffAddr happyTable off_i
+
+
+
+
+-----------------------------------------------------------------------------
+-- Error recovery (0# is the error token)
+
+-- parse error if we are in recovery and we fail again
+happyFail 0# tk old_st _ stk@(x `HappyStk` _) =
+     let i = (case Happy_GHC_Exts.unsafeCoerce# x of { (Happy_GHC_Exts.I# (i)) -> i }) in
+--      trace "failing" $ 
+        happyError_ i tk
+
+{-  We don't need state discarding for our restricted implementation of
+    "error".  In fact, it can cause some bogus parses, so I've disabled it
+    for now --SDM
+
+-- discard a state
+happyFail  0# tk old_st (HappyCons ((action)) (sts)) 
+                                                (saved_tok `HappyStk` _ `HappyStk` stk) =
+--      trace ("discarding state, depth " ++ show (length stk))  $
+        happyDoAction 0# tk action sts ((saved_tok`HappyStk`stk))
+-}
+
+-- Enter error recovery: generate an error token,
+--                       save the old token and carry on.
+happyFail  i tk (action) sts stk =
+--      trace "entering error recovery" $
+        happyDoAction 0# tk action sts ( (Happy_GHC_Exts.unsafeCoerce# (Happy_GHC_Exts.I# (i))) `HappyStk` stk)
+
+-- Internal happy errors:
+
+notHappyAtAll :: a
+notHappyAtAll = error "Internal Happy error\n"
+
+-----------------------------------------------------------------------------
+-- Hack to get the typechecker to accept our action functions
+
+
+happyTcHack :: Happy_GHC_Exts.Int# -> a -> a
+happyTcHack x y = y
+{-# INLINE happyTcHack #-}
+
+
+-----------------------------------------------------------------------------
+-- Seq-ing.  If the --strict flag is given, then Happy emits 
+--      happySeq = happyDoSeq
+-- otherwise it emits
+--      happySeq = happyDontSeq
+
+happyDoSeq, happyDontSeq :: a -> b -> b
+happyDoSeq   a b = a `seq` b
+happyDontSeq a b = b
+
+-----------------------------------------------------------------------------
+-- Don't inline any functions from the template.  GHC has a nasty habit
+-- of deciding to inline happyGoto everywhere, which increases the size of
+-- the generated parser quite a bit.
+
+
+{-# NOINLINE happyDoAction #-}
+{-# NOINLINE happyTable #-}
+{-# NOINLINE happyCheck #-}
+{-# NOINLINE happyActOffsets #-}
+{-# NOINLINE happyGotoOffsets #-}
+{-# NOINLINE happyDefActions #-}
+
+{-# NOINLINE happyShift #-}
+{-# NOINLINE happySpecReduce_0 #-}
+{-# NOINLINE happySpecReduce_1 #-}
+{-# NOINLINE happySpecReduce_2 #-}
+{-# NOINLINE happySpecReduce_3 #-}
+{-# NOINLINE happyReduce #-}
+{-# NOINLINE happyMonadReduce #-}
+{-# NOINLINE happyGoto #-}
+{-# NOINLINE happyFail #-}
+
+-- end of Happy Template.
+
diff --git a/harmony-commandline/Main.hs b/harmony-commandline/Main.hs
new file mode 100644
--- /dev/null
+++ b/harmony-commandline/Main.hs
@@ -0,0 +1,102 @@
+module Main where
+
+import           Control.Monad              (forM_, unless)
+import           Data.Maybe                 (fromJust)
+import qualified Generation.OutputGenerator as OG
+import           Language.ErrM
+import           Language.Par
+import           System.Console.GetOpt
+import           System.Environment         (getArgs, getProgName)
+import           System.Exit                (ExitCode (ExitFailure), exitWith)
+import qualified TypeCheck.ApiSpec          as AS
+import qualified TypeCheck.StaticCheck      as SC
+
+-- | Flags of the executable
+data Options = Options
+  { generationFunctions :: [OG.GenerationFunction]
+  , outputDir           :: FilePath
+  }
+
+defaultOptions :: Options
+defaultOptions = Options
+  { generationFunctions = []
+  , outputDir = "./harmony_output"
+  }
+
+-- | Definition of the flags expected by the executable
+options :: [OptDescr (Options -> Options)]
+options = [ Option "c" ["client"]
+                   (OptArg (\c options -> options { generationFunctions = parseClient c:generationFunctions options})
+                           "CLIENTS")
+                   "Desired output for the client"
+          , Option "s" ["server"]
+                   (OptArg (\s options -> options { generationFunctions = parseServer s:generationFunctions options})
+                           "SERVERS")
+                   "Desired output for the server"
+          , Option "o" ["output_dir"]
+                   (OptArg (\dir options -> options { outputDir = fromJust dir })
+                           "OUTPUT_DIR")
+                   "Output path"
+          ]
+
+-- | Parse flag input
+parseClient, parseServer :: Maybe String -> OG.GenerationFunction
+parseClient (Just "js") = OG.generateJSClient
+parseClient (Just "python") = OG.generatePythonClient
+parseClient (Just other) = error $ "Could not parse client: " ++ other
+parseClient Nothing = error "parseClient: not expected Nothing as flag"
+parseServer (Just "js") = OG.generateJSServer
+parseServer (Just other) = error $ "Could not parse server" ++ other
+parseServer Nothing = error "parseServer: not expected Nothing as flag"
+
+-- | Entry point, parses arguments, then the specification file and generates all the desired
+-- | outputs.
+main :: IO ()
+main = do
+  (inputFile, outputPath, toGenerateList) <- parseArgs
+  contents <- readFile inputFile
+  case pSpecification (myLexer contents) of
+    Bad err -> ioError (userError err)
+    Ok tree -> case SC.staticCheck tree of
+                 Bad err -> ioError (userError err)
+                 Ok env -> generateOutput env toGenerateList outputPath
+  return ()
+
+-- | Parses the arguments and returns a list of targets to generate.
+parseArgs :: IO (FilePath, FilePath, [OG.GenerationFunction])
+parseArgs = do
+  args <- getArgs
+  programName <- getProgName
+
+  case getOpt Permute options args of
+    (flags, args, []) -> do
+      unless (length args == 1)
+             (printUsageAndExitWithError Nothing programName options)
+      unless (not $ null flags)
+             (printUsageAndExitWithError (Just "Select at least a client/server") programName options)
+      return (head args, outputDir info, generationFunctions info)
+        where
+          info :: Options
+          info = foldl (flip ($))  defaultOptions flags
+    -- TODO: check if this should be another printUsageAndExitWithError call
+    (_, _, errs) -> ioError (userError (concat errs ++ usage programName options))
+
+-- | Generate all the output required.
+generateOutput :: AS.ApiSpec -> [OG.GenerationFunction] -> FilePath -> IO ()
+generateOutput apiSpec genFunctions outputPath = forM_ genFunctions (\f -> f outputPath apiSpec)
+
+-- | Generates the usage message.
+usage :: String -> [OptDescr (Options -> Options)] -> String
+usage progName = usageInfo header
+  where
+    header = "Usage: " ++ progName ++ " [OPTION...] input_file"
+
+-- | Prints usage and exits with error.
+printUsageAndExitWithError :: Maybe String -> String -> [OptDescr (Options -> Options)] -> IO ()
+printUsageAndExitWithError message progName options = do
+  case message of
+    Just str -> putStrLn $ "ERROR: " ++ str ++ "\n"
+    Nothing -> return ()
+  putStrLn $ usage progName options
+  exitWith (ExitFailure 2)
+
diff --git a/harmony.cabal b/harmony.cabal
new file mode 100644
--- /dev/null
+++ b/harmony.cabal
@@ -0,0 +1,127 @@
+name:                harmony
+
+-- The package version.  See the Haskell package versioning policy (PVP) 
+-- for standards guiding when and how versions should be incremented.
+-- http://www.haskell.org/haskellwiki/Package_versioning_policy
+-- PVP summary:      +-+------- breaking API changes
+--                   | | +----- non-breaking API additions
+--                   | | | +--- code changes with no API change
+version:             0.1.0.0
+
+synopsis:            A web service specification compiler that generates implementation and tests.
+
+description:         This application defines a specification language for web services and reads
+                     it in order to generate implementation, tests, clients, etc...
+
+license:             GPL-3
+
+license-file:        LICENSE
+
+author:              Santiago Munín
+
+maintainer:          santimunin@gmail.com
+
+bug-reports:         https://github.com/SantiMunin/harmony/issues
+
+category:            Development
+
+build-type:          Custom
+
+data-files:          templates/server/js/package.tpl
+                   , templates/server/js/server.tpl
+                   , templates/client/python/client.tpl
+                   , templates/client/python/test.tpl
+
+extra-source-files:  README.md
+
+cabal-version:       >= 1.18
+
+source-repository head
+  type:     git
+  location: https://github.com/SantiMunin/harmony
+
+library
+
+  build-depends:       base >=4.7 && <4.8
+                     , array
+                     , containers
+                     , BNFC
+                     , hastache
+                     , text
+                     , mtl
+                     , derive
+                     , directory
+                     , QuickCheck
+                     , process
+                     , hslogger
+  
+  ghc-options:         -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind
+  
+  hs-source-dirs:      src
+
+  build-tools:         alex
+                     , happy
+
+  exposed-modules:     TypeCheck.ApiSpec
+                     , TypeCheck.StaticCheck
+                     , Generation.OutputGenerator
+                     , Generation.ServiceGenerator
+                     , Generation.TemplateCompiler
+                     , Data.DiGraph
+                     , Language.Abs
+                     , Language.ErrM
+                     , Language.Lex
+                     , Language.Par
+                     , LangUtils
+                     , Paths_harmony
+
+  default-language:    Haskell2010
+  
+executable harmony
+
+  ghc-options:         -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind
+
+  hs-source-dirs:      harmony-commandline
+
+  main-is:             Main.hs
+
+  build-depends:       base >= 4.7 && < 4.8
+                     , harmony
+
+  default-language:    Haskell2010
+
+test-suite hspec
+
+  type:                exitcode-stdio-1.0
+
+  ghc-options:         -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind -fno-warn-orphans -fhpc
+
+  hs-source-dirs:      test
+
+  main-is:             Spec.hs
+
+  build-depends:       base >= 4.7 && < 4.8
+                     , containers
+                     , hspec >= 2.0
+                     , QuickCheck
+                     , HUnit
+                     , harmony
+                     , derive
+                     , hslogger
+
+  default-language:    Haskell2010
+
+test-suite hlint
+  build-depends:       base >= 4.7 && < 4.8
+                     , hlint
+
+  ghc-options:         -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind
+
+  hs-source-dirs:      test
+  
+  main-is:             HLint.hs
+
+  type:                exitcode-stdio-1.0
+  
+  default-language:    Haskell2010
+
diff --git a/src/Data/DiGraph.hs b/src/Data/DiGraph.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/DiGraph.hs
@@ -0,0 +1,94 @@
+module Data.DiGraph( Graph ()
+                   , empty
+                   , create
+                   , addNode
+                   , addAllNodes
+                   , addNeighbors
+                   , addAllNeighbors
+                   , contains
+                   , deleteNode
+                   , getNeighbors
+                   , getNodes
+                   , isEmpty
+                   , hasCycle
+                   , generateInverseDependencyList) where
+
+import qualified Data.Map as M
+import qualified Data.Set as S
+
+data (Ord a) => Graph a = Graph { nodes :: S.Set a
+                                , next  :: M.Map a (S.Set a)
+                                } deriving (Eq, Show)
+
+empty :: Ord a => Graph a
+empty = Graph { nodes = S.empty
+              , next = M.empty
+              }
+
+create :: Ord a => [(a, [a])] -> Graph a
+create pairs = addAllNeighbors pairs $ addAllNodes (map fst pairs) empty
+
+addNode :: Ord a => a -> Graph a -> Graph a
+addNode v graph = graph { nodes = v `S.insert` nodes graph }
+
+deleteNode :: Ord a => a -> Graph a -> Graph a
+deleteNode v graph = graph { nodes = v `S.delete` nodes graph
+                           , next = deleteNodeFromNext v $ next graph}
+  where
+    deleteNodeFromNext v m = rmFromAllSets v $ M.delete v m
+    rmFromAllSets v = M.map (S.delete v)
+
+addAllNodes :: Ord a => [a] -> Graph a -> Graph a
+addAllNodes nodes graph = foldl (flip addNode) graph nodes
+
+addNeighbors :: Ord a => a -> [a] -> Graph a -> Graph a
+addNeighbors v neighboors graph | graph `contains` v = graph { nodes = nodes $ addAllNodes neighboors graph, next = M.insert v (S.fromList neighboors) $ next graph }
+                                | otherwise = addNeighbors v neighboors $ addNode v graph
+
+addAllNeighbors :: Ord a => [(a, [a])] -> Graph a -> Graph a
+addAllNeighbors pairs graph = foldl (\g (v, next) -> addNeighbors v next g) graph pairs
+
+contains :: Ord a => Graph a -> a -> Bool
+contains graph v = v `S.member` nodes graph
+
+getNeighbors :: Ord a => Graph a -> a -> Maybe [a]
+getNeighbors graph v = do
+  ns <- M.lookup v $ next graph
+  let nList = S.toList ns
+  if null nList
+  then Nothing
+  else return nList
+
+getNodes :: Ord a => Graph a -> [a]
+getNodes = S.toList . nodes
+
+isEmpty :: Ord a => Graph a -> Bool
+isEmpty graph = S.null $ nodes graph
+
+hasCycle :: Ord a => Graph a -> Bool
+hasCycle graph | isEmpty graph = False
+               | otherwise = any (`go` S.empty) $ getNodes graph
+  where
+    go node visited | node `S.member` visited = True
+                    | otherwise = case getNeighbors graph node of
+                                    Nothing -> False
+                                    Just next -> any (flip go $ node `S.insert` visited) next
+
+dfs :: Ord a => Graph a -> Maybe a
+dfs graph | isEmpty graph = Nothing
+          | otherwise = go (head $ getNodes graph) graph
+  where
+    go :: Ord a => a -> Graph a -> Maybe a
+    go node graph =
+      case getNeighbors graph node of
+        Nothing -> return node
+        Just [] -> error "getNeighbors returning \"Just []\" should never happen"
+        Just (node':_) -> go node' graph
+
+generateInverseDependencyList :: Ord a => Graph a -> [a]
+generateInverseDependencyList graph = go graph []
+  where
+    go graph accum =
+      case dfs graph of
+        Nothing -> reverse accum
+        Just n -> go (deleteNode n graph) (n:accum)
diff --git a/src/Generation/OutputGenerator.hs b/src/Generation/OutputGenerator.hs
new file mode 100644
--- /dev/null
+++ b/src/Generation/OutputGenerator.hs
@@ -0,0 +1,137 @@
+{-# LANGUAGE OverloadedStrings #-}
+-- | Contains the generation logic and functions of the different possible outputs.
+module Generation.OutputGenerator(GenerationFunction, generateJSServer, generateJSClient, generatePythonClient) where
+
+import           Control.Monad
+import           Data.List
+import qualified Data.Text.Lazy.IO           as TL
+import qualified Generation.ServiceGenerator as SG
+import qualified Generation.TemplateCompiler as TC
+import           Paths_harmony
+import           System.Directory
+import           System.Exit                 (ExitCode (..))
+import           System.Log.Formatter        ()
+import           System.Log.Handler          ()
+import           System.Log.Handler.Simple   ()
+import           System.Log.Handler.Syslog   ()
+import           System.Log.Logger
+import           System.Process              (system)
+import qualified TypeCheck.ApiSpec           as AS
+
+-- | A template is a source file and a new extension; e.g. ("template.tpl", "js") will result in
+--   "template.js" after the template compilation.
+type TemplateInfo = (FilePath, String)
+
+-- | All the info necesaary in order to generate a target:
+--   * List of regular files (this will be just directly copied)
+--   * List of templates that will be compiled
+--   * A map from a Harmony type to the target's type
+type GenerationInfo = ([FilePath], [TemplateInfo], AS.Type -> String)
+
+-- | A function that generates the target.
+type GenerationFunction = FilePath -- ^ Output path
+                       -> AS.ApiSpec -- ^ Information of the defined web service
+                       -> IO ()
+
+-- | Target generation function.
+generateJSServer, generateJSClient, generatePythonClient :: GenerationFunction
+generateJSServer = generateOutput (files, templates, fieldMapping) postOpFunc
+  where
+    files = []
+    templates = [ ("templates/server/js/server.tpl", "js")
+                , ("templates/server/js/package.tpl", "json")
+                ]
+    fieldMapping AS.TString = "String"
+    fieldMapping AS.TLong = "Number"
+    fieldMapping AS.TInt = "Number"
+    fieldMapping AS.TDouble = "Number"
+    -- An enum is an string with constraints.
+    fieldMapping (AS.TEnum _) = "String"
+    fieldMapping (AS.TStruct t) = t
+    fieldMapping (AS.TList t) = fieldMapping t
+    fieldMapping other = error $ "Javascript server generation: Type not recognized -> " ++ show other
+
+generateJSClient = error "Javascript client is not implemented yet"
+
+generatePythonClient = generateOutput (files, templates, fieldMapping) postOpFunc
+  where
+    files = []
+    templates = [ ("templates/client/python/client.tpl", "py")
+                , ("templates/client/python/test.tpl", "py")
+                ]
+    -- These are the generators for the different types used by Hypothesis.
+    fieldMapping AS.TString = "strategy([strategy(integers_in_range(65,90)) | strategy(integers_in_range(97, 122))]).map(lambda l: map(chr, l)).map(lambda l: ''.join(l))"
+    fieldMapping AS.TInt = "integers_in_range(-1000,1000)"
+    fieldMapping AS.TLong = "integers_in_range(-1000,1000)"
+    fieldMapping AS.TDouble = "error:PythonNoTypes (Double)"
+    fieldMapping (AS.TEnum _) = "error: no directly translation from enum type to Hypothesis type"
+    fieldMapping (AS.TStruct name) = name ++ "Data"
+    fieldMapping (AS.TList t) = "[" ++ fieldMapping t ++ "]"
+    fieldMapping other = error $ "Python client generation: Type not recognized -> " ++ show other
+
+-- | Applies different post processing operations to each file type.
+postOpFunc :: String -> FilePath -> IO ()
+postOpFunc "js" = applyJsBeautify
+postOpFunc "py" = applyYapf
+postOpFunc _ = \_ -> return ()
+
+applyJsBeautify :: FilePath -> IO ()
+applyJsBeautify path = do
+  infoM "Generation.OutputGenerator" $ "Applying js-beautifier to " ++ path
+  outcome <- system $ "js-beautify " ++ path ++ " > tempfile && cat tempfile > " ++ path ++ " && rm tempfile"
+  case outcome of
+    ExitSuccess -> return ()
+    (ExitFailure _) ->
+      warningM "Generation.OutputGenerator" $ "There was a problem applying the python beautifier, "
+              ++ "please check it is installed and in the system's path (if "
+              ++ "you ignore this message the Python generated files will not be properly formatted"
+
+
+applyYapf :: FilePath -> IO ()
+applyYapf path = do
+  infoM "Generation.OutputGenerator" $ "Applying yapf to " ++ path
+  outcome <- system $ "yapf " ++ path ++ " > tempfile && cat tempfile > " ++ path ++ " && rm tempfile"
+  case outcome of
+    ExitSuccess -> return ()
+    (ExitFailure _) ->
+      warningM "Generation.OutputGenerator" $ "There was a problem applying the python beautifier, "
+              ++ "please check it is installed and in the system's path (if "
+              ++ "you ignore this message the Python generated files will not be properly formatted"
+
+-- | Uses all the information provided by the user (and the input file) and generates
+-- the output by compiling the templates and copying all the files to the output directory.
+generateOutput :: GenerationInfo -- ^ The information gathered from the user
+               -> (String -> FilePath -> IO ()) -- ^ A function that performs a different operation per file extension
+               -> FilePath -- ^ Output path
+               -> AS.ApiSpec -- ^ The information gathered from the input file (specification)
+               -> IO ()
+generateOutput (files, templates, fieldMapping) postOpFunc outputPath apiSpec = do
+  updateGlobalLogger "Generation.OutputGenerator" (setLevel INFO)
+  forM_ files (copy outputPath)
+  forM_ templates (generateAndWrite outputPath (SG.generateService apiSpec fieldMapping) postOpFunc)
+
+-- | Copies a file.
+copy :: FilePath -- ^ Origin file
+     -> FilePath -- ^ Destination path
+     -> IO ()
+copy origin dest = do
+  cabalFilePath <- getDataFileName origin
+  copyFile cabalFilePath (dest ++ "/" ++ origin)
+
+-- | Generate a template and writes it to the destination path.
+generateAndWrite :: FilePath -- ^ Destination path
+                -> TC.Service -- ^ Information for the template
+                -> (String -> FilePath -> IO ()) -- ^ A function that performs a different operation per file extension
+                -> TemplateInfo -- ^ Information of the template
+                -> IO ()
+generateAndWrite dest service postOpFunc (templatePath, newExt) = do
+  output <- TC.render templatePath service
+  createDirectoryIfMissing {- create parent dirs too -} True destDir
+  TL.writeFile destFile output
+  postOpFunc newExt destFile
+  where
+    destFileWithoutExt = dest ++ takeWhile (/= '.') (dropWhile (/= '/') templatePath)
+    destDir =
+      let indices = elemIndices '/' destFile
+      in if null indices then "." else take (last indices + 1) destFile
+    destFile = destFileWithoutExt ++ "." ++ newExt
diff --git a/src/Generation/ServiceGenerator.hs b/src/Generation/ServiceGenerator.hs
new file mode 100644
--- /dev/null
+++ b/src/Generation/ServiceGenerator.hs
@@ -0,0 +1,75 @@
+-- | Generation of 'TC.Service' objects from the specification.
+module Generation.ServiceGenerator(generateService) where
+
+import qualified Data.Map                    as M
+import           Data.Maybe                  (fromJust, fromMaybe, isJust)
+import qualified Data.Set                    as S
+import qualified Generation.TemplateCompiler as TC
+import qualified TypeCheck.ApiSpec           as AS
+
+-- | Transforms an api specification to a service.
+generateService :: AS.ApiSpec -- ^ The specification of the web service
+                -> (AS.Type -> String) -- ^ A mapping from internal types to target's types
+                -> TC.Service
+generateService apiSpec fieldMapping =
+  TC.Service (AS.name apiSpec)
+             (AS.version apiSpec)
+             (AS.requiresAuth apiSpec)
+             $ map (generateSchema fieldMapping apiSpec . fst) $ AS.structs apiSpec
+
+-- | Generates the information of a resource/struct.
+generateSchema :: (AS.Type -> String) -- ^ A mapping from internal types to target's types
+               -> AS.ApiSpec -- ^ The specification of the web service
+               -> AS.Id -- ^ The name of the struct
+               -> TC.Schema
+generateSchema fieldMapping apiSpec strId =
+  TC.Schema { TC.schemaName = strId
+            , TC.schemaRoute = schemaRoute'
+            , TC.writable = writable'
+            , TC.hasKeyField = hasKeyField
+            , TC.keyField = keyField
+            , TC.schemaVars = generateVars fieldMapping apiSpec structInfo }
+  where
+    (schemaRoute', writable') = maybe (Nothing, False) (\(r, w) -> (Just TC.StrValue { TC.value = r }, w)) (M.lookup strId $ AS.resources apiSpec)
+    structInfo = fromJust $ lookup strId $ AS.structs apiSpec
+    maybeKeyField = AS.getPrimaryKey structInfo
+    -- Leave empty if it doesn't exist
+    keyField = fromMaybe "" maybeKeyField
+    hasKeyField = isJust maybeKeyField
+
+-- | Generates the information of the fields of a 'TC.Schema'.
+generateVars :: (AS.Type -> String) -- ^ A mapping from internal types to target's types
+             -> AS.ApiSpec -- ^ The specification of the web service
+             -> AS.StructInfo -- ^ The information of the struct
+             -> [TC.SchemaVar] -- ^ The information of all the fields of the schema
+generateVars fieldMapping apiSpec = map getVarFromField
+  where
+    getVarFromField :: AS.FieldInfo -> TC.SchemaVar
+    getVarFromField (AS.FI (n, t, modifs)) = generateSchemaVar n t modifs
+    -- TODO(6): implement custom fields
+    generateSchemaVar :: AS.Id -> AS.Type -> S.Set AS.Modifier -> TC.SchemaVar
+    generateSchemaVar name type' modifs =
+      TC.SchemaVar { TC.varName = name
+                   , TC.varType = fieldMapping type'
+                   , TC.isList = isList type'
+                   , TC.isEnum = if isEnum type' then Just $ getValues type' else Nothing
+                   , TC.isStruct = isStruct type'
+                   , TC.isKey = AS.PrimaryKey `S.member` modifs
+                   , TC.isRequired = AS.Required `S.member` modifs
+                   , TC.isHidden = AS.Hidden `S.member` modifs
+                   , TC.isUnique = AS.Unique `S.member` modifs || AS.PrimaryKey `S.member` modifs
+                   , TC.isUserLogin = AS.UserLogin `S.member` modifs
+                   }
+        where
+          getValues (AS.TEnum enumId) = TC.EnumValue $ map TC.StrValue (fromJust $ M.lookup enumId $ AS.enums apiSpec)
+          getValues (AS.TList t') = getValues t'
+          getValues other = error $ "getValues called on a non-enum type: " ++ show other
+          isEnum (AS.TEnum _) = True
+          isEnum (AS.TList t') = isEnum t'
+          isEnum _ = False
+          isList (AS.TList _) = True
+          isList _ = False
+          isStruct (AS.TStruct _) = True
+          isStruct (AS.TList t') = isStruct t'
+          isStruct _ = False
+
diff --git a/src/Generation/TemplateCompiler.hs b/src/Generation/TemplateCompiler.hs
new file mode 100644
--- /dev/null
+++ b/src/Generation/TemplateCompiler.hs
@@ -0,0 +1,64 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE OverloadedStrings  #-}
+{-# LANGUAGE TemplateHaskell    #-}
+
+-- | Compiles Hastache templates and defines the datatypes to pass information to them.
+module Generation.TemplateCompiler where
+
+import           Data.Data
+import           Data.DeriveTH
+import qualified Data.Text.Lazy        as TL
+import           Data.Typeable         ()
+import           Paths_harmony
+import           Test.QuickCheck
+import           Text.Hastache
+import           Text.Hastache.Context
+
+-- | An enum value
+data StrValue = StrValue { value :: String } deriving (Show, Data, Typeable, Eq)
+data EnumValues = EnumValue { values :: [StrValue] } deriving (Show, Data, Typeable, Eq)
+
+-- | A schema variable. It is a field of a struct.
+-- <b>DISCLAIMER</b>: there is some redundancy but the focus of this module is to make the templating easy.
+data SchemaVar = SchemaVar { varName     :: String
+                           , varType     :: String
+                           , isList      :: Bool
+                           -- Only if it is an enum (varType == String and values not empty)
+                           , isEnum      :: Maybe EnumValues
+                           , isStruct    :: Bool
+                           , isKey       :: Bool
+                           , isRequired  :: Bool
+                           , isHidden    :: Bool
+                           , isUnique    :: Bool
+                           , isUserLogin :: Bool
+                           } deriving (Show, Data, Typeable, Eq)
+
+-- | A schema is a struct (it has a name, a route, a write mode, etc...).
+data Schema = Schema { schemaName  :: String
+                     , schemaRoute :: Maybe StrValue
+                     , writable    :: Bool
+                     , hasKeyField :: Bool
+                     , keyField    :: String
+                     , schemaVars  :: [SchemaVar] } deriving (Show, Data, Typeable)
+
+-- | A service has a name, a version, and a list of 'Schema'
+data Service = Service { name         :: String
+                       , version      :: String
+                       , requiresAuth :: Bool
+                       , schema       :: [Schema] } deriving (Show, Data, Typeable)
+
+-- | Given a template and a service object, render the template.
+render:: String -> Service -> IO TL.Text
+render templateLoc service =
+  do
+    template <- getDataFileName templateLoc >>= readFile
+    let context = mkGenericContext service in
+      hastacheStr defaultConfig (encodeStr template) context
+
+
+derive makeArbitrary ''Service
+derive makeArbitrary ''StrValue
+derive makeArbitrary ''Schema
+derive makeArbitrary ''SchemaVar
+derive makeArbitrary ''EnumValues
+
diff --git a/src/LangUtils.hs b/src/LangUtils.hs
new file mode 100644
--- /dev/null
+++ b/src/LangUtils.hs
@@ -0,0 +1,85 @@
+-- | Contains useful methods to work with the defined types (both from the language
+-- specification/bnfc and the 'ApiSpec' module).
+module LangUtils where
+
+import qualified Data.Set          as S
+import           Language.Abs
+import qualified TypeCheck.ApiSpec as AS
+
+-- | Extracts the name of the 'Specification' (AST).
+specName :: Specification -- ^ Specification returned by the parser
+         -> String -- ^ Name of the specification
+specName (Spec (Nm (Ident n)) _ _ _ _ _) = n
+
+-- | Extracts the version of the 'Specification' (AST).
+specVersion :: Specification -- ^ Specification returned by the parser
+            -> String -- ^ Version of the specification
+specVersion (Spec _(Ver (VerIdent v)) _ _ _ _) = v
+
+-- | Extracts the name of an enum.
+enumName :: EnumType -- ^ Enum information
+         -> String -- ^ Name of the enum type
+enumName (DefEnum (Ident name) _) = name
+
+-- | Extracts the values of an enum.
+enumVals :: EnumType -- ^ Enum information
+         -> [EnumVal] -- ^ List of enum values
+enumVals (DefEnum _ vals) = vals
+
+enumValName :: EnumVal -- ^ Enum value information
+            -> String -- ^ Identifier of the enum value
+enumValName (EnVal (Ident name)) = name
+
+-- | Extracts the name of a struct.
+strName :: StructType -- ^ The struct info
+        -> String -- ^ The name of the struct
+strName (DefStr (Ident name) _) = name
+
+-- | Extracts the fields of a struct.
+strFields :: StructType -- ^ Struct info
+          -> [Field] -- ^ List of fields of the struct
+strFields (DefStr _ fields) = fields
+
+-- | Extracts the name of a resource.
+resName :: Resource -- ^ Resource information
+        -> String -- ^ Name of the resource
+resName (Res (Ident name) _ _) = name
+
+-- | Extracts the route of a resource.
+resRoute :: Resource -- ^ Resource information
+         -> String -- ^ Route of the resource
+resRoute (Res _ (RouteIdent route) _) = route
+
+-- | Extracts the write mode of a resource.
+resIsWritable :: Resource -- ^ Resource information
+              -> Bool -- ^ True if it is writable, False otherwise
+resIsWritable (Res _ _ mode) = mode == Write
+
+-- | Extracts the name of a field.
+fieldName :: Field -- ^ Field information
+          -> String -- ^ Name of the field
+fieldName (FDef _ (Ident name) _) = name
+
+-- | Extracts the annotation of a field.
+fieldAnnotations :: Field -- ^ Field information
+                 -> [Annotation] -- ^ List of annotations
+fieldAnnotations (FDef annotations _ _) = annotations
+
+-- | Extracts the type (defined by the language specification/bnfc) of a field.
+fieldType :: Field -- ^ Field information
+          -> FType -- ^ Type of the field
+fieldType (FDef _ _ ft) = ft
+
+-- | Extracts the type (defined in 'ApiSpec') of a field.
+fieldSpecType :: (S.Set String, S.Set String) -- ^ (Struct names, Enum names)
+              -> FType -- ^ Field type
+              -> AS.Type -- ^ 'ApiSpec' field type
+fieldSpecType _ FString = AS.TString
+fieldSpecType _ FInt = AS.TInt
+fieldSpecType _ FLong = AS.TLong
+fieldSpecType _ FDouble = AS.TDouble
+fieldSpecType (strs, enums) (FDefined (Ident n)) | n `S.member` enums = AS.TEnum n
+                                                 | n `S.member` strs = AS.TStruct n
+                                                 | otherwise = error $ "getType: " ++ n ++ " is not defined."
+fieldSpecType as (FList type') = AS.TList $ fieldSpecType as type'
+
diff --git a/src/Language/Abs.hs b/src/Language/Abs.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/Abs.hs
@@ -0,0 +1,67 @@
+
+
+module Language.Abs where
+
+-- Haskell module generated by the BNF converter
+
+
+
+
+newtype Ident = Ident String deriving (Eq,Ord,Show,Read)
+newtype VerIdent = VerIdent String deriving (Eq,Ord,Show,Read)
+newtype RouteIdent = RouteIdent String deriving (Eq,Ord,Show,Read)
+data Specification =
+   Spec Name Version Modules [EnumType] [StructType] [Resource]
+  deriving (Eq,Ord,Show,Read)
+
+data Name =
+   Nm Ident
+  deriving (Eq,Ord,Show,Read)
+
+data Version =
+   Ver VerIdent
+  deriving (Eq,Ord,Show,Read)
+
+data Modules =
+   EmptyMods
+ | Mods [Ident]
+  deriving (Eq,Ord,Show,Read)
+
+data EnumType =
+   DefEnum Ident [EnumVal]
+  deriving (Eq,Ord,Show,Read)
+
+data StructType =
+   DefStr Ident [Field]
+  deriving (Eq,Ord,Show,Read)
+
+data Resource =
+   Res Ident RouteIdent Mode
+  deriving (Eq,Ord,Show,Read)
+
+data Mode =
+   ReadOnly
+ | Write
+  deriving (Eq,Ord,Show,Read)
+
+data Field =
+   FDef [Annotation] Ident FType
+  deriving (Eq,Ord,Show,Read)
+
+data FType =
+   FString
+ | FInt
+ | FLong
+ | FDouble
+ | FDefined Ident
+ | FList FType
+  deriving (Eq,Ord,Show,Read)
+
+data Annotation =
+   Ann Ident
+  deriving (Eq,Ord,Show,Read)
+
+data EnumVal =
+   EnVal Ident
+  deriving (Eq,Ord,Show,Read)
+
diff --git a/src/Language/ErrM.hs b/src/Language/ErrM.hs
new file mode 100644
--- /dev/null
+++ b/src/Language/ErrM.hs
@@ -0,0 +1,37 @@
+-- BNF Converter: Error Monad
+-- Copyright (C) 2004  Author:  Aarne Ranta
+
+-- This file comes with NO WARRANTY and may be used FOR ANY PURPOSE.
+module Language.ErrM where
+
+-- the Error monad: like Maybe type with error msgs
+
+import Control.Monad (MonadPlus(..), liftM)
+import Control.Applicative (Applicative(..), Alternative(..))
+
+data Err a = Ok a | Bad String
+  deriving (Read, Show, Eq, Ord)
+
+instance Monad Err where
+  return      = Ok
+  fail        = Bad
+  Ok a  >>= f = f a
+  Bad s >>= _ = Bad s
+
+instance Applicative Err where
+  pure = Ok
+  (Bad s) <*> _ = Bad s
+  (Ok f) <*> o  = liftM f o
+
+
+instance Functor Err where
+  fmap = liftM
+
+instance MonadPlus Err where
+  mzero = Bad "Err.mzero"
+  mplus (Bad _) y = y
+  mplus x       _ = x
+
+instance Alternative Err where
+  empty = mzero
+  (<|>) = mplus
diff --git a/src/Language/Lex.x b/src/Language/Lex.x
new file mode 100644
--- /dev/null
+++ b/src/Language/Lex.x
@@ -0,0 +1,187 @@
+-- -*- haskell -*-
+-- This Alex file was machine-generated by the BNF converter
+{
+{-# OPTIONS -fno-warn-incomplete-patterns #-}
+{-# OPTIONS_GHC -w #-}
+module Language.Lex where
+
+
+
+import qualified Data.Bits
+import Data.Word (Word8)
+}
+
+
+$l = [a-zA-Z\192 - \255] # [\215 \247]    -- isolatin1 letter FIXME
+$c = [A-Z\192-\221] # [\215]    -- capital isolatin1 letter FIXME
+$s = [a-z\222-\255] # [\247]    -- small isolatin1 letter FIXME
+$d = [0-9]                -- digit
+$i = [$l $d _ ']          -- identifier character
+$u = [\0-\255]          -- universal: any character
+
+@rsyms =    -- symbols and non-identifier-like reserved words
+   \: | \[ | \] | \{ | \} | \( | \" | \) | \@ | \,
+
+:-
+"//" [.]* ; -- Toss single line comments
+"/*" ([$u # \*] | \*+ [$u # [\* \/]])* ("*")+ "/" ;
+
+$white+ ;
+@rsyms { tok (\p s -> PT p (eitherResIdent (TV . share) s)) }
+$d \. $d \. $d { tok (\p s -> PT p (eitherResIdent (T_VerIdent . share) s)) }
+\/ $l + { tok (\p s -> PT p (eitherResIdent (T_RouteIdent . share) s)) }
+
+$l $i*   { tok (\p s -> PT p (eitherResIdent (TV . share) s)) }
+
+
+
+
+
+{
+
+tok :: (Posn -> String -> Token) -> (Posn -> String -> Token)
+tok f p s = f p s
+
+share :: String -> String
+share = id
+
+data Tok =
+   TS !String !Int    -- reserved words and symbols
+ | TL !String         -- string literals
+ | TI !String         -- integer literals
+ | TV !String         -- identifiers
+ | TD !String         -- double precision float literals
+ | TC !String         -- character literals
+ | T_VerIdent !String
+ | T_RouteIdent !String
+
+ deriving (Eq,Show,Ord)
+
+data Token =
+   PT  Posn Tok
+ | Err Posn
+  deriving (Eq,Show,Ord)
+
+tokenPos :: [Token] -> String
+tokenPos (PT (Pn _ l _) _ :_) = "line " ++ show l
+tokenPos (Err (Pn _ l _) :_) = "line " ++ show l
+tokenPos _ = "end of file"
+
+tokenPosn :: Token -> Posn
+tokenPosn (PT p _) = p
+tokenPosn (Err p) = p
+
+tokenLineCol :: Token -> (Int, Int)
+tokenLineCol = posLineCol . tokenPosn
+
+posLineCol :: Posn -> (Int, Int)
+posLineCol (Pn _ l c) = (l,c)
+
+mkPosToken :: Token -> ((Int, Int), String)
+mkPosToken t@(PT p _) = (posLineCol p, prToken t)
+
+prToken :: Token -> String
+prToken t = case t of
+  PT _ (TS s _) -> s
+  PT _ (TL s)   -> s
+  PT _ (TI s)   -> s
+  PT _ (TV s)   -> s
+  PT _ (TD s)   -> s
+  PT _ (TC s)   -> s
+  PT _ (T_VerIdent s) -> s
+  PT _ (T_RouteIdent s) -> s
+
+
+data BTree = N | B String Tok BTree BTree deriving (Show)
+
+eitherResIdent :: (String -> Tok) -> String -> Tok
+eitherResIdent tv s = treeFind resWords
+  where
+  treeFind N = tv s
+  treeFind (B a t left right) | s < a  = treeFind left
+                              | s > a  = treeFind right
+                              | s == a = t
+
+resWords :: BTree
+resWords = b "]" 12 (b "@" 6 (b ")" 3 (b "(" 2 (b "\"" 1 N N) N) (b ":" 5 (b "," 4 N N) N)) (b "Long" 9 (b "Int" 8 (b "Double" 7 N N) N) (b "[" 11 (b "String" 10 N N) N))) (b "service_name" 18 (b "read_only" 15 (b "modules" 14 (b "enum" 13 N N) N) (b "resource" 17 (b "require" 16 N N) N)) (b "{" 21 (b "struct" 20 (b "service_version" 19 N N) N) (b "}" 22 N N)))
+   where b s n = let bs = id s
+                  in B bs (TS bs n)
+
+unescapeInitTail :: String -> String
+unescapeInitTail = id . unesc . tail . id where
+  unesc s = case s of
+    '\\':c:cs | elem c ['\"', '\\', '\''] -> c : unesc cs
+    '\\':'n':cs  -> '\n' : unesc cs
+    '\\':'t':cs  -> '\t' : unesc cs
+    '"':[]    -> []
+    c:cs      -> c : unesc cs
+    _         -> []
+
+-------------------------------------------------------------------
+-- Alex wrapper code.
+-- A modified "posn" wrapper.
+-------------------------------------------------------------------
+
+data Posn = Pn !Int !Int !Int
+      deriving (Eq, Show,Ord)
+
+alexStartPos :: Posn
+alexStartPos = Pn 0 1 1
+
+alexMove :: Posn -> Char -> Posn
+alexMove (Pn a l c) '\t' = Pn (a+1)  l     (((c+7) `div` 8)*8+1)
+alexMove (Pn a l c) '\n' = Pn (a+1) (l+1)   1
+alexMove (Pn a l c) _    = Pn (a+1)  l     (c+1)
+
+type Byte = Word8
+
+type AlexInput = (Posn,     -- current position,
+                  Char,     -- previous char
+                  [Byte],   -- pending bytes on the current char
+                  String)   -- current input string
+
+tokens :: String -> [Token]
+tokens str = go (alexStartPos, '\n', [], str)
+    where
+      go :: AlexInput -> [Token]
+      go inp@(pos, _, _, str) =
+               case alexScan inp 0 of
+                AlexEOF                   -> []
+                AlexError (pos, _, _, _)  -> [Err pos]
+                AlexSkip  inp' len        -> go inp'
+                AlexToken inp' len act    -> act pos (take len str) : (go inp')
+
+alexGetByte :: AlexInput -> Maybe (Byte,AlexInput)
+alexGetByte (p, c, (b:bs), s) = Just (b, (p, c, bs, s))
+alexGetByte (p, _, [], s) =
+  case  s of
+    []  -> Nothing
+    (c:s) ->
+             let p'     = alexMove p c
+                 (b:bs) = utf8Encode c
+              in p' `seq` Just (b, (p', c, bs, s))
+
+alexInputPrevChar :: AlexInput -> Char
+alexInputPrevChar (p, c, bs, s) = c
+
+-- | Encode a Haskell String to a list of Word8 values, in UTF8 format.
+utf8Encode :: Char -> [Word8]
+utf8Encode = map fromIntegral . go . ord
+ where
+  go oc
+   | oc <= 0x7f       = [oc]
+
+   | oc <= 0x7ff      = [ 0xc0 + (oc `Data.Bits.shiftR` 6)
+                        , 0x80 + oc Data.Bits..&. 0x3f
+                        ]
+
+   | oc <= 0xffff     = [ 0xe0 + (oc `Data.Bits.shiftR` 12)
+                        , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)
+                        , 0x80 + oc Data.Bits..&. 0x3f
+                        ]
+   | otherwise        = [ 0xf0 + (oc `Data.Bits.shiftR` 18)
+                        , 0x80 + ((oc `Data.Bits.shiftR` 12) Data.Bits..&. 0x3f)
+                        , 0x80 + ((oc `Data.Bits.shiftR` 6) Data.Bits..&. 0x3f)
+                        , 0x80 + oc Data.Bits..&. 0x3f
+                        ]
+}
diff --git a/src/Language/Par.y b/src/Language/Par.y
new file mode 100644
--- /dev/null
+++ b/src/Language/Par.y
@@ -0,0 +1,179 @@
+-- This Happy file was machine-generated by the BNF converter
+{
+{-# OPTIONS_GHC -fno-warn-incomplete-patterns -fno-warn-overlapping-patterns #-}
+module Language.Par where
+import Language.Abs
+import Language.Lex
+import Language.ErrM
+
+}
+
+%name pSpecification Specification
+%name pName Name
+%name pVersion Version
+%name pModules Modules
+%name pEnumType EnumType
+%name pStructType StructType
+%name pResource Resource
+%name pMode Mode
+%name pField Field
+%name pFType FType
+%name pAnnotation Annotation
+%name pEnumVal EnumVal
+%name pListEnumType ListEnumType
+%name pListField ListField
+%name pListStructType ListStructType
+%name pListResource ListResource
+%name pListEnumVal ListEnumVal
+%name pListAnnotation ListAnnotation
+%name pListIdent ListIdent
+
+-- no lexer declaration
+%monad { Err } { thenM } { returnM }
+%tokentype { Token }
+
+%token
+  '\"' { PT _ (TS _ 1) }
+  '(' { PT _ (TS _ 2) }
+  ')' { PT _ (TS _ 3) }
+  ',' { PT _ (TS _ 4) }
+  ':' { PT _ (TS _ 5) }
+  '@' { PT _ (TS _ 6) }
+  'Double' { PT _ (TS _ 7) }
+  'Int' { PT _ (TS _ 8) }
+  'Long' { PT _ (TS _ 9) }
+  'String' { PT _ (TS _ 10) }
+  '[' { PT _ (TS _ 11) }
+  ']' { PT _ (TS _ 12) }
+  'enum' { PT _ (TS _ 13) }
+  'modules' { PT _ (TS _ 14) }
+  'read_only' { PT _ (TS _ 15) }
+  'require' { PT _ (TS _ 16) }
+  'resource' { PT _ (TS _ 17) }
+  'service_name' { PT _ (TS _ 18) }
+  'service_version' { PT _ (TS _ 19) }
+  'struct' { PT _ (TS _ 20) }
+  '{' { PT _ (TS _ 21) }
+  '}' { PT _ (TS _ 22) }
+
+L_ident  { PT _ (TV $$) }
+L_VerIdent { PT _ (T_VerIdent $$) }
+L_RouteIdent { PT _ (T_RouteIdent $$) }
+
+
+%%
+
+Ident   :: { Ident }   : L_ident  { Ident $1 }
+VerIdent    :: { VerIdent} : L_VerIdent { VerIdent ($1)}
+RouteIdent    :: { RouteIdent} : L_RouteIdent { RouteIdent ($1)}
+
+Specification :: { Specification }
+Specification : Name Version Modules ListEnumType ListStructType ListResource { Spec $1 $2 $3 (reverse $4) $5 $6 } 
+
+
+Name :: { Name }
+Name : 'service_name' ':' Ident { Nm $3 } 
+
+
+Version :: { Version }
+Version : 'service_version' ':' VerIdent { Ver $3 } 
+
+
+Modules :: { Modules }
+Modules : {- empty -} { EmptyMods } 
+  | 'require' 'modules' '[' ListIdent ']' { Mods $4 }
+
+
+EnumType :: { EnumType }
+EnumType : 'enum' Ident '{' ListEnumVal '}' { DefEnum $2 $4 } 
+
+
+StructType :: { StructType }
+StructType : 'struct' Ident '{' ListField '}' { DefStr $2 $4 } 
+
+
+Resource :: { Resource }
+Resource : 'resource' Ident '(' '\"' RouteIdent '\"' ')' Mode { Res $2 $5 $8 } 
+
+
+Mode :: { Mode }
+Mode : 'read_only' { ReadOnly } 
+  | {- empty -} { Write }
+
+
+Field :: { Field }
+Field : ListAnnotation Ident ':' FType { FDef (reverse $1) $2 $4 } 
+
+
+FType :: { FType }
+FType : 'String' { FString } 
+  | 'Int' { FInt }
+  | 'Long' { FLong }
+  | 'Double' { FDouble }
+  | Ident { FDefined $1 }
+  | '[' FType ']' { FList $2 }
+
+
+Annotation :: { Annotation }
+Annotation : '@' Ident { Ann $2 } 
+
+
+EnumVal :: { EnumVal }
+EnumVal : Ident { EnVal $1 } 
+
+
+ListEnumType :: { [EnumType] }
+ListEnumType : {- empty -} { [] } 
+  | ListEnumType EnumType { flip (:) $1 $2 }
+
+
+ListField :: { [Field] }
+ListField : Field { (:[]) $1 } 
+  | Field ',' ListField { (:) $1 $3 }
+
+
+ListStructType :: { [StructType] }
+ListStructType : StructType { (:[]) $1 } 
+  | StructType ListStructType { (:) $1 $2 }
+
+
+ListResource :: { [Resource] }
+ListResource : Resource { (:[]) $1 } 
+  | Resource ListResource { (:) $1 $2 }
+
+
+ListEnumVal :: { [EnumVal] }
+ListEnumVal : EnumVal { (:[]) $1 } 
+  | EnumVal ',' ListEnumVal { (:) $1 $3 }
+
+
+ListAnnotation :: { [Annotation] }
+ListAnnotation : {- empty -} { [] } 
+  | ListAnnotation Annotation { flip (:) $1 $2 }
+
+
+ListIdent :: { [Ident] }
+ListIdent : Ident { (:[]) $1 } 
+  | Ident ListIdent { (:) $1 $2 }
+
+
+
+{
+
+returnM :: a -> Err a
+returnM = return
+
+thenM :: Err a -> (a -> Err b) -> Err b
+thenM = (>>=)
+
+happyError :: [Token] -> Err a
+happyError ts =
+  Bad $ "syntax error at " ++ tokenPos ts ++ 
+  case ts of
+    [] -> []
+    [Err _] -> " due to lexer error"
+    _ -> " before " ++ unwords (map (id . prToken) (take 4 ts))
+
+myLexer = tokens
+}
+
diff --git a/src/TypeCheck/ApiSpec.hs b/src/TypeCheck/ApiSpec.hs
new file mode 100644
--- /dev/null
+++ b/src/TypeCheck/ApiSpec.hs
@@ -0,0 +1,214 @@
+{-# LANGUAGE DeriveGeneric   #-}
+{-# LANGUAGE TemplateHaskell #-}
+-- | Defines an api spec (to be built after the static checking of the AST) and helper methods over
+-- it.
+module TypeCheck.ApiSpec where
+
+import           Control.Monad   (liftM)
+import           Data.DeriveTH
+import qualified Data.Map        as M
+import qualified Data.Set        as S
+import           Test.QuickCheck
+
+-- | Identifier of an enum, struct, field...
+type Id = String
+
+-- | The route of a resource.
+type Route = String
+
+-- | An enum value.
+type EnumValue = String
+
+-- | An enum is a list of values.
+type EnumInfo = [EnumValue]
+
+-- | A field modifier.
+data Modifier =
+    Hidden -- ^ The field will not be returned when read
+  | Immutable -- ^ The field cannot be modified
+  | Required -- ^ The field can't be absent
+  | PrimaryKey -- ^ The field is the primary key (thus 'Unique' as well)
+  | Unique -- ^ The field can't have repeated values throughout the collection
+  | UserLogin -- ^ The field value will contain the user's login
+  deriving (Eq, Ord, Show)
+
+derive makeArbitrary ''Modifier
+
+-- | A field has a type, an identifier and a set of modifiers.
+newtype FieldInfo = FI (Id, Type, S.Set Modifier) deriving (Show, Eq, Ord)
+
+-- | A struct is a list of fields.
+type StructInfo = [FieldInfo]
+
+-- | A resource has a route and a write mode.
+type ResourceInfo = (Route, Writable)
+
+-- | A type can be a primitive one (int, long, double, bool...), an enum, a struct, or a list of
+-- another type.
+data Type = TInt
+          | TLong
+          | TFloat
+          | TDouble
+          | TBool
+          | TString
+          | TEnum Id
+          | TStruct Id
+          | TList Type deriving (Eq, Ord, Show)
+
+instance (CoArbitrary Type) where
+  coarbitrary = coarbitraryShow
+
+-- | Map from enum id to its info.
+type Enums = M.Map Id EnumInfo
+
+-- | Map from struct id to its info.
+type Structs = [(Id, StructInfo)]
+
+-- | Map from resource id to the route and the mode.
+type Resources = M.Map Id ResourceInfo
+
+-- | Writable is a boolean type.
+type Writable = Bool
+
+-- | The spec of an api is a set of enums and structs, along with the resources.
+data ApiSpec = AS { name         :: String -- ^ Name of the service
+                  , version      :: String -- ^ Version of the service
+                  , requiresAuth :: Bool -- ^ Whether it should support authentication or not
+                  , enums        :: Enums -- ^ Information about the user defined enums
+                  , structs      :: Structs -- ^ Information about the user defined structs
+                  , resources    :: Resources -- ^ Information about the resources defined
+                  }
+
+derive makeShow ''ApiSpec
+
+-- | Gets the primary key of a struct if it was specified.
+getPrimaryKey :: StructInfo -- ^ The info of the struct
+              -> Maybe Id -- ^ The result (Nothing if there was no PK defined)
+getPrimaryKey structInfo =
+  case filter hasPkModifier structInfo of
+    [] -> Nothing
+    [FI (x, _, _)] -> Just x
+    _ -> error "A struct should have at most one specified primary key."
+  where
+    hasPkModifier (FI (_, _, modifiers)) = PrimaryKey `S.member` modifiers
+
+-- | Finds out if a fieldinfo is relative to a struct
+isStructField :: FieldInfo -> Bool
+isStructField (FI (_, t, _)) = isStruct t
+
+-- | Find outs if a type is a struct
+isStruct :: Type -> Bool
+isStruct (TStruct _) = True
+isStruct (TList t) = isStruct t
+isStruct _ = False
+
+-- | Get the name of a struct
+strName :: Type -> String
+strName (TStruct t) = t
+strName (TList t) = strName t
+strName other = error $ "strName of a non struct type (" ++ show other ++ ")"
+
+-- Testing
+
+-- | Generates a non-empty arbitrary 'String'.
+nonEmptyString :: Gen String
+nonEmptyString = listOf1 arbitrary
+
+-- | Generates an arbitrary 'FieldInfo', making sure that the ids used for enums and structs are valid.
+generateRandomFieldInfo :: [Id] -> [Id] -> Gen FieldInfo
+generateRandomFieldInfo enumIds structIds =
+  do
+    id <- nonEmptyString
+    t <- generateRandomType enumIds structIds
+    modifiers <- listOf arbitrary
+    return $ FI (id, t, S.fromList modifiers)
+  where
+    generateRandomType :: [Id] -> [Id] -> Gen Type
+    generateRandomType enumIds structIds = do
+      t <- arbitrary
+
+      case t of
+           (TStruct _) -> processStruct
+           (TEnum _) -> processEnum
+           (TList t') | needsEnumId t' ->
+                          if null enumIds
+                            then generateRandomType enumIds structIds
+                            else do
+                                newId <- elements enumIds
+                                return $ TList $ setNewId newId t'
+                      | needsStructId t' ->
+                          if null structIds
+                            then generateRandomType enumIds structIds
+                            else do
+                              newId <- elements structIds
+                              return $ TList $ setNewId newId t'
+                      | otherwise -> return $ TList t'
+           other -> return other
+      where
+        processEnum = if null enumIds
+                        then generateRandomType enumIds structIds
+                        else liftM TEnum $ elements enumIds
+        processStruct =  if null structIds
+                          then generateRandomType enumIds structIds
+                          else liftM TStruct $ elements structIds
+        needsEnumId (TEnum _) = True
+        needsEnumId (TList t) = needsEnumId t
+        needsEnumId _ = False
+
+        needsStructId (TStruct _) = True
+        needsStructId (TList t) = needsStructId t
+        needsStructId _ = False
+
+        setNewId newId' (TEnum _) = TEnum newId'
+        setNewId newId' (TStruct _) = TStruct newId'
+        setNewId newId' (TList t) = TList $ setNewId newId' t
+        setNewId _ t = t
+
+instance (Arbitrary ApiSpec) where
+  arbitrary = do
+    name' <- nonEmptyString
+    version' <- nonEmptyString
+    enumIds <- listOf nonEmptyString
+    enums' <- mapM createEnum enumIds
+    structIds <- listOf nonEmptyString
+    structs' <- mapM (createStruct enumIds structIds) structIds
+    resources' <- mapM (createResource . fst) structs'
+    return AS { name = name'
+              , version = version'
+              , requiresAuth = False
+              , enums = M.fromList enums'
+              , structs = structs'
+              , resources = M.fromList resources'
+              }
+    where
+      createEnum :: Id -> Gen (Id, EnumInfo)
+      createEnum id = do
+        values <- listOf1 nonEmptyString
+        return (id, values)
+
+      createStruct :: [Id] -> [Id] -> Id -> Gen (Id, StructInfo)
+      createStruct enumIds structIds thisStructId = do
+        rawFields <- listOf1 $ generateRandomFieldInfo enumIds structIds
+        shouldHavePk <- arbitrary
+        let fields = filterPrimaryKey shouldHavePk rawFields
+        return (thisStructId, fields)
+        where
+          filterPrimaryKey _ [] = []
+          filterPrimaryKey True (FI (id, t, mods):fs) | PrimaryKey `S.member` mods = FI (id, t, PrimaryKey `S.delete` mods) : filterPrimaryKey False fs
+          filterPrimaryKey True (FI (id, t, mods):fs) = FI (id, t, mods) : filterPrimaryKey True fs
+          filterPrimaryKey False (FI (id, t, mods):fs) = FI (id, t, PrimaryKey `S.delete` mods) : filterPrimaryKey False fs
+
+      createResource :: Id -> Gen (Id, ResourceInfo)
+      createResource id = do
+        route <- nonEmptyString
+        writable <- arbitrary
+        return (id, (route, writable))
+
+instance (Arbitrary Type) where
+  arbitrary = do
+    t <- elements [TInt, TLong, TFloat, TDouble, TBool, TString, TEnum "", TStruct "", TList TInt]
+    case t of
+         TEnum _ -> liftM TEnum nonEmptyString
+         TStruct _ -> liftM TStruct nonEmptyString
+         TList _ -> liftM TList arbitrary
+         other -> return other
diff --git a/src/TypeCheck/StaticCheck.hs b/src/TypeCheck/StaticCheck.hs
new file mode 100644
--- /dev/null
+++ b/src/TypeCheck/StaticCheck.hs
@@ -0,0 +1,229 @@
+-- | Static checking of the input file.
+module TypeCheck.StaticCheck (staticCheck) where
+
+import           Control.Arrow
+import           Control.Monad
+import           Control.Monad.State as CMS
+import           Data.Char
+import qualified Data.DiGraph        as DG
+import qualified Data.Foldable       as F
+import qualified Data.Map            as M
+import           Data.Maybe
+import qualified Data.Set            as S
+import           Language.Abs
+import           Language.ErrM
+import           LangUtils
+import qualified TypeCheck.ApiSpec   as AS
+
+
+type Env = ( S.Set String
+           , AS.ApiSpec
+           )
+
+type StaticCheck a = StateT Env Err a
+
+-- | List of reserved words.
+reservedWords :: [String]
+-- TODO(18): complete list
+reservedWords = ["Long", "Int", "String", "Resource", "Enum", "Struct"]
+
+-- | Initial environment (all empty).
+initialEnv :: Env
+initialEnv = (S.empty,
+              AS.AS { AS.name = ""
+                    , AS.version = ""
+                    , AS.requiresAuth = False
+                    , AS.enums = M.empty
+                    , AS.structs = []
+                    , AS.resources = M.empty
+                    }
+             )
+
+-- | Checks the definition for:
+--   * Name clashes
+--   * Undefined types
+-- and returns a better representation of the api spec.
+staticCheck :: Specification -> Err AS.ApiSpec
+staticCheck spec@(Spec _ _ modules enums structs resources) = do
+  (_, (_, apiSpec)) <- runStateT checkSeq initialEnv
+  return apiSpec
+  where
+    checkSeq = do
+      CMS.modify (\(strs, s) -> (strs, s { AS.name = specName spec, AS.version = specVersion spec }))
+      let enumNames = getEnumNames enums
+          structNames = getStructNames structs
+          customTypeNames = enumNames ++ structNames
+      checkClashes $ customTypeNames ++ reservedWords
+
+      CMS.modify (\(_, as) -> (S.fromList structNames, as))
+      readAndCheckEnums enums
+      addStructNames structs
+      processModules modules
+      readAndCheckStructs structs
+      checkResources resources
+      sortStructsByDependencyOrder
+
+-- | Looks for name clashes in the definitions.
+-- Note that it skips resources as those need to have the same name as some struct.
+checkClashes :: [String] -> StaticCheck ()
+checkClashes names =
+  case findDuplicates names of
+    Nothing -> return ()
+    Just name ->
+      fail $ "Name clash in declaration: "
+          ++ name
+          ++ " is declared more than once (or it is a reserved word)."
+
+-- | Reads all enums, making sure there are not repeated values.
+readAndCheckEnums :: [EnumType] -> StaticCheck ()
+readAndCheckEnums es = F.forM_ es checkEnumValues >> F.forM_ es readEnum
+  where
+    checkEnumValues :: EnumType -> StaticCheck ()
+    checkEnumValues (DefEnum _ vals) =
+      let duplicates = findDuplicates (map enumValName vals) in
+        unless (isNothing duplicates) (fail $ "Enum value defined more than once " ++ fromJust duplicates)
+    readEnum :: EnumType -> StaticCheck ()
+    readEnum (DefEnum (Ident name) vals) =
+      CMS.modify (\(structNames, as) ->
+                     (structNames, as { AS.enums = M.insert name (map enumValName vals) (AS.enums as)}))
+
+-- | Adds struct names (without information). Useful to check if a field is valid even if the type is a struct defined afterwards.
+addStructNames :: [StructType] -> StaticCheck ()
+addStructNames strs = F.forM_ strs addStr
+  where
+    addStr (DefStr (Ident strName) _) = CMS.modify $ Control.Arrow.first (S.insert strName)
+
+-- | Modifies the environment with the given modules
+processModules :: Modules -> StaticCheck ()
+processModules EmptyMods = return ()
+processModules (Mods moduleDefs) = void (F.forM_ moduleDefs processModule)
+  where
+    processModule :: Ident -> StaticCheck ()
+    processModule (Ident m) | map toLower m == "authentication"  = CMS.modify (\(structNames, as) -> (structNames, as { AS.requiresAuth = True }))
+                            | otherwise = fail $ "Error processing module: " ++ show m ++ " is not supported."
+
+-- | Makes sure all the types used in the struct definitions are valid.
+readAndCheckStructs :: [StructType] -> StaticCheck ()
+readAndCheckStructs strs = do
+  F.forM_ strs structOk
+  F.forM_ strs readStruct
+    where
+      structOk :: StructType -> StaticCheck ()
+      structOk (DefStr (Ident strName) fields) = do
+        names <- getAllNamesFromEnv
+        checkAttributeClashes fields (names `S.union` S.fromList reservedWords)
+        F.forM_ fields fieldOk
+        checkHasPk strName fields
+
+      checkAttributeClashes :: [Field] -> S.Set String -> StaticCheck (S.Set String)
+      checkAttributeClashes fields alreadySeen =
+        F.foldlM (\names name ->
+          if name `S.member` names
+          then fail $ "Field " ++ name
+                   ++ " is defined twice (or it is a reserved word/custom type name)"
+          else return $ name `S.insert` names) alreadySeen (map fieldName fields)
+
+      fieldOk :: Field -> StaticCheck ()
+      fieldOk (FDef _ _ (FDefined (Ident name))) = do
+        knownTypes <- getAllNamesFromEnv
+        unless (name `S.member` knownTypes)
+               (fail $ "The type (" ++ name ++ ") was not defined.")
+      fieldOk _ = return ()
+
+      checkHasPk :: String -> [Field] -> StaticCheck ()
+      checkHasPk strName fields = do
+        fieldsWithPk <- filterM (\f -> do
+          m <- readAnnotation f
+          return (m==AS.PrimaryKey)) $ concatMap fieldAnnotations fields
+        --unless (length (filter ((==AS.PrimaryKey) . readAnnotation) $ concatMap fieldAnnotations fields) <= 1)
+        unless (length fieldsWithPk <= 1)
+               (fail $ strName ++ " Primary Key annotation (@PK) is used more than once")
+
+      readStruct :: StructType -> StaticCheck ()
+      readStruct (DefStr (Ident name) fields) = do
+        enums <- getEnumNamesFromEnv
+        (strs, as) <- CMS.get
+        allFields <- mapM (readField (strs, enums)) fields
+        CMS.put (strs, as { AS.structs = (name, allFields):AS.structs as})
+      readAnnotation :: Annotation -> StaticCheck AS.Modifier
+      readAnnotation (Ann (Ident name)) | map toLower name == "hidden" = return AS.Hidden
+                                        | map toLower name == "pk" = return AS.PrimaryKey
+                                        | map toLower name == "unique" = return AS.Unique
+                                        | map toLower name == "immutable" = return AS.Immutable
+                                        | map toLower name == "required" = return AS.Required
+                                        | map toLower name == "userlogin" = do
+                                          as <- CMS.gets snd
+                                          if AS.requiresAuth as
+                                          then return AS.UserLogin
+                                          else fail "The UserLogin annotation requires the module \"Authentication\""
+                                        | otherwise = fail $ "Annotation " ++ name ++ " not recognized."
+      readField envInfo (FDef anns (Ident n) ft) = do
+        allAnnotations <- mapM readAnnotation anns
+        return $ AS.FI (n, fieldSpecType envInfo ft, S.fromList allAnnotations)
+
+-- | Gets enum names from the environment.
+getEnumNamesFromEnv :: StaticCheck (S.Set String)
+getEnumNamesFromEnv = do
+  as <- CMS.gets snd
+  return $ S.fromList (map fst $ M.toList $ AS.enums as)
+
+-- | Gets the names (identifiers) of all structs and enums (form the environment).
+getAllNamesFromEnv :: StaticCheck (S.Set String)
+getAllNamesFromEnv = do
+  (strNames, as) <- CMS.get
+  return $ strNames `S.union` S.fromList (map fst $ M.toList $ AS.enums as)
+
+checkResources :: [Resource] -> StaticCheck ()
+checkResources ress = do
+  checkDifferentRoutes ress
+  F.forM_ ress resourceOk
+  F.forM_ ress addResource
+  where
+    checkDifferentRoutes ress =
+      case findDuplicates (map resRoute ress) of
+           Nothing -> case findDuplicates (map resName ress) of
+                        Nothing -> return ()
+                        (Just repeated') -> fail $ "Struct " ++ repeated' ++ " is referred more than once by a resource."
+           (Just repeated) -> fail $ "Route " ++ repeated ++ " is defined more than once"
+    resourceOk res = do
+      definedStructs <- CMS.gets (\(_, as) -> AS.structs as)
+      unless (isJust $ lookup (resName res) definedStructs)
+             (fail $ "Resource " ++ resName res ++ " does not refer to a defined struct.")
+    addResource res = CMS.modify (\(names, as) -> (names, as { AS.resources = M.insert (resName res) (resRoute res, resIsWritable res) (AS.resources as)}))
+
+getEnumNames :: [EnumType] -> [String]
+getEnumNames = map enumName
+
+getStructNames :: [StructType] -> [String]
+getStructNames = map strName
+
+findDuplicates :: [String] -> Maybe String
+findDuplicates list = go list S.empty S.empty
+  where
+    go [] _ _ = Nothing
+    go (x:_) seen _ | lowerCaseStr x `S.member` seen = return x
+    go (x:xs) seen repeatedSet = go xs (lowerCaseStr x `S.insert` seen) repeatedSet
+    lowerCaseStr :: String -> String
+    lowerCaseStr = map toLower
+
+-- | Builds a dependency graph to sort the structs so forall a,b -> if "a" depends on "b", "b" is
+-- first in the list. It fails if there is a cycle in the graph.
+sortStructsByDependencyOrder :: StaticCheck ()
+sortStructsByDependencyOrder = do
+  apiSpec <- CMS.gets snd
+  let g = createGraph apiSpec
+  unless (not $ DG.hasCycle g) (fail "There is a cycle in the struct definitions")
+  let priorityList = DG.generateInverseDependencyList g
+  let sortedStructs = matchOrder priorityList (AS.structs apiSpec)
+  CMS.modify (\(ns, as) -> (ns, as { AS.structs = sortedStructs }))
+    where
+      createGraph :: AS.ApiSpec -> DG.Graph AS.Id
+      createGraph apiSpec = foldl (\g str -> DG.addNeighbors (fst str) (getDeps str) g) DG.empty (AS.structs apiSpec)
+        where
+          getDeps (_, fields) = map (\(AS.FI (_, t, _)) -> AS.strName t) $ filter AS.isStructField fields
+      matchOrder :: Eq a => [a] -> [(a, b)] -> [(a,b)]
+      matchOrder pList list = go pList list []
+        where
+          go :: Eq a => [a] -> [(a, b)] -> [(a, b)] -> [(a, b)]
+          go [] _ acc = reverse acc
+          go (x:xs) list acc = go xs list ((x, fromJust (lookup x list)):acc)
diff --git a/templates/client/python/client.tpl b/templates/client/python/client.tpl
new file mode 100644
--- /dev/null
+++ b/templates/client/python/client.tpl
@@ -0,0 +1,79 @@
+import requests, json
+{{#schema}}
+
+class {{schemaName}}:
+
+    def __init__(self, {{#schemaVars}}{{varName}} = None, {{/schemaVars}}):
+        self._info = {}
+{{#schemaVars}}
+{{#isStruct}}
+{{#isList}}
+        self._info["{{varName}}"] = map((lambda x: x if (isinstance(x, dict) or isinstance(x, list)) else x.toDict()), {{varName}})
+{{/isList}}
+{{^isList}}
+        self._info["{{varName}}"] = {{varName}}.toDict()
+{{/isList}}
+{{/isStruct}}
+{{^isStruct}}
+        self._info["{{varName}}"] = {{varName}}
+{{/isStruct}}
+{{/schemaVars}}
+
+    @staticmethod
+    def fromDict(dict):
+      return {{schemaName}}({{#schemaVars}}dict["{{varName}}"],{{/schemaVars}})
+    
+    def toDict(self):
+      return self._info
+
+    @staticmethod
+    def fromJSON(text):
+        return {{schemaName}}.fromDict(json.loads(text))
+
+    def toJSON(self):
+        return json.dumps(self._info)
+{{#schemaVars}}
+
+    def get_{{varName}}(self):
+        return self._info["{{varName}}"]
+
+    def set_{{varName}}(self, {{varName}}):
+        self._info["{{varName}}"] = {{varName}}
+{{/schemaVars}}
+{{/schema}}
+
+{{#requiresAuth}}
+def login(url, login, password):
+  return requests.post(url + "/u_auth" + "/" + login + "/" + password)
+
+def register(url , login, password):
+  return requests.post(url + "/u_auth/register", data=json.dumps({'login' : login, 'password': password}), headers = {'content-type': 'application/json'})
+{{/requiresAuth}}
+
+{{#schema}}{{#schemaRoute}}
+
+def get{{schemaName}}_list(url{{#requiresAuth}}, token{{/requiresAuth}}):
+    return requests.get(url + "{{&value}}"{{#requiresAuth}}+ "/" + token{{/requiresAuth}})
+
+def get{{schemaName}}(url, item_id{{#requiresAuth}}, token{{/requiresAuth}}):
+    return requests.get(url + "{{&value}}" + "/" + item_id{{#requiresAuth}}+ "/" + token{{/requiresAuth}})
+{{#writable}}
+
+{{#hasKeyField}}
+
+def put{{schemaName}}(url, item{{#requiresAuth}}, token{{/requiresAuth}}):
+    return requests.put(url + "{{&value}}" + "/" + item.get_{{keyField}}(){{#requiresAuth}}+ "/" + token{{/requiresAuth}}, data=item.toJSON(), headers = {'content-type': 'application/json'})
+{{/hasKeyField}}
+
+def put{{schemaName}}(url, item_id, item{{#requiresAuth}}, token{{/requiresAuth}}):
+    return requests.put(url + "{{&value}}" + "/" + item_id{{#requiresAuth}}+ "/" + token{{/requiresAuth}}, data=item.toJSON(), headers = {'content-type': 'application/json'})
+{{^hasKeyField}}
+
+def post{{schemaName}}(url, item{{#requiresAuth}}, token{{/requiresAuth}}):
+    return requests.post(url + "{{&value}}"{{#requiresAuth}}+ "/" + token{{/requiresAuth}}, data=item.toJSON(), headers = {'content-type': 'application/json'})
+{{/hasKeyField}}
+
+def delete{{schemaName}}(url, item_id{{#requiresAuth}}, token{{/requiresAuth}}):
+    return requests.delete(url + "{{&value}}" + "/" + item_id{{#requiresAuth}}+ "/" + token{{/requiresAuth}})
+{{/writable}}
+{{/schemaRoute}}{{/schema}}
diff --git a/templates/client/python/test.tpl b/templates/client/python/test.tpl
new file mode 100644
--- /dev/null
+++ b/templates/client/python/test.tpl
@@ -0,0 +1,168 @@
+from client import *
+from hypothesis import *
+from hypothesis.searchstrategy.collections import *
+from hypothesis.specifiers import * 
+import unittest
+import copy
+import sys
+
+def is_valid_id_string(id_string):
+  return len(id_string) > 0 \
+         and len(id_string) < 20 \
+         and all(map(lambda x: (ord(x) >= 65 and ord(x) <= 90) or (ord(x) >= 97 and ord(x) <= 122), id_string))
+
+class ServiceTest(unittest.TestCase):
+
+    def assertEqual(self, item1, item2):
+        i1 = copy.deepcopy(item1)
+        i2 = copy.deepcopy(item2)
+        if type(i1) != type(i2):
+            t1 = type(i1).__name__
+            t2 = type(i2).__name__
+            # str and unicode can be treated as the same type
+            if not ((t1 == "unicode" and t2 == "str") or (t1 == "str" and t2 == "unicode")):
+                self.fail("Different types ("+ type(i1).__name__ + "," + type(i2).__name__ + ")")
+        if isinstance(i1, dict):
+            self.assertEquals_dict(i1, i2)
+        elif isinstance(i1, list):
+            self.assertEquals_list(i1, i2)
+        else:  
+            super(ServiceTest, self).assertEqual(i1, i2)
+ 
+    def assertEquals_dict(self, d1, d2):
+        self.rm_id_key(d1)
+        self.rm_id_key(d2)
+        super(ServiceTest, self).assertEqual(d1, d2)
+
+    def assertEquals_list(self, l1, l2):
+        i1 = map(self.rm_id_key, l1)
+        i2 = map(self.rm_id_key, l2)
+        i1.sort()
+        i2.sort()
+        for i in range(len(i1)):
+            self.assertEqual(i1[i], i2[i])
+
+    def rm_id_key(self, item):
+        if not isinstance(item, dict):
+            return item
+        if "id" in item:
+            item.pop("id", None)
+        return item
+
+Settings.default.max_examples = 10000
+Settings.default.timeout = 3
+Settings.default.average_list_length = 3
+
+{{#schema}}
+{{schemaName}}Data = {
+{{#schemaVars}}
+{{#isEnum}}
+  '{{varName}}': {{#isList}}[{{/isList}}sampled_from([{{#values}}"{{value}}", {{/values}}]){{#isList}}]{{/isList}},
+{{/isEnum}}
+{{^isEnum}}
+{{^isKey}}
+  '{{varName}}': {{&varType}}, 
+{{/isKey}}
+{{/isEnum}}
+{{/schemaVars}}
+}
+{{/schema}}
+
+{{#schema}}
+{{#schemaRoute}}
+class Test{{schemaName}}(ServiceTest):
+  @given({{#schemaVars}}{{#isKey}}{{&varType}}, {{/isKey}}{{/schemaVars}}{{schemaName}}Data, {{schemaName}}Data{{#requiresAuth}}, strategy([strategy(integers_in_range(65,90)) | strategy(integers_in_range(97, 122))]).map(lambda l: map(chr, l)).map(lambda l: ''.join(l)){{/requiresAuth}})
+  def test_insert_edit_delete(self, {{#hasKeyField}}id, {{/hasKeyField}}data, data2{{#requiresAuth}}, userData{{/requiresAuth}}):
+{{#schemaVars}}
+{{#isUserLogin}}
+{{#isKey}}
+    assume(is_valid_id_string(userData))
+    id = userData
+{{/isKey}}
+{{^isKey}}
+    {{varName}} = userData
+{{/isKey}}
+{{/isUserLogin}}
+{{^isUserLogin}}
+{{#isKey}}
+    assume(is_valid_id_string(id))
+    {{varName}} = id
+{{/isKey}}
+{{^isKey}}
+    {{varName}} = data["{{varName}}"]
+{{/isKey}}
+{{/isUserLogin}}
+{{/schemaVars}}
+{{#requiresAuth}}
+    assume(is_valid_id_string(userData))
+    registerResponse = register(url, userData, userData)
+    authResponse = login(url, userData, userData)
+    self.assertEqual(authResponse.status_code, 200);
+    token = json.loads(authResponse.text)['token']
+{{/requiresAuth}}
+{{#hasKeyField}}
+
+    putResponse = put{{schemaName}}(url, id, {{schemaName}}({{#schemaVars}}{{^isUserLogin}}{{varName}} = {{varName}},{{/isUserLogin}} {{/schemaVars}}){{#requiresAuth}},token{{/requiresAuth}})
+    self.assertEqual(200, putResponse.status_code)
+{{/hasKeyField}}
+{{^hasKeyField}}
+    postResponse = post{{schemaName}}(url, {{schemaName}}({{#schemaVars}}{{^isUserLogin}}{{varName}} = {{varName}},{{/isUserLogin}} {{/schemaVars}}){{#requiresAuth}},token{{/requiresAuth}})
+    self.assertEqual(201, postResponse.status_code)
+    id = json.loads(postResponse.text)["id"]
+{{/hasKeyField}}
+{{#schemaVars}}
+{{^isKey}}
+    self.assertEqual({{varName}}, {{schemaName}}.fromJSON(get{{schemaName}}(url, id{{#requiresAuth}},token{{/requiresAuth}}).text).get_{{varName}}())
+{{/isKey}}
+{{/schemaVars}}
+
+{{#schemaVars}}
+{{#isUserLogin}}
+    {{varName}} = userData
+{{/isUserLogin}}
+{{^isUserLogin}}
+{{#isKey}}
+    {{varName}} = id
+{{/isKey}}
+{{^isKey}}
+    {{varName}} = data["{{varName}}"]
+{{/isKey}}
+{{/isUserLogin}}
+{{/schemaVars}}
+
+    putResponse = put{{schemaName}}(url, id, {{schemaName}}({{#schemaVars}}{{varName}}, {{/schemaVars}}){{#requiresAuth}},token{{/requiresAuth}})
+    self.assertEqual(200, putResponse.status_code)
+{{#schemaVars}}
+{{^isKey}}
+    self.assertEqual({{varName}}, {{schemaName}}.fromJSON(get{{schemaName}}(url, id{{#requiresAuth}},token{{/requiresAuth}}).text).get_{{varName}}())
+{{/isKey}}
+{{/schemaVars}}
+
+    deleteResponse = delete{{schemaName}}(url, id{{#requiresAuth}},token{{/requiresAuth}})
+    self.assertEqual(200, deleteResponse.status_code)
+
+    getAfterDeleteResponse = get{{schemaName}}(url, id{{#requiresAuth}},token{{/requiresAuth}})
+    self.assertEqual(404, getAfterDeleteResponse.status_code)
+
+{{/schemaRoute}}
+{{/schema}}
+
+{{#requiresAuth}}
+class LoginTest(ServiceTest):
+  @given(strategy([strategy(integers_in_range(65,90)) | strategy(integers_in_range(97, 122))]).map(lambda l: map(chr, l)).map(lambda l: ''.join(l)))
+  def login_test(self, userData):
+    register = register(url, userData, userData)
+    correctLoginResponse = login(url, userData, userData)
+    assertEqual(200, correctLoginResponse.status_code)
+    assertTrue(len(json.loads(correctLoginResponse.text)['token']) > 0)
+    incorrectLoginResponse = login(url, userData, userData + "XYZ")
+    assertEqual(401, incorrectLoginResponse.status_code)
+{{/requiresAuth}}
+
+if __name__ == '__main__':
+    if len(sys.argv) != 2:
+        print("Url must be specified. Example: python tests.py http://localhost:3000")
+    else:
+        url = sys.argv[1]
+        del sys.argv[1]
+        unittest.main(argv = None)
diff --git a/templates/server/js/package.tpl b/templates/server/js/package.tpl
new file mode 100644
--- /dev/null
+++ b/templates/server/js/package.tpl
@@ -0,0 +1,10 @@
+{
+  "name": "{{name}}",
+  "version" : "{{version}}",
+  "dependencies": {
+    "express": ">= 4.12.0",
+    "body-parser" : "1.12.0",
+    "mongoose": "4.0.1"
+  },
+  "engine": "node 0.12.0"
+}
diff --git a/templates/server/js/server.tpl b/templates/server/js/server.tpl
new file mode 100644
--- /dev/null
+++ b/templates/server/js/server.tpl
@@ -0,0 +1,247 @@
+var express = require('express'),
+    bodyParser = require('body-parser'),
+    mongoose = require('mongoose'),
+    app = express(),
+    args = process.argv.slice(2);
+
+app.use(bodyParser.json());
+
+mongoose.connect(args[1]);
+
+{{#requiresAuth}}
+// User registration and authentication
+var UserAutoGeneratedSchema = new mongoose.Schema({
+  login : { type: String, required: true, unique: true, index: true, dropDupes: true },
+  password: { type: String, required: true },
+});
+
+UserAutoGeneratedSchema.set('toJSON', {
+  transform: function (doc, ret, options) {
+    delete ret._id
+    delete ret.__v
+    delete ret.password
+  }
+});
+
+var UserAutoGenerated = mongoose.model('UserAutoGenerated', UserAutoGeneratedSchema);
+
+app.post('/u_auth/register', function (req, res) {
+  UserAutoGenerated.create(new UserAutoGenerated(req.body), function(err, obj) {
+    if (err) {
+      console.log("Error registering: ", err);
+      res.status(500).send(err);
+      return; 
+    }
+    res.status(201).send();
+   });
+});
+
+app.post('/u_auth/:login/:password', function (req, res) {
+  UserAutoGenerated.find({ login: req.params.login }, function(err, result) {
+      if (err) {
+        console.log(err);
+        res.status(500).send(err);
+        return;
+      }
+      if (result.length == 0) {
+        res.status(401).send('Invalid credentials');
+      } else {
+        if (result[0].password != req.params.password) {
+          res.status(401).send('Invalid credentials');
+        } else {
+          var t = generateToken(req.params.login)
+          addSession(t, req.params.login, function() {
+            res.status(200).json({token: t});
+          });
+        }
+      }
+  });
+});
+
+var SessionAutoGeneratedSchema = new mongoose.Schema({
+  token : { type: String, required: true, unique: true, index: true, dropDupes: true },
+  login : { type: String, required: true, unique: true, dropDupes: true }
+});
+
+var SessionAutoGenerated = mongoose.model('SessionAutoGenerated', SessionAutoGeneratedSchema);
+
+var addSession = function(newToken, referredLogin, callback) {
+ SessionAutoGenerated.update({token : newToken}, {login: referredLogin}, {upsert: true}, callback); 
+}
+
+var assertSessionCorrect = function(t, res, callback) {
+ SessionAutoGenerated.findOne({token: t}, function(err, result) {
+   if (err) {
+     console.log("Error asserting user token is correct: ", err);
+     res.status(500).send(err);
+     return;
+   }
+   if(result == null || result.login == null) {
+     console.log("Token " + t + " was not found");
+     res.status(401).send("Invalid credentials.");
+     return;
+  }
+   callback(result.login);
+ });
+}
+
+var generateToken = function(login) {
+  //TODO implement
+  return login;
+}
+{{/requiresAuth}}
+
+{{#schema}}
+var {{schemaName}}Schema = new mongoose.Schema({
+{{#schemaVars}}{{#isList}}
+  {{varName}} : { type: [{{#isStruct}}{{varType}}Schema{{/isStruct}}{{^isStruct}}{{varType}}{{/isStruct}}]
+               {{/isList}}{{^isList}}
+  {{varName}} : { type: {{#isStruct}}{{varType}}Schema{{/isStruct}}{{^isStruct}}{{varType}}{{/isStruct}}
+               {{/isList}} {{#isUnique}}, unique : true {{/isUnique}}{{#isKey}}, index: true, dropDupes: true {{/isKey}} {{#isRequired}}, required: true {{/isRequired}} {{#isEnum}}, enum: [{{/isEnum}}{{#isEnum}}{{#values}}'{{value}}',{{/values}}{{/isEnum}}{{#isEnum}}]{{/isEnum}}{{/isStruct}} },
+{{/schemaVars}}
+});
+
+{{schemaName}}Schema.set('toJSON', {
+  transform: function (doc, ret, options) {
+    {{^hasKeyField}}ret.id = ret._id{{/hasKeyField}}
+    {{#schemaVars}}{{#isHidden}}delete ret.{{varName}};{{/isHidden}}{{/schemaVars}}
+    delete ret._id
+    delete ret.__v
+  }
+});
+
+{{^hasKeyField}}
+{{schemaName}}Schema.set('toObject', {
+  transform : function (doc, ret, options) {
+    ret._id = ret.id
+    delete ret.id
+  }
+});
+{{/hasKeyField}}
+
+var {{schemaName}} = mongoose.model('{{schemaName}}', {{schemaName}}Schema);
+
+{{/schema}}
+
+{{#schema}}
+{{#schemaRoute}}
+app.get('{{&value}}{{#requiresAuth}}/:token{{/requiresAuth}}', function(req, res) {
+{{#requiresAuth}}
+  assertSessionCorrect(req.params.token, res, function(userLogin) {
+{{/requiresAuth}}
+        {{schemaName}}.find(function(err, result) {
+          if (err) {
+            res.status(500).send(err);  
+          } else {
+            res.send(result); 
+          }   
+         });
+{{#requiresAuth}}
+});
+{{/requiresAuth}}
+});
+
+app.get('{{&value}}/:id{{#requiresAuth}}/:token{{/requiresAuth}}', function(req, res) {
+  {{^hasKeyField}}
+  if (!req.params.id.match(/^[0-9a-fA-F]{24}$/)) {
+    res.status(404).send();
+    return;
+  }
+  {{/hasKeyField}}
+{{#requiresAuth}}
+  assertSessionCorrect(req.params.token, res, function(userLogin) {
+{{/requiresAuth}}
+        {{schemaName}}.find({ {{#hasKeyField}}{{keyField}}{{/hasKeyField}}{{^hasKeyField}}_id{{/hasKeyField}}: req.params.id }, function(err, result) {
+          if (err) {
+            res.status(500).send(err);
+            return;
+            }
+          if (result.length == 0) {
+            res.status(404).send('Not Found');
+          } else {
+            res.send(result[0]);
+          }
+        });
+{{#requiresAuth}}
+});
+{{/requiresAuth}}
+});
+
+{{#writable}}
+{{^hasKeyField}}
+app.post('{{&value}}{{#requiresAuth}}/:token{{/requiresAuth}}', function(req, res) {
+{{#requiresAuth}}
+  assertSessionCorrect(req.params.token, res, function(userLogin) {
+{{/requiresAuth}}
+{{#schemaVars}}
+{{#isUserLogin}}
+req.body.{{varName}} = userLogin;
+{{/isUserLogin}}
+{{/schemaVars}}
+  {{schemaName}}.create(new {{schemaName}}(req.body), function(err, obj) {
+    if (err) {
+      res.status(500).send(err);
+      return;  
+    }
+    res
+      .status(201)
+      .json({id : obj._id});
+   });
+{{#requiresAuth}}
+});
+{{/requiresAuth}}
+});
+{{/hasKeyField}}
+
+app.put('{{&value}}/:id{{#requiresAuth}}/:token{{/requiresAuth}}', function(req, res) {
+  {{^hasKeyField}}
+  if (!req.params.id.match(/^[0-9a-fA-F]{24}$/)) {
+    res.status(404).send();
+    return;
+  }
+  {{/hasKeyField}}
+{{#requiresAuth}}
+  assertSessionCorrect(req.params.token, res, function(userLogin) {
+{{/requiresAuth}}
+{{#schemaVars}}
+{{#isUserLogin}}
+req.body.{{varName}} = userLogin;
+{{/isUserLogin}}
+{{/schemaVars}}
+  {{schemaName}}.update({ {{#hasKeyField}}{{keyField}}{{/hasKeyField}}{{^hasKeyField}}_id{{/hasKeyField}} : req.params.id }, req.body, {upsert : true, runValidators : true}, function(err, result) {
+    if (err) {
+      res.status(500).send(err);
+    } else {
+      res.status(200).send();
+    }
+  });
+{{#requiresAuth}}
+});
+{{/requiresAuth}}
+});
+
+app.delete('{{&value}}/:id{{#requiresAuth}}/:token{{/requiresAuth}}', function(req, res) {
+  {{^hasKeyField}}
+  if (!req.params.id.match(/^[0-9a-fA-F]{24}$/)) {
+    res.status(404).send();
+    return;
+  }
+  {{/hasKeyField}}
+{{#requiresAuth}}
+  assertSessionCorrect(req.params.token, res, function(userLogin) {
+{{/requiresAuth}}
+  {{schemaName}}.remove({ {{#hasKeyField}}{{keyField}}{{/hasKeyField}}{{^hasKeyField}}_id{{/hasKeyField}}: req.params.id}, function(err, result) {
+      if (err) { 
+        res.status(500).send(err);
+        return;
+    }});
+    res.status(200).send();
+{{#requiresAuth}}
+});
+{{/requiresAuth}}
+});
+{{/writable}}
+{{/schemaRoute}}
+{{/schema}}
+
+app.listen(args[0]);
diff --git a/test/HLint.hs b/test/HLint.hs
new file mode 100644
--- /dev/null
+++ b/test/HLint.hs
@@ -0,0 +1,16 @@
+module Main (main) where
+
+import           Language.Haskell.HLint (hlint)
+import           System.Exit            (exitFailure, exitSuccess)
+
+arguments :: [String]
+arguments =
+    [ "harmony-commandline"
+    , "src"
+    , "test"
+    ]
+
+main :: IO ()
+main = do
+    hints <- hlint arguments
+    if null hints then exitSuccess else exitFailure
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,1 @@
+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
