diff --git a/.gitignore b/.gitignore index 085e3b71..fdbf6974 100644 --- a/.gitignore +++ b/.gitignore @@ -4,9 +4,15 @@ *.swp /pkg Makefile -lib/racc/parser-text.rb +lib/racc/grammar_file_scanner.rb tags tmp target lib/racc/cparse-jruby.jar racc.gemspec +TAGS + +# For Bundler +.bundle +Gemfile.lock +Gemfile.local diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..d7d2d50d --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,12 @@ +AllCops: + Exclude: + - Gemfile + +Lint/AssignmentInCondition: + Enabled: false + +Style/Semicolon: + Enabled: false + +Style/TrivialAccessors: + AllowPredicates: true \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 442c46d1..100b0b3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,18 +1,25 @@ --- -after_script: -- rake travis:after -t -before_script: -- gem install hoe-travis --no-rdoc --no-ri -- rake travis:before -t +dist: xenial + +cache: + - bundler + - directories: + - /home/travis/.rvm/ language: ruby -notifications: - email: + rvm: -- 1.8.7 -- 1.9.3 -- 2.0.0 -- ruby-head -script: rake travis + - 2.4.6 + - 2.5.5 + - 2.6.3 + - jruby-9.2.7.0 + - ruby-head + matrix: + fast_finish: true allow_failures: - rvm: ruby-head + - rvm: jruby-9.2.7.0 + +install: + - bundle install --retry 3 +script: ./test/run_tests.sh diff --git a/COPYING b/COPYING index c4792dd2..00e3e0db 100644 --- a/COPYING +++ b/COPYING @@ -1,515 +1,22 @@ - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations -below. - - When we speak of free software, we are referring to freedom of use, -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 this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. -^L - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it -becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. -^L - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control -compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. -^L - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. -^L - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. -^L - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. -^L - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -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 -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply, and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License -may add an explicit geographical distribution limitation excluding those -countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser 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 Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. -^L - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "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 -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY 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 -LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS -^L - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms -of the ordinary General Public License). - - To apply these terms, attach the following notices to the library. -It is safest to attach them to the start of each source file to most -effectively convey the exclusion of warranty; and each file should -have at least the "copyright" line and a pointer to where the full -notice is found. - - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper -mail. - -You should also get your employer (if you work as a programmer) or -your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James -Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - +Copyright (C) 2019 Yukihiro Matsumoto. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index 762b5ee7..00000000 --- a/ChangeLog +++ /dev/null @@ -1,846 +0,0 @@ -Tue Feb 20 18:45:45 2007 Minero Aoki - - * lib/racc/grammar.rb (separated_by): last commit was wrong. use - optional default return value of #option. - -Tue Feb 20 18:27:48 2007 Minero Aoki - - * lib/racc/grammar.rb (separated_by): return [] for empty list. - -Tue Nov 7 07:13:47 2006 Minero Aoki - - * lib/racc/grammar.rb (Rule#prec): rule.prec{...} should set - action. - -Tue Nov 7 06:38:57 2006 Minero Aoki - - * lib/racc/grammar.rb: system call error on writing log file - should be ignored. - - * lib/racc/grammar.rb: never define lvar which have same name with - block local variable. - - * lib/racc/iset.rb: ditto. - - * lib/racc/logfilegenerator.rb: ditto. - - * lib/racc/parser.rb: ditto. - - * lib/racc/state.rb: ditto. - - * lib/racc/statetransitiontable.rb: ditto. - - * test/test.rb: racc -c is obsolete, use --line-convert-all. - -Sun Oct 29 13:27:30 2006 Minero Aoki - - * lib/racc/grammarfileparser.rb: use String#lines instead of - #to_a. - - * lib/racc/parserfilegenerator.rb: ditto. - - * lib/racc/compat.rb: provide Object#__send. - - * lib/racc/compat.rb: provide Object#__send!. - - * lib/racc/compat.rb: provide String#lines. - -Thu Aug 24 23:14:16 2006 Minero Aoki - - * lib/racc/grammar.rb: report conflicts/useless if $DEBUG. - - * lib/racc/statetransitiontable.rb: remove code for Ruby 1.4 - compatibility. - -Fri Aug 4 01:02:36 2006 Minero Aoki - - * lib/racc/grammar.rb: #should_terminal should be called in - #check_terminals. - -Fri Aug 4 00:44:56 2006 Minero Aoki - - * bin/racc: getopts -> optparse. - - * lib/racc/grammar.rb: value of error symbol is :error. - - * lib/racc/grammar.rb (check_terminals): string symbols are - terminal. - - * lib/racc/grammarfileparser.rb (add_rule_block): specified-prec - did not work. - -Fri Aug 4 00:29:53 2006 Minero Aoki - - * lib/racc/parserfilegenerator.rb - (serialize_integer_list_compressed): fix typo. - -Thu Aug 3 22:20:34 2006 Minero Aoki - - * bin/y2racc: fix filename. - -Thu Aug 3 21:10:48 2006 Minero Aoki - - * bin/y2racc: getopts -> optparse. - -Thu Aug 3 19:35:34 2006 Minero Aoki - - * setup.rb: updated. - -Thu Aug 3 19:34:55 2006 Minero Aoki - - * bin/racc2y: getopts -> optparse. - - * bin/racc2y: rewrite code for new generator. - - * lib/racc/grammar.rb (_regist): did not check @delayed rules (it - causes registering same dummy rules many times). - - * lib/racc/grammarfileparser.rb: refactoring: simplify syntax. - - * lib/racc/grammarfileparser.rb: new method - GrammarFileParser.parse. - - * lib/racc/grammarfileparser.rb: new method - GrammarFileParser.parse_file. - -Sat Jul 29 04:51:42 2006 Minero Aoki - - * lib/racc/pre-setup: We need not make grammarfileparser.rb. - -Sat Jul 29 04:30:33 2006 Minero Aoki - - * lib/racc/grammar.rb: allow '|' operation with meta rules - (many, option...). - -Sat Jul 29 03:17:20 2006 Minero Aoki - - * lib/racc/grammar.rb (Grammar#parser_class): write log file when - $DEBUG=true. - - * lib/racc/grammar.rb (Grammar.define): run block on a - Racc::Grammar::DefinitionEnv object, instead of a Racc::Grammar - object. - - * lib/racc/grammar.rb (DefinitionEnv): new method #null. - - * lib/racc/grammar.rb (DefinitionEnv): new method #many. - - * lib/racc/grammar.rb (DefinitionEnv): new method #many1. - - * lib/racc/grammar.rb (DefinitionEnv): new method #option. - - * lib/racc/grammar.rb (DefinitionEnv): new method #seperated_by. - - * lib/racc/grammar.rb (DefinitionEnv): new method #seperated_by1. - - * lib/racc/grammar.rb (DefinitionEnv): new method #action. - -Sat Jul 29 03:13:22 2006 Minero Aoki - - * lib/racc/compat.rb: reduce warning. - -Sun Jul 16 05:07:12 2006 Minero Aoki - - * lib/racc/compat.rb: implement Enumerable#each_slice for Ruby - 1.8. - - * lib/racc/parserfilegenerator.rb: better output. - - * ext/racc/cparse/cparse.c: always use VALUE instead of struct - cparse_params. - - * ext/racc/cparse/cparse.c: mark params->value_v. - -Thu Jul 6 20:44:48 2006 Minero Aoki - - * lib/racc/grammar.rb: on-the-fly generator implemented. - - * lib/racc/generator.rb -> statetransitiontable.rb, - parserfilegenerator.rb, logfilegenerator.rb. - - * lib/racc/statetransitiontable.rb: new file. - - * lib/racc/parserfilegenerator.rb: new file. - - * lib/racc/logfilegenerator.rb: new file. - - * lib/racc/grammarfileparser.rb.in: removed. - - * lib/racc/grammarfileparser.rb: new file. uses on-the-fly - generator. - - * misc/boot.rb: removed. - - * lib/racc/static.rb: new file, to import static generator - (lib/racc.rb provides dynamic generator). - - * lib/racc/grammar.rb: grand refactoring. - - * lib/racc/sourcetext.rb: new method #to_s, #location. - - * lib/racc/state.rb: compute NFA/DFA on demand. - - * bin/racc: follow these changes. - -Thu Jul 6 20:39:42 2006 Minero Aoki - - * ext/racc/cparse/cparse.so: should mark VALUEs in cparse_params. - -Tue Jul 4 02:24:27 2006 Minero Aoki - - * bin/racc: simplify report code. - - * lib/racc/grammar.rb: introduce new methods for racc command. - - * lib/racc/states.rb: ditto. - - * lib/racc/generator.rb: class CodeGenerator -> - ParserFileGenerator. - - * lib/racc/generator.rb: new class ParserFileGenerator::Params. - - * bin/racc: ditto. - - * misc/boot.rb: ditto. - - * lib/racc/grammarfileparser.rb.in: ditto. - - * lib/racc/grammarfileparser.rb.in: merge grammarfilescanner.rb. - - * lib/racc/grammarfilescanner.rb: removed. - - * lib/racc/grammarfileparser.rb.in: parses user code blocks. - - * lib/racc/usercodeparser.rb: removed. - - * lib/racc/generator.rb: remove user code parsing code. - - * lib/racc/grammarfileparser.rb.in: passes user code block by a - SourceText object. - - * lib/racc/generator.rb: ditto. - - * lib/racc/sourcetext.rb: new file. - - * lib/racc/generator.rb: introduce DSL to describe file contents. - -Tue Jul 4 02:15:36 2006 Minero Aoki - - * lib/racc/debugflags.rb: remove unused class GenerationOptions. - -Tue Jul 4 02:14:48 2006 Minero Aoki - - * lib/racc/compat.rb: update coding style. - -Mon Jul 3 04:34:32 2006 Minero Aoki - - * lib/racc/compiler.rb: do not export Grammar/SymbolTable/States. - - * lib/racc/compiler.rb: make a new class for debug flags - (Racc::DebugFlags). - - * lib/racc/compiler.rb: removed. - - * bin/racc: eliminate Racc::Compiler class. - - * bin/racc: refactor profiling code. - - * bin/racc: move file generation code to racc/generator.rb. - - * misc/boot.rb: does not emulate Racc::Compiler interface. - - * lib/racc.rb: new file to require whole generator. - - * lib/racc/grammar.rb: class RuleTable -> Grammar. - - * lib/racc/grammar.rb: Grammar.new does not acccept a Compiler. - - * lib/racc/grammar.rb: refactoring. - - * lib/racc/grammarfileparser.rb.in: GrammarFileParser.new does not - accept a Compiler. - - * lib/racc/grammarfileparser.rb.in: #parser takes more 2 args, a - filename and a base line number. - - * lib/racc/grammarfileparser.rb.in: refactoring. - - * lib/racc/output.rb -> generate.rb - - * lib/racc/generate.rb: class Formatter -> CodeGenerator. - - * lib/racc/generate.rb: CodeGenerator.new does not accept a - Compiler. - - * lib/racc/generate.rb: a CodeGenerator got many parameters via - setter method. - - * lib/racc/generate.rb: class VerboseOutputter -> - LogFileGenerator. - - * lib/racc/generate.rb: LogFileGenerator.new does not accept a - Compiler. - - * lib/racc/generate.rb: refactoring. - - * lib/racc/state.rb: class StateTable -> States. - - * lib/racc/state.rb: States.new does not acccept a Compiler. - - * lib/racc/state.rb: refactoring. - - * test/test.rb: -Da is obsolete (I forgot what this flag is). - - * test/test.rb: allow replacing racc via environment variable - $RACC. - -Mon Jul 3 04:18:49 2006 Minero Aoki - - * Makefile: new task bootstrap-force. - -Sun Jul 2 19:46:58 2006 Minero Aoki - - * test/ichk.y: update coding style. - -Sun Jul 2 19:01:55 2006 Minero Aoki - - * ext/racc/cparse/cparse.c: must require version.h to get - RUBY_VERSION_CODE. - -Sun Jul 2 18:33:32 2006 Minero Aoki - - * ext/racc/cparse/cparse.c: do not use rb_iterate to give a block - to the method, use rb_block_call instead. [ruby-dev:28445] - -Mon Jun 19 02:38:18 2006 Minero Aoki - - * bin/racc: -g option is now -t. -g option is obsolete and is an - alias of -t. - -Mon Jun 19 02:35:59 2006 Minero Aoki - - * ext/racc/cparse/cparse.c: K&R -> ANSI C. - -Mon Nov 21 02:37:10 2005 Minero Aoki - - * version 1.4.5 released. - -Mon Nov 21 02:31:18 2005 Minero Aoki - - * bin/racc: shebang line should include file extension. - - * lib/racc/compat.rb: method removed: bug!. - - * lib/racc/*.rb: racc compiler should not depend on - Racc::ParseError. - - * lib/racc/*.rb: update copyright year. - - * lib/racc/*.rb: update coding style. - - * lib/racc/exception.rb: new file. - -Mon Nov 21 00:49:18 2005 Minero Aoki - - * Makefile: remove useless target `import'. - - * Makefile: generate parser-text.rb. - - * misc/dist.sh: setup.rb and COPYING is now in repository. - - * misc/dist.sh: generate parser-text.rb. - -Mon Nov 21 00:14:21 2005 Minero Aoki - - * bin/racc: read racc/parser.rb from parser-text.rb. - - * lib/racc/rubyloader.rb: no longer needed. - - * lib/racc/pre-setup: new file. - - * lib/racc/pre-setup: generate parser-text.rb. - - * lib/racc/pre-setup: generate grammarfileparser.rb. - - * misc/boot.rb: new method BootstrapCompiler.main. - - * misc/boot.rb: new method BootstrapCompiler.generate, which is - used from pre-setup. - -Mon Nov 21 00:09:04 2005 Minero Aoki - - * bin/racc2y: refactoring. - - * bin/y2racc: refactoring. - -Sun Nov 20 23:46:42 2005 Minero Aoki - - * lib/racc/pre-setup: new file. - -Sun Nov 20 22:46:21 2005 Minero Aoki - - * COPYING: new file. - -Sun Nov 20 22:25:15 2005 Minero Aoki - - * setup.rb: import setup.rb 3.4.1. - -Thu Sep 29 02:51:56 2005 Minero Aoki - - * Makefile (clean): invoke `make clean' in ext. - -Thu Sep 29 02:50:56 2005 Minero Aoki - - * lib/racc/.cvsignore: removed. - -Thu Sep 29 02:46:30 2005 Minero Aoki - - * Makefile: use .makeparams system. - - * Makefile: unify lib/racc/Makefile. - - * Makefile: new target lib/racc/grammarfileparser.rb. - - * lib/racc/Makefile: unified by ./Makefile. - - * lib/racc/boot: removed (moved under misc). - - * misc/boot.rb: new file. - -Thu Sep 29 02:43:30 2005 Minero Aoki - - * setup.rb: new file. - -Tue Jul 26 23:37:46 2005 Minero Aoki - - * bin/racc: --no-omit-actions did not work (This patch is - contributed by OHKUBO Takuya). - -Sun Jan 2 11:48:19 2005 Minero Aoki - - * lib/racc/grammer.rb (once_writer): bug! needs argument. - -Mon Feb 16 16:14:16 2004 Minero Aoki - - * test/echk.y: fix typo. - - * test/ichk.y: does not use amstd. - - * test/opt.y: untabify. - -Mon Feb 16 16:10:46 2004 Minero Aoki - - * lib/racc/boot: update coding style. - - * lib/racc/compat.rb: ditto. - - * lib/racc/compiler.rb: ditto. - - * lib/racc/grammar.rb: ditto. - - * lib/racc/grammarfileparser.rb.in: ditto. - - * lib/racc/grammarfilescanner.rb: ditto. - - * lib/racc/info.rb: ditto. - - * lib/racc/iset.rb: ditto. - - * lib/racc/output.rb: ditto. - - * lib/racc/parser.rb: ditto. - - * lib/racc/state.rb: ditto. - - * lib/racc/usercodeparser.rb: ditto. - -Mon Feb 16 16:01:34 2004 Minero Aoki - - * lib/racc/rubyloader.rb: imported rev1.6. - -Fri Dec 12 01:57:47 2003 Minero Aoki - - * sample/hash.y: use no_result_var option. - - * sample/array.y: use latest (my) coding style. - - * sample/array2.y: ditto. - - * sample/hash.y: ditto. - - * sample/lists.y: ditto. - -Wed Nov 5 19:50:35 2003 Minero Aoki - - * test/bench.y: remove dependency on amstd. - - * test/chk.y: ditto. - - * test/echk.y: ditto. - - * test/ichk.y: ditto. - - * test/intp.y: ditto. - - * test/opt.y: ditto. - - * test/percent.y: ditto. - -Wed Nov 5 19:11:15 2003 Minero Aoki - - * bin/racc (get_options): remove --no-extensions option; - racc/parser is preloaded, Racc_No_Extension does not work. - -Mon Nov 3 22:41:42 2003 Minero Aoki - - * bin/racc: apply latest coding style. - - * lib/racc/parser.rb: ditto. - - * lib/racc/compat.rb: add File.read. - -Mon Nov 3 21:20:25 2003 Minero Aoki - - * ext/racc/cparse/cparse.c (parse_main): abort if length of state - stack <=1, not ==0. - - * lib/racc/parser.rb: use <=1, not <2. - - * ext/racc/cparse/cparse.c: check_*() -> assert_*() - - * ext/racc/cparse/cparse.c (racc_cparse): define lvar `v' for - debugging. - - * ext/racc/cparse/cparse.c (racc_yyparse): ditto. - -Mon Nov 3 17:21:55 2003 Minero Aoki - - * Makefile (all): make cparse.so. - -Mon Nov 3 17:19:26 2003 Minero Aoki - - * lib/racc/parser.rb: update version. - - * ext/racc/cparse/cparse.c: update version. - -Mon Nov 3 17:19:01 2003 Minero Aoki - - * Makefile: update version in parser.rb, cparse.c. - -Sun Oct 12 23:49:58 2003 Minero Aoki - - * version 1.4.4. - -Sun Oct 12 23:49:40 2003 Minero Aoki - - * bin/y2racc: did not work. - - * bin/y2racc: -u options did not work. - -Sun Oct 12 23:41:46 2003 Minero Aoki - - * misc/dist.sh: cd before make. - -Sun Oct 12 23:38:04 2003 Minero Aoki - - * Makefile (site): create $siteroot/{ja,en}/man/racc/*.html. - -Sun Oct 12 23:37:18 2003 Minero Aoki - - * doc/parser.rrd.m: missing 'j'. - -Sun Oct 12 23:29:11 2003 Minero Aoki - - * Makefile: new target `doc'. - - * Makefile: new target `clean'. - - * lib/racc/Makefile: new target `clean'. - - * misc/dist.sh: create documents before pack. - -Sun Oct 12 23:27:58 2003 Minero Aoki - - * doc/debug.rd.m: junk char was inserted. - - * doc/index.html.m: en/ja text were mixed. - - * doc/parser.rrd.m: add return values. - - * doc/usage.html.m: fix hyper link. - -Sun Oct 12 22:57:28 2003 Minero Aoki - - * doc.en/changes.html, doc.ja/changes.html -> doc/NEWS.rd.m - - * doc.en/command.html, doc.ja/command.html -> doc/command.html.m - - * doc.en/debug.html, doc.ja/debug.html -> doc/debug.rd.m - - * doc.en/grammar.html, doc.ja/grammar.html -> doc/grammar.rd.m - - * doc.en/index.html, doc.ja/index.html -> doc/index.html.m - - * doc.en/parser.html, doc.ja/parser.html -> doc/parser.rrd.m - - * doc.en/usage.html, doc.ja/usage.html -> doc/usage.html.m - -Sun Oct 12 18:46:21 2003 Minero Aoki - - * web/racc.ja.html: update descriptions. - - * web/racc.en.html: ditto. - -Sun Oct 12 18:43:45 2003 Minero Aoki - - * misc/dist.sh: remove web/ directory before distribute. - -Sun Oct 12 18:37:29 2003 Minero Aoki - - * Makefile: new target `site'. - - * web/racc.ja.html: new file. - - * web/racc.en.html: new file. - -Sun Oct 12 18:30:55 2003 Minero Aoki - - * misc/dist.sh: forgot to remove tmp comment out. - -Sun Oct 12 18:12:09 2003 Minero Aoki - - * lib/racc/info.rb: version 1.4.4. - -Sun Oct 12 18:11:42 2003 Minero Aoki - - * Makefile (dist): split out misc/dist.sh. - - * misc/dist.sh: new file. - -Sun Oct 12 17:18:47 2003 Minero Aoki - - * README.en: update documents. - - * README.ja: ditto. - - * doc.en/changes.html: ditto. - - * doc.en/command.html: ditto. - - * doc.en/debug.html: ditto. - - * doc.en/grammar.html: ditto. - - * doc.en/index.html: ditto. - - * doc.en/parser.html: ditto. - - * doc.en/usage.html: ditto. - - * doc.ja/changes.html: ditto. - - * doc.ja/command.html: ditto. - - * doc.ja/debug.html: ditto. - - * doc.ja/index.html: ditto. - - * doc.ja/parser.html: ditto. - - * doc.ja/usage.html: ditto. - -Sun Oct 12 16:24:46 2003 Minero Aoki - - * sameple/calc-ja.y: simplify. - -Sun Oct 12 16:24:16 2003 Minero Aoki - - * misc/y2racc -> bin/y2racc - - * misc/racc2y -> bin/racc2y - -Sun Oct 12 15:56:30 2003 Minero Aoki - - * bin/racc: follow method name change. - -Sun Oct 12 15:34:14 2003 Minero Aoki - - * Makefile: new target `test'. - - * Makefile: missing $datadir. - -Sun Oct 12 15:33:02 2003 Minero Aoki - - * README.ja: update description. - - * README.en: ditto. - -Sun Oct 12 15:25:23 2003 Minero Aoki - - * lib/racc/compiler.rb: adjust file names. - - * lib/racc/grammarfileparser.rb.in: ditto. - - * lib/racc/grammarfilescanner.rb: ditto. - -Sun Oct 12 15:24:53 2003 Minero Aoki - - * Makefile: new file. - -Sun Oct 12 15:19:57 2003 Minero Aoki - - * BUGS.en: removed. - - * BUGS.ja: removed. - -Sun Oct 12 15:10:38 2003 Minero Aoki - - * racc -> bin/racc - - * .cvsignore -> lib/racc/.cvsignore - - * lib/racc/Makefile: new file. - - * boot.rb -> lib/racc/boot - - * compat.rb -> lib/racc/compat.rb - - * compiler.rb -> lib/racc/compiler.rb - - * grammar.rb -> lib/racc/grammar.rb - - * in.raccp.rb -> lib/racc/grammarfileparser.rb.in - - * raccs.rb -> lib/racc/grammarfilescanner.rb - - * info.rb -> lib/racc/info.rb - - * iset.rb -> lib/racc/iset.rb - - * outpur.rb -> lib/racc/output.rb - - * parser.rb -> lib/racc/parser.rb - - * rubyloader.rb -> lib/racc/rubyloader.rb - - * state.rb -> lib/racc/state.rb - - * ucodep.rb -> lib/racc/usercodeparser.rb - - * cparse/MANIFEST -> ext/racc/cparse/MANIFEST - - * cparse/cparse.c -> ext/racc/cparse/cparse.c - - * cparse/depend -> ext/racc/cparse/depend - - * cparse/extconf.rb -> ext/racc/cparse/extconf.rb - - * cparse/.cvsignore -> ext/racc/cparse/.cvsignore - -Sun Oct 12 15:10:13 2003 Minero Aoki - - * test/test.rb: use /bin/rm if exists. - -Sun Oct 12 14:33:29 2003 Minero Aoki - - * rubyloader.rb: imported from amstd, rev 1.5. - -Sun Oct 12 14:24:47 2003 Minero Aoki - - * boot.rb: reformat only. - - * compiler.rb: ditto. - - * grammar.rb: ditto. - - * in.raccp.rb: ditto. - - * iset.rb: ditto. - - * output.rb: ditto. - - * raccs.rb: ditto. - - * state.rb: ditto. - -Sun Oct 12 14:17:22 2003 Minero Aoki - - * test/test.rb: refactoring. - -Tue Jun 24 03:14:01 2003 Minero Aoki - - * ucodep.rb: typo: Grammer -> Grammar - -Mon May 26 23:06:58 2003 Minero Aoki - - * compiler.rb: update copyright year. - - * grammar.rb: ditto. - - * in.raccp.rb: ditto. - - * info.rb: ditto. - - * iset.rb: ditto. - - * output.rb: ditto. - - * parser.rb: ditto. - - * raccs.rb: ditto. - - * state.rb: ditto. - - * ucodep.rb: ditto. - -Sun May 25 13:21:27 2003 Minero Aoki - - * raccs.rb: update coding style. - -Fri Nov 15 17:53:12 2002 Minero Aoki - - * racc: changes style. - - * parser.rb: ditto. - -Fri Nov 15 17:11:52 2002 Minero Aoki - - version 1.4.3. - -Fri Nov 15 17:08:01 2002 Minero Aoki - - * boot.rb, compiler.rb, grammar.rb, in.raccp.rb, iset.rb, - output.rb, parser.rb, racc, raccs.rb, state.rb, ucodep.rb, - misc/racc2y, misc/y2racc: follows (my) latest coding styles. - -Thu Nov 14 14:39:53 2002 Minero Aoki - - * raccs.rb: explicit method call for VCALL. - -Wed Oct 16 15:45:11 2002 Minero Aoki - - * parser.rb: reformat. - -Fri Aug 9 18:21:01 2002 Minero Aoki - - * cparse/cparse.c: use better variable/macro names. - -Wed Aug 7 08:39:19 2002 Minero Aoki - - * cparse/cparse.c: goto label requires stmt. - -Mon Aug 5 21:53:07 2002 Minero Aoki - - * cparse/cparse.c: grand refine. - - * cparse/depend: re-added from ruby/ext/racc/cparse. - -Tue Jun 4 00:15:28 2002 Minero Aoki - - * boot.rb: allow to omit last 'end'. - -Mon Jun 3 23:29:45 2002 Minero Aoki - - * racc (write_table_file): shebang must placed on first line. - (reported by Hiroyuki Sato) - diff --git a/DEPENDS b/DEPENDS index 82d7516d..dbaafcd4 100644 --- a/DEPENDS +++ b/DEPENDS @@ -1,4 +1,2 @@ racc: raccruntime raccruntime: -y2racc: strscan -racc2y: racc diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..b78ecc1b --- /dev/null +++ b/Gemfile @@ -0,0 +1,21 @@ +# -*- ruby -*- + +# DO NOT EDIT THIS FILE. Instead, edit Rakefile, and run `rake bundler:gemfile`. + +source "https://rubygems.org/" + + +gem "rake", "~>12.2", :group => [:development, :test] +gem "rake-compiler", "~>1.0", :group => [:development, :test] +gem "minitest", "~>5.10", :group => [:development, :test] +gem "hoe", "~>3.16", :group => [:development, :test] +gem "hoe-debugging", "~>1.4", :group => [:development, :test] +gem "hoe-doofus", "~>1.0", :group => [:development, :test] +gem "hoe-git", "~>1.6", :group => [:development, :test] +gem "hoe-gemspec", "~>1.0", :group => [:development, :test] +gem "hoe-bundler", "~>1.3", :group => [:development, :test] +gem "rubocop", "~>0.51", :group => [:development, :test] +gem "pry", "~>0.11", :group => [:development, :test] +gem "rdoc", "~>4.0", :group => [:development, :test] + +# vim: syntax=ruby diff --git a/Manifest.txt b/Manifest.txt index d77dfcad..9a55836b 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -1,5 +1,4 @@ COPYING -ChangeLog DEPENDS Manifest.txt README.ja.rdoc @@ -7,33 +6,30 @@ README.rdoc Rakefile TODO bin/racc -bin/racc2y -bin/y2racc ext/racc/MANIFEST ext/racc/cparse.c ext/racc/depend ext/racc/extconf.rb ext/racc/com/headius/racc/Cparse.java -fastcache/extconf.rb -fastcache/fastcache.c lib/racc.rb -lib/racc/compat.rb -lib/racc/debugflags.rb +lib/racc/color.rb +lib/racc/directed_graph.rb +lib/racc/dsl.rb lib/racc/exception.rb lib/racc/grammar.rb -lib/racc/grammarfileparser.rb +lib/racc/grammar_file_parser.rb +lib/racc/grammar_file_scanner.rb +lib/racc/grammar_file_scanner.rl lib/racc/info.rb -lib/racc/iset.rb -lib/racc/logfilegenerator.rb -lib/racc/parser-text.rb lib/racc/parser.rb -lib/racc/parserfilegenerator.rb -lib/racc/pre-setup -lib/racc/sourcetext.rb +lib/racc/parser_file_generator.rb +lib/racc/simulated_automaton.rb +lib/racc/source.rb lib/racc/state.rb -lib/racc/statetransitiontable.rb -lib/racc/static.rb -misc/dist.sh +lib/racc/state_summary_generator.rb +lib/racc/state_transition_table.rb +lib/racc/util.rb +lib/racc/warning.rb rdoc/en/NEWS.en.rdoc rdoc/en/grammar.en.rdoc rdoc/ja/NEWS.ja.rdoc @@ -53,49 +49,134 @@ sample/lalr.y sample/lists.y sample/syntax.y sample/yyerr.y -setup.rb -tasks/doc.rb -tasks/email.rb +test/assets/badprec1.y +test/assets/badprec2.y +test/assets/badrule1.y +test/assets/badrule2.y +test/assets/badrule3.y +test/assets/badrule4.y +test/assets/badsyntax.y +test/assets/bench.y +test/assets/cadenza.y +test/assets/calc-ja.y +test/assets/cast.y test/assets/chk.y test/assets/conf.y +test/assets/csspool.y test/assets/digraph.y +test/assets/duplicate.y test/assets/echk.y +test/assets/edtf.y +test/assets/empty.y test/assets/err.y +test/assets/error_recovery.y test/assets/expect.y +test/assets/eye-of-newt.y test/assets/firstline.y +test/assets/huia.y test/assets/ichk.y +test/assets/infini.y test/assets/intp.y +test/assets/journey.y +test/assets/liquor.y +test/assets/lr_not_lalr.y +test/assets/lr_not_lalr2.y +test/assets/machete.y +test/assets/macruby.y +test/assets/mediacloth.y test/assets/mailp.y +test/assets/mof.y +test/assets/namae.y +test/assets/nasl.y test/assets/newsyn.y test/assets/noend.y +test/assets/nokogiri-css.y test/assets/nonass.y test/assets/normal.y test/assets/norule.y test/assets/nullbug1.y test/assets/nullbug2.y +test/assets/opal.y test/assets/opt.y test/assets/percent.y +test/assets/php_serialization.y test/assets/recv.y +test/assets/riml.y test/assets/rrconf.y +test/assets/ruby18.y +test/assets/ruby19.y +test/assets/ruby20.y +test/assets/ruby21.y +test/assets/ruby22.y test/assets/scan.y +test/assets/src.intp +test/assets/start.y test/assets/syntax.y +test/assets/tp_plus.y +test/assets/twowaysql.y test/assets/unterm.y test/assets/useless.y test/assets/yyerr.y -test/bench.y test/helper.rb -test/infini.y +test/regress.rb +test/regress/README.txt +test/regress/badprec1.out +test/regress/badprec2.out +test/regress/badrule1.out +test/regress/badrule2.out +test/regress/badrule3.out +test/regress/badrule4.out +test/regress/badsyntax.out +test/regress/cadenza.rb +test/regress/cast.rb +test/regress/csspool.html +test/regress/csspool.out +test/regress/csspool.rb +test/regress/duplicate.out +test/regress/edtf.out +test/regress/edtf.rb +test/regress/empty.out +test/regress/eye-of-newt.rb +test/regress/journey.rb +test/regress/huia.rb +test/regress/liquor.rb +test/regress/lr_not_lalr.out +test/regress/lr_not_lalr2.out +test/regress/machete.rb +test/regress/mediacloth.rb +test/regress/mof.out +test/regress/mof.rb +test/regress/namae.rb +test/regress/nasl.rb +test/regress/nokogiri-css.rb +test/regress/normal.out +test/regress/opal.out +test/regress/opal.rb +test/regress/php_serialization.rb +test/regress/riml.rb +test/regress/ruby18.rb +test/regress/ruby22.rb +test/regress/tp_plus.rb +test/regress/twowaysql.html +test/regress/twowaysql.rb +test/scandata/blockcomment test/scandata/brace +test/scandata/comment_at_eof +test/scandata/dynstr +test/scandata/escapednl test/scandata/gvar +test/scandata/heredocs +test/scandata/leading_whitespace test/scandata/normal +test/scandata/operators test/scandata/percent +test/scandata/regexp test/scandata/slash -test/src.intp -test/start.y +test/scandata/strings +test/scandata/suffixes test/test_chk_y.rb +test/test_directed_graph.rb test/test_grammar_file_parser.rb test/test_racc_command.rb test/test_scan_y.rb -test/testscanner.rb -web/racc.en.rhtml -web/racc.ja.rhtml +test/test_scanner.rb diff --git a/README.ja.rdoc b/README.ja.rdoc index ba1c1bf8..50ccc7b3 100644 --- a/README.ja.rdoc +++ b/README.ja.rdoc @@ -17,6 +17,7 @@ == 必要環境 * Ruby 1.8 以降 + * Ragel (*) C コンパイラと make @@ -76,10 +77,9 @@ == ライセンス このパッケージに付属するファイルの著作権は青木峰郎が保持します。 - ライセンスは GNU Lesser General Public License (LGPL) version 2 - です。ただしユーザが書いた規則ファイルや、Racc がそこから生成し - た Ruby スクリプトはその対象外です。好きなライセンスで配布して - ください。 + ライセンスは Ruby ライセンスです。ただしユーザが書いた規則 + ファイルや、Racc がそこから生成した Ruby スクリプトはその対象 + 外です。好きなライセンスで配布してください。 == バグなど diff --git a/README.rdoc b/README.rdoc index 56bed808..32ed4ccd 100644 --- a/README.rdoc +++ b/README.rdoc @@ -1,21 +1,21 @@ = Racc * http://i.loveruby.net/en/projects/racc/ -* http://racc.rubyforge.org/ == DESCRIPTION: Racc is a LALR(1) parser generator. - It is written in Ruby itself, and generates Ruby program. + It is written in Ruby itself, and generates Ruby programs. - NOTE: Ruby 1.8.x comes with Racc runtime module. You + NOTE: Ruby 1.8+ comes with the Racc runtime module. You can run your parsers generated by racc 1.4.x out of the box. -== Requirement +== Requirements - * Ruby 1.8.x or later. + * Ruby 1.8+ + * Ragel (*) make and C compiler. @@ -25,60 +25,36 @@ $ gem install racc - setup.rb install: - - Type this in the top directory of the extracted archive: - - $ ruby setup.rb config - $ ruby setup.rb setup - ($ su) - # ruby setup.rb install - - You can install Racc into your favorite directory by giving - options to setup.rb. e.g. - - $ ruby setup.rb config --prefix=/usr - - For details, try "ruby setup.rb --help". - - - If you don't have C Compiler - ---------------------------- - - You can install Racc without C compilers. Type following - command in config phase. - - $ ruby setup.rb config --without-ext - == Testing Racc - Racc comes with simple calculator. To compile this, on shell: + Racc comes with a simple calculator. To compile this at the shell: - $ racc -o calc calc.y + $ racc -o calc sample/calc.y - This process costs few seconds (or less). Then type: + This process takes few seconds (or less). Then type: $ ruby calc - ... Does it works? - For details of Racc, see HTML documents placed under 'doc.en/' - and sample grammer files under 'sample/'. + ... Does it work? + + For details about Racc, see the HTML documents under 'doc.en/' + and sample grammar files under 'sample/'. == License - Racc is distributed under the terms of the GNU Lesser General - Public License version 2. Note that you do NOT need to follow - LGPL for your own parser (racc outputs). You can provide those - files under any licenses you want. + Racc is distributed under the same terms of ruby. + (see the file COPYING). Note that you do NOT need to follow + ruby license for your own parser (racc outputs). + You can distribute those files under any licenses you want. == Bug Reports Any kind of bug reports are welcome. - If you find a bug of Racc, please email me. Your grammer file, - debug output genereted by "racc -g", are helpful. + If you find a bug in Racc, please email me. Your grammar file, + and debug output generated by "racc -g", will be helpful. Minero Aoki diff --git a/Rakefile b/Rakefile index d6c6b050..b2fb529d 100644 --- a/Rakefile +++ b/Rakefile @@ -3,9 +3,11 @@ require 'rubygems' require 'hoe' -gem 'rake-compiler', '>= 0.4.1' +gem 'rake-compiler' -Hoe.plugin :debugging, :doofus, :git, :isolate, :gemspec +Hoe.plugin :debugging, :doofus, :git, :gemspec, :bundler + +$:.unshift(File.dirname(__FILE__) + '/lib') def java? /java/ === RUBY_PLATFORM @@ -19,11 +21,21 @@ HOE = Hoe.spec 'racc' do license "MIT" self.extra_rdoc_files = Dir['*.rdoc'] - self.history_file = 'ChangeLog' self.readme_file = 'README.rdoc' - dependency 'rake-compiler', '>= 0.4.1', :developer - dependency 'minitest', '~> 4.7', :developer # stick to stdlib's version + dependency 'rake', '~> 12.2', :developer + dependency 'rake-compiler', '~> 1.0', :developer + dependency 'minitest', '~> 5.10', :developer + + dependency 'hoe', '~> 3.16', :developer + dependency 'hoe-debugging', '~> 1.4', :developer + dependency 'hoe-doofus', '~> 1.0', :developer + dependency 'hoe-git', '~> 1.6', :developer + dependency 'hoe-gemspec', '~> 1.0', :developer + dependency 'hoe-bundler', '~> 1.3', :developer + + dependency 'rubocop', '~> 0.51', :developer + dependency 'pry', '~> 0.11', :developer if java? self.spec_extras[:platform] = 'java' @@ -33,6 +45,7 @@ HOE = Hoe.spec 'racc' do self.clean_globs << "lib/#{self.name}/*.{so,bundle,dll,jar}" # from hoe/compiler + require_ruby_version '2.2.8' end def add_file_to_gem relative_path @@ -48,20 +61,6 @@ def gem_build_path File.join 'pkg', HOE.spec.full_name end -file 'lib/racc/parser-text.rb' => ['lib/racc/parser.rb'] do |t| - source = 'lib/racc/parser.rb' - - open(t.name, 'wb') { |io| - io.write(<<-eorb) -module Racc - PARSER_TEXT = <<'__end_of_file__' -#{File.read(source)} -__end_of_file__ -end - eorb - } -end - unless jruby? # MRI require "rake/extensiontask" @@ -69,9 +68,6 @@ unless jruby? ext.lib_dir = File.join 'lib', 'racc' ext.ext_dir = File.join 'ext', 'racc' end - - task :compile => 'lib/racc/parser-text.rb' - # else # JRUBY require "rake/javaextensiontask" @@ -87,14 +83,34 @@ else ext.name = 'cparse-jruby' end - task :compile => ['lib/racc/parser-text.rb'] - task gem_build_path => [:compile] do add_file_to_gem 'lib/racc/cparse-jruby.jar' end +end +task :test_pure do + ENV["PURERUBY"] = "1" + Rake.application[:test].invoke end task :test => :compile +require 'rubocop/rake_task' +RuboCop::RakeTask.new(:rubocop) do |task| + task.options = ['-a', '-D'] +end + +task :pry, [:grammar_file] do |t, args| + require 'pry' + require 'racc' + require 'racc/grammar_file_parser' + puts "Parsing #{args[:grammar_file]}" + grammar = Racc::GrammarFileParser.parse_file(args[:grammar_file]).grammar + grammar.pry +end + Hoe.add_include_dirs('.:lib/racc') + +rule '.rb' => '.rl' do |t| + sh "ragel -F1 -R #{t.source} -o #{t.name}" +end diff --git a/TODO b/TODO index 8e68e6e4..ca25bfad 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,46 @@ -* check 'error' token handling. -* interactive transition table monitor. -* support backtracking. -* output Ruby extention library? -* LL(k)? (But it should not be called Racc) +TO CHECK: + +- Try grammars which contain non-ASCII chars. + +DIAGNOSTICS: + +- On conflict, try to find a series of tokens which can be parsed BOTH by + an automaton which resolves the conflict in one way, and by an automaton + which resolves the conflict in the other way. + + This problem is not solvable in the general case. Just do a recursive search, + limiting the search space enough to terminate quickly. + + First though, we need to abstract the classes which represent LR states and + automatons a bit more, making them amenable to use for general-purpose + analysis and manipulation, not just solely doing what Racc needs to generate + a parser. + +- If we can do that, show alternative derivation trees for the same tokens. + +- Any other compiler checks or warnings which we should add? + +PARSER CORE: + +- Generate LR(1) rather than LALR(1) parsers. + +- Add a directive to manually resolve one specific conflict. + This will also be used internally for the next point: + +- Add *, ?, +, as well as parentheses for grouping, to the understood grammar + file format. + +RUNTIME: + +- Generate more efficient parsers! + +OTHER: + +- Documentation + +- Full code review and cleanup + +- Make the code RuboCop-compliant +- Then add RC to the build process + +- Any further tests which can be added to verify correctness? diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..11adeee9 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,36 @@ +--- +image: Visual Studio 2017 + +clone_depth: 10 + +build: off +deploy: off + +install: + - SET PATH=C:\Ruby%ruby_version%\bin;%PATH% + - ps: | + $rv = $env:ruby_version + if ( $rv -lt '24' ) { + gem install minitest hoe rake-compiler rubocop:0.68.1 --no-document --conservative + } else { + gem install minitest hoe rake-compiler rubocop --no-document --conservative + } + if ( $rv.EndsWith('-x64') ) { + C:/msys64/usr/bin/pacman -S --noconfirm --needed --noprogressbar mingw-w64-x86_64-ragel + $env:PATH = "C:/Ruby$rv/bin;$env:PATH;C:/msys64/mingw64/bin" + } else { + C:/msys64/usr/bin/pacman -S --noconfirm --needed --noprogressbar mingw-w64-i686-ragel + $env:PATH = "C:/Ruby$rv/bin;$env:PATH;C:/msys64/mingw32/bin" + } + +test_script: + - rake -rdevkit test + +environment: + matrix: + - ruby_version: "24" + - ruby_version: "24-x64" + - ruby_version: "25" + - ruby_version: "25-x64" + - ruby_version: "26" + - ruby_version: "26-x64" diff --git a/bin/racc b/bin/racc index d8764bce..beefa394 100755 --- a/bin/racc +++ b/bin/racc @@ -1,203 +1,173 @@ #!/usr/bin/env ruby # -# $Id$ -# # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of LGPL, see the file "COPYING". -# - -require 'racc/static' +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". + +require 'racc' +require 'racc/parser' +require 'racc/grammar_file_parser' +require 'racc/parser_file_generator' +require 'racc/state_summary_generator' +require 'racc/color' require 'optparse' +include Racc::Color + def main - output = nil - debug_parser = false - make_logfile = false - logfilename = nil + output_file = nil + check_only = false + verbose = false + output_format = :ruby + + debug_parser = false make_executable = false - rubypath = nil - embed_runtime = false - debug_flags = Racc::DebugFlags.new - line_convert = true - line_convert_all = false - omit_action_call = true - superclass = nil - check_only = false - verbose = false - profiler = RaccProfiler.new(false) + rubypath = nil + embed_runtime = false + superclass = nil + + profiler = RaccProfiler.new(!!ENV['PROFILE']) + + Racc::Color.enabled = $stderr.tty? parser = OptionParser.new parser.banner = "Usage: #{File.basename($0)} [options] " + parser.separator 'General:' parser.on('-o', '--output-file=PATH', - 'output file name [.tab.rb]') {|name| - output = name - } - parser.on('-t', '--debug', 'Outputs debugging parser.') {|fl| - debug_parser = fl + 'Output file name [.rb / .html]') { |name| + output_file = name } - parser.on('-g', 'Equivalent to -t (obsolete).') {|fl| - $stderr.puts "racc -g is obsolete. Use racc -t instead." if $VERBOSE - debug_parser = fl + parser.on('-C', '--check-only', 'Check syntax and quit immediately') { + check_only = true } - parser.on('-v', '--verbose', - 'Creates .output log file.') {|fl| - make_logfile = fl + parser.on('-S', '--states', 'Output summary of parser states as HTML') { + output_format = :html } - parser.on('-O', '--log-file=PATH', - 'Log file name [.output]') {|path| - make_logfile = true - logfilename = path - } - parser.on('-e', '--executable [RUBYPATH]', 'Makes executable parser.') {|path| - executable = true - rubypath = (path == 'ruby' ? nil : path) - } - parser.on('-E', '--embedded', "Embeds Racc runtime in output.") { - embed_runtime = true - } - parser.on('--line-convert-all', 'Converts line numbers of user codes.') { - line_convert_all = true - } - parser.on('-l', '--no-line-convert', 'Never convert line numbers.') { - line_convert = false - line_convert_all = false - } - parser.on('-a', '--no-omit-actions', 'Never omit actions.') { - omit_action_call = false - } - parser.on('--superclass=CLASSNAME', - 'Uses CLASSNAME instead of Racc::Parser.') {|name| - superclass = name + parser.on('--version', 'Print version and quit') { + core = Racc::Parser.racc_runtime_type == 'ruby' ? '(ruby core)' : '(c core)' + puts "racc #{Racc::VERSION}, codename: #{Racc::CODENAME} #{core}" + exit 0 } - parser.on('--runtime=FEATURE', - "Uses FEATURE instead of 'racc/parser'") {|feat| - runtime = feature + parser.on('--copyright', 'Print copyright and quit') { + puts Racc::COPYRIGHT + exit 0 } - parser.on('-C', '--check-only', 'Checks syntax and quit immediately.') {|fl| - check_only = fl + parser.on('--help', 'Print this message and quit') { + puts parser.help + exit 1 } - parser.on('-S', '--output-status', 'Outputs internal status time to time.') { + parser.separator '' + parser.separator 'Console output:' + parser.on('-v', '--verbose', 'Display extra diagnostic information') { verbose = true } - parser.on('-P', 'Enables generator profile') { - profiler = RaccProfiler.new(true) + parser.on('--[no-]color', 'Force colored output on or off') { |fl| + Racc::Color.enabled = fl } - parser.on('-D flags', "Flags for Racc debugging (do not use).") {|flags| - debug_flags = Racc::DebugFlags.parse_option_string(flags) + parser.separator '' + parser.separator 'Ruby parser code output:' + parser.on('-t', '--debug', 'Output debugging parser') { + debug_parser = true } - #parser.on('--no-extensions', 'Run Racc without any Ruby extension.') { - # Racc.const_set :Racc_No_Extentions, true - #} - parser.on('--version', 'Prints version and quit.') { - puts "racc version #{Racc::Version}" - exit 0 + parser.on('-e', '--executable [RUBYPATH]', 'Output executable parser') { |path| + make_executable = true + rubypath = path || 'ruby' } - parser.on('--runtime-version', 'Prints runtime version and quit.') { - printf "racc runtime version %s (rev. %s); %s\n", - Racc::Parser::Racc_Runtime_Version, - Racc::Parser::Racc_Runtime_Revision, - if Racc::Parser.racc_runtime_type == 'ruby' - sprintf('ruby core version %s (rev. %s)', - Racc::Parser::Racc_Runtime_Core_Version_R, - Racc::Parser::Racc_Runtime_Core_Revision_R) - else - sprintf('c core version %s (rev. %s)', - Racc::Parser::Racc_Runtime_Core_Version_C, - Racc::Parser::Racc_Runtime_Core_Revision_C) - end - exit 0 + parser.on('-E', '--embedded', "Embed Racc runtime in output") { + embed_runtime = true } - parser.on('--copyright', 'Prints copyright and quit.') { - puts Racc::Copyright - exit 0 + parser.on('--superclass=CLASSNAME', + 'Use CLASSNAME as superclass instead of Racc::Parser') { |name| + superclass = name } - parser.on('--help', 'Prints this message and quit.') { - puts parser.help + + fail = proc do |err| + $stderr.puts "#{red('Error: ')}#{err}" + $stderr.puts + $stderr.puts parser.help exit 1 - } + end + begin parser.parse! rescue OptionParser::ParseError => err - $stderr.puts err.message - $stderr.puts parser.help - exit 1 + fail[err.message] end + if ARGV.empty? - $stderr.puts 'no input' - exit 1 - end - if ARGV.size > 1 - $stderr.puts 'too many input' - exit 1 + fail['no input file'] + elsif ARGV.size > 1 + fail['too many input files'] end input = ARGV[0] begin + if output_file.nil? + output_file = make_filename(input, '.rb') + if File.exist?(output_file) + $stderr.puts "#{red('Error: ')}'#{output_file}' already exists. " \ + "Please use '-o #{output_file}' if you are sure that you want to " \ + "overwrite this file." + exit 1 + end + end + $stderr.puts 'Parsing grammar file...' if verbose - result = profiler.section('parse') { - parser = Racc::GrammarFileParser.new(debug_flags) + result = profiler.section('parse') do + parser = Racc::GrammarFileParser.new parser.parse(File.read(input), File.basename(input)) - } + end if check_only - $stderr.puts 'syntax ok' + $stderr.puts "Syntax is OK for #{input}" exit 0 end - $stderr.puts 'Generating LALR states...' if verbose - states = profiler.section('nfa') { - Racc::States.new(result.grammar).nfa - } - - $stderr.puts "Resolving #{states.size} states..." if verbose - profiler.section('dfa') { - states.dfa - } - - $stderr.puts 'Creating parser file...' if verbose - params = result.params.dup - # Overwrites parameters given by a grammar file with command line options. - params.superclass = superclass if superclass - params.omit_action_call = true if omit_action_call - # From command line option - if make_executable - params.make_executable = true - params.interpreter = rubypath + $stderr.puts 'Generating and resolving LALR states...' if verbose + states = profiler.section('nfa') do + result.grammar.states end - params.debug_parser = debug_parser - params.convert_line = line_convert - params.convert_line_all = line_convert_all - params.embed_runtime = embed_runtime - profiler.section('generation') { - generator = Racc::ParserFileGenerator.new(states, params) - generator.generate_parser_file(output || make_filename(input, '.tab.rb')) - } - if make_logfile - profiler.section('logging') { - $stderr.puts 'Creating log file...' if verbose - logfilename ||= make_filename(output || File.basename(input), '.output') - File.open(logfilename, 'w') {|f| - Racc::LogFileGenerator.new(states, debug_flags).output f - } - } + if output_format == :ruby + $stderr.puts 'Creating parser file...' if verbose + params = result.params.dup + # Overwrite parameters from grammar file with command line options + params.superclass = superclass if superclass + if make_executable + params.make_executable = true + params.interpreter = rubypath + end + params.debug_parser = debug_parser + params.embed_runtime = embed_runtime + profiler.section('generation') do + generator = Racc::ParserFileGenerator.new(states, params) + generator.generate_parser_file(output_file) + end + elsif output_format == :html + $stderr.puts 'Creating HTML summary of parser states...' if verbose + generator = Racc::StateSummaryGenerator.new(states, input) + generator.generate_summary_file(output_file) end - if debug_flags.status_logging - log_useless states.grammar - log_conflict states - else - report_useless states.grammar - report_conflict states + + warnings = result.grammar.warnings(verbose) + if warnings.any? + $stderr.puts + $stderr.puts warnings.map(&:to_s).join("\n\n") + $stderr.puts + $stderr.puts warning_summary(warnings) + if !verbose && warnings.any?(&:verbose_details?) + $stderr.puts "Run with --verbose for more details." + end end profiler.report - rescue Racc::Error, Errno::ENOENT, Errno::EPERM => err - raise if $DEBUG or debug_flags.any? - lineno = err.message.slice(/\A\d+:/).to_s - $stderr.puts "#{File.basename $0}: #{input}:#{lineno} #{err.message.strip}" + rescue Racc::CompileError, Errno::ENOENT, Errno::EPERM => err + raise if $DEBUG + message = err.message.dup # string may be frozen literal + lineno = message.slice!(/\A\d+:/).to_s + location = lineno.empty? ? bright("#{input}:") : bright("#{input}:#{lineno}") + $stderr.puts "#{red('Error: ')}#{location} #{message.strip}" exit 1 end end @@ -206,71 +176,42 @@ def make_filename(path, suffix) path.sub(/(?:\..*?)?\z/, suffix) end -def report_conflict(states) - if states.should_report_srconflict? - $stderr.puts "#{states.n_srconflicts} shift/reduce conflicts" - end - if states.rrconflict_exist? - $stderr.puts "#{states.n_rrconflicts} reduce/reduce conflicts" - end -end - -def log_conflict(states) - logging('w') {|f| - f.puts "ex#{states.grammar.n_expected_srconflicts}" - if states.should_report_srconflict? - f.puts "sr#{states.n_srconflicts}" - end - if states.rrconflict_exist? - f.puts "rr#{states.n_rrconflicts}" - end - } +def warning_summary(warnings) + freq = Hash.new(0) + warnings.each { |w| freq[w.type] += 1 } + types = { + useless_terminal: 'useless terminal', + useless_nonterminal: 'useless nonterminal', + useless_prec: "useless '=' precedence declaration", + useless_rule: 'useless rule', + sr_conflict: 'shift/reduce conflict', + rr_conflict: 'reduce/reduce conflict' + } + order = [:useless_terminal, :useless_nonterminal, :useless_prec, + :useless_rule, :sr_conflict, :rr_conflict] + + freq.sort_by { |k, v| order.index(k) }.map { |k, v| pluralize(v, types[k]) }.join(', ') end -def report_useless(grammar) - if grammar.useless_nonterminal_exist? - $stderr.puts "#{grammar.n_useless_nonterminals} useless nonterminals" - end - if grammar.useless_rule_exist? - $stderr.puts "#{grammar.n_useless_rules} useless rules" +def pluralize(count, noun) + if count == 1 + "#{count} #{noun}" + else + "#{count} #{noun}s" end - if grammar.start.useless? - $stderr.puts 'fatal: start symbol does not derive any sentence' - end -end - -def log_useless(grammar) - logging('a') {|f| - if grammar.useless_nonterminal_exist? - f.puts "un#{grammar.n_useless_nonterminals}" - end - if grammar.useless_rule_exist? - f.puts "ur#{grammar.n_useless_rules}" - end - } -end - -def logging(mode, &block) - File.open("log/#{File.basename(ARGV[0])}", mode, &block) end class RaccProfiler def initialize(really) @really = really @log = [] - unless ::Process.respond_to?(:times) - # Ruby 1.6 - @class = ::Time - else - @class = ::Process - end end def section(name) if @really - t1 = @class.times.utime + t1 = Process.times.utime result = yield - t2 = @class.times.utime + t2 = Process.times.utime @log.push [name, t2 - t1] result else diff --git a/bin/racc2y b/bin/racc2y deleted file mode 100755 index f88d73ed..00000000 --- a/bin/racc2y +++ /dev/null @@ -1,195 +0,0 @@ -#!/usr/local/bin/ruby -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is feee software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the LGPL, see the file "COPYING". -# - -require 'racc/grammarfileparser' -require 'racc/info' -require 'optparse' - -def main - @with_action = true - with_header = false - with_inner = false - with_footer = false - output = nil - parser = OptionParser.new - parser.banner = "Usage: #{File.basename($0)} [-AHIF] [-oFILENAME] GRAMMARFILE" - parser.on('-o', '--output=FILENAME', 'output file name [.yacc]') {|name| - output = name - } - parser.on('-A', '--without-action', 'Does not include actions.') { - @with_action = false - } - parser.on('-H', '--with-header', 'Includes header part.') { - with_header = true - } - parser.on('-I', '--with-inner', 'Includes inner part.') { - with_inner = true - } - parser.on('-F', '--with-footer', 'Includes footer part.') { - with_footer = true - } - parser.on('--version', 'Prints version and quit.') { - puts "racc2y version #{Racc::Version}" - exit 0 - } - parser.on('--copyright', 'Prints copyright and quit.') { - puts Racc::Copyright - exit 0 - } - parser.on('--help', 'Prints this message and quit.') { - puts parser.help - exit 1 - } - begin - parser.parse! - rescue OptionParser::ParseError => err - $stderr.puts err.message - $stderr.puts parser.help - exit 1 - end - if ARGV.empty? - $stderr.puts "no input file" - exit 1 - end - unless ARGV.size == 1 - $stderr.puts "too many inputs" - exit 1 - end - input = ARGV[0] - - begin - result = Racc::GrammarFileParser.parse_file(input) - result.grammar.init - File.open(output || "#{input}.yacc", 'w') {|f| - f.puts "/* generated from #{input} */" - if with_header - f.puts - f.puts '%{' - print_user_codes f, result.params.header - f.puts '%}' - end - f.puts - print_terminals f, result.grammar - f.puts - print_precedence_table f, precedence_table(result.grammar) - f.puts - f.puts '%%' - print_grammar f, result.grammar - f.puts '%%' - if with_inner - f.puts '/*---- inner ----*/' - print_user_codes f, result.params.inner - end - if with_footer - f.puts '/*---- footer ----*/' - print_user_codes f, result.params.footer - end - } - rescue SystemCallError => err - $stderr.puts err.message - exit 1 - end -end - -def print_terminals(f, grammar) - init_indent = '%token'.size - f.print '%token' - columns = init_indent - grammar.symboltable.each_terminal do |t| - next unless t.terminal? - next if t.dummy? - next if t == grammar.symboltable.anchor - next if t == grammar.symboltable.error - unless t.value.kind_of?(String) - if columns > 60 - f.puts - f.print ' ' * init_indent - columns = init_indent - end - columns += f.write(" #{yacc_symbol(t)}") - end - end - f.puts -end - -def precedence_table(grammar) - table = [] - grammar.symboltable.select {|sym| sym.precedence }.each do |sym| - (table[sym.prec] ||= [sym.assoc]).push sym - end - table.compact -end - -def print_precedence_table(f, table) - return if table.empty? - f.puts '/* precedance table */' - table.each do |syms| - assoc = syms.shift - f.printf '%%%-8s ', assoc.to_s.downcase - f.puts syms.map {|s| yacc_symbol(s) }.join(' ') - end - f.puts -end - -def print_grammar(f, grammar) - prev_target = nil - indent = 10 - embactions = [] - grammar.each do |rule| - if rule.target.dummy? - embactions.push rule.action unless rule.action.empty? - next - end - if rule.target == prev_target - f.print ' ' * indent, '|' - else - prev_target = rule.target - f.printf "\n%-10s:", yacc_symbol(prev_target) - end - rule.symbols.each do |s| - if s.dummy? # target of dummy rule for embedded action - f.puts - print_action f, embactions.shift, indent - f.print ' ' * (indent + 1) - else - f.print ' ', yacc_symbol(s) - end - end - if rule.specified_prec - f.print ' %prec ', yacc_symbol(rule.specified_prec) - end - f.puts - unless rule.action.empty? - print_action f, rule.action, indent - end - end -end - -def print_action(f, action, indent) - return unless @with_action - f.print ' ' * (indent + 4), "{\n" - f.print ' ' * (indent + 6), action.source.text.strip, "\n" - f.print ' ' * (indent + 4) , "}\n" -end - -def print_user_codes(f, srcs) - return if srcs.empty? - srcs.each do |src| - f.puts src.text - end -end - -def yacc_symbol(s) - s.to_s.gsub('"', "'") -end - -main diff --git a/bin/y2racc b/bin/y2racc deleted file mode 100755 index 38bd3669..00000000 --- a/bin/y2racc +++ /dev/null @@ -1,339 +0,0 @@ -#!/usr/local/bin/ruby -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public Lisence version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# - -require 'racc/info' -require 'strscan' -require 'forwardable' -require 'optparse' - -def main - @with_action = true - @with_header = false - @with_usercode = false - cname = 'MyParser' - input = nil - output = nil - parser = OptionParser.new - parser.banner = "Usage: #{File.basename($0)} [-Ahu] [-c ] [-o ] " - parser.on('-o', '--output=FILENAME', 'output file name [.racc]') {|name| - output = name - } - parser.on('-c', '--classname=NAME', "Name of the parser class. [#{cname}]") {|name| - cname = name - } - parser.on('-A', '--without-action', 'Does not include actions.') { - @with_action = false - } - parser.on('-h', '--with-header', 'Includes header (%{...%}).') { - @with_header = true - } - parser.on('-u', '--with-user-code', 'Includes user code.') { - @with_usercode = true - } - parser.on('--version', 'Prints version and quit.') { - puts "y2racc version #{Racc::Version}" - exit 0 - } - parser.on('--copyright', 'Prints copyright and quit.') { - puts Racc::Copyright - exit 0 - } - parser.on('--help', 'Prints this message and quit.') { - puts parser.help - exit 1 - } - begin - parser.parse! - rescue OptionParser::ParseError => err - $stderr.puts err.message - $stderr.puts parser.help - exit 1 - end - if ARGV.empty? - $stderr.puts 'no input' - exit 1 - end - if ARGV.size > 1 - $stderr.puts 'too many input' - exit 1 - end - input = ARGV[0] - - begin - result = YaccFileParser.parse_file(input) - File.open(output || "#{input}.racc", 'w') {|f| - convert cname, result, f - } - rescue SystemCallError => err - $stderr.puts err.message - exit 1 - end -end - -def convert(classname, result, f) - init_indent = 'token'.size - f.puts %<# Converted from "#{result.filename}" by y2racc version #{Racc::Version}> - f.puts - f.puts "class #{classname}" - unless result.terminals.empty? - f.puts - f.print 'token' - columns = init_indent - result.terminals.each do |t| - if columns > 60 - f.puts - f.print ' ' * init_indent - columns = init_indent - end - columns += f.write(" #{t}") - end - f.puts - end - unless result.precedence_table.empty? - f.puts - f.puts 'preclow' - result.precedence_table.each do |assoc, toks| - f.printf " %-8s %s\n", assoc, toks.join(' ') unless toks.empty? - end - f.puts 'prechigh' - end - if result.start - f.puts - f.puts "start #{@start}" - end - - f.puts - f.puts 'rule' - texts = @with_action ? result.grammar : result.grammar_without_actions - texts.each do |text| - f.print text - end - - if @with_header and result.header - f.puts - f.puts '---- header' - f.puts result.header - end - if @with_usercode and result.usercode - f.puts - f.puts '---- footer' - f.puts result.usercode - end -end - -class ParseError < StandardError; end - -class StringScanner_withlineno - def initialize(src) - @s = StringScanner.new(src) - @lineno = 1 - end - - extend Forwardable - def_delegator "@s", :eos? - def_delegator "@s", :rest - - attr_reader :lineno - - def scan(re) - advance_lineno(@s.scan(re)) - end - - def scan_until(re) - advance_lineno(@s.scan_until(re)) - end - - def skip(re) - str = advance_lineno(@s.scan(re)) - str ? str.size : nil - end - - def getch - advance_lineno(@s.getch) - end - - private - - def advance_lineno(str) - @lineno += str.count("\n") if str - str - end -end - -class YaccFileParser - - Result = Struct.new(:terminals, :precedence_table, :start, - :header, :grammar, :usercode, :filename) - class Result # reopen - def initialize - super - self.terminals = [] - self.precedence_table = [] - self.start = nil - self.grammar = [] - self.header = nil - self.usercode = nil - self.filename = nil - end - - def grammar_without_actions - grammar().map {|text| text[0,1] == '{' ? '{}' : text } - end - end - - def YaccFileParser.parse_file(filename) - new().parse(File.read(filename), filename) - end - - def parse(src, filename = '-') - @result = Result.new - @filename = filename - @result.filename = filename - s = StringScanner_withlineno.new(src) - parse_header s - parse_grammar s - @result - end - - private - - COMMENT = %r - CHAR = /'((?:[^'\\]+|\\.)*)'/ - STRING = /"((?:[^"\\]+|\\.)*)"/ - - def parse_header(s) - skip_until_percent s - until s.eos? - case - when t = s.scan(/left/) - @result.precedence_table.push ['left', scan_symbols(s)] - when t = s.scan(/right/) - @result.precedence_table.push ['right', scan_symbols(s)] - when t = s.scan(/nonassoc/) - @result.precedence_table.push ['nonassoc', scan_symbols(s)] - when t = s.scan(/token/) - list = scan_symbols(s) - list.shift if /\A<(.*)>\z/ =~ list[0] - @result.terminals.concat list - when t = s.scan(/start/) - @result.start = scan_symbols(s)[0] - when s.skip(%r<(?: - type | union | expect | thong | binary | - semantic_parser | pure_parser | no_lines | - raw | token_table - )\b>x) - skip_until_percent s - when s.skip(/\{/) # header (%{...%}) - str = s.scan_until(/\%\}/) - str.chop! - str.chop! - @result.header = str - skip_until_percent s - when s.skip(/\%/) # grammar (%%...) - return - else - raise ParseError, "#{@filename}:#{s.lineno}: scan error" - end - end - end - - def skip_until_percent(s) - until s.eos? - s.skip /[^\%\/]+/ - next if s.skip(COMMENT) - return if s.getch == '%' - end - end - - def scan_symbols(s) - list = [] - until s.eos? - s.skip /\s+/ - if s.skip(COMMENT) - ; - elsif t = s.scan(CHAR) - list.push t - elsif t = s.scan(STRING) - list.push t - elsif s.skip(/\%/) - break - elsif t = s.scan(/\S+/) - list.push t - else - raise ParseError, "#{@filename}:#{@lineno}: scan error" - end - end - list - end - - def parse_grammar(s) - buf = [] - until s.eos? - if t = s.scan(/[^%'"{\/]+/) - buf.push t - break if s.eos? - end - if s.skip(/\{/) - buf.push scan_action(s) - elsif t = s.scan(/'(?:[^'\\]+|\\.)*'/) then buf.push t - elsif t = s.scan(/"(?:[^"\\]+|\\.)*"/) then buf.push t - elsif t = s.scan(COMMENT) then buf.push t - elsif s.skip(/%prec\b/) then buf.push '=' - elsif s.skip(/%%/) - @result.usercode = s.rest - break - else - buf.push s.getch - end - end - @result.grammar = buf - end - - def scan_action(s) - buf = '{' - nest = 1 - until s.eos? - if t = s.scan(%r<[^/{}'"]+>) - buf << t - break if s.eos? - elsif t = s.scan(COMMENT) - buf << t - elsif t = s.scan(CHAR) - buf << t - elsif t = s.scan(STRING) - buf << t - else - c = s.getch - buf << c - case c - when '{' - nest += 1 - when '}' - nest -= 1 - return buf if nest == 0 - end - end - end - $stderr.puts "warning: unterminated action in #{@filename}" - buf - end - -end - -unless Object.method_defined?(:funcall) - class Object - alias funcall __send__ - end -end - - -main diff --git a/ext/racc/com/headius/racc/Cparse.java b/ext/racc/com/headius/racc/Cparse.java index 1d740656..459f3f69 100644 --- a/ext/racc/com/headius/racc/Cparse.java +++ b/ext/racc/com/headius/racc/Cparse.java @@ -1,3 +1,17 @@ +/* + Cparse.java -- Racc Runtime Core for JRuby + + Copyright (c) 2016 Charles Oliver Nutter + + Ported from and distributed under the same licence as cparse.c + + cparse.c -- Racc Runtime Core + + Copyright (c) 1999-2006 Minero Aoki + + This library is free software. + You can distribute/modify this program under the same terms of ruby. +*/ package com.headius.racc; import org.jruby.Ruby; @@ -7,6 +21,7 @@ import org.jruby.RubyContinuation; import org.jruby.RubyFixnum; import org.jruby.RubyHash; +import org.jruby.RubyKernel; import org.jruby.RubyModule; import org.jruby.RubyNumeric; import org.jruby.RubyObject; @@ -24,13 +39,14 @@ import org.jruby.runtime.Helpers; import org.jruby.runtime.MethodIndex; import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.Signature; import org.jruby.runtime.ThreadContext; import org.jruby.runtime.Visibility; import org.jruby.runtime.builtin.IRubyObject; import org.jruby.runtime.load.Library; public class Cparse implements Library { - public static final String RACC_VERSION = "1.4.13"; // TODO: parse from Cparse.c + public static final String RACC_VERSION = "2.0.0-dev"; // TODO: parse from Cparse.c public enum TokenType { DEFAULT(-1), @@ -233,10 +249,6 @@ private void SHIFT(ThreadContext context, int act, IRubyObject tok, IRubyObject shift(context, act, tok, val); } - private int REDUCE(ThreadContext context, int act) { - return reduce(context, act); - } - public void parse_main(ThreadContext context, IRubyObject tok, IRubyObject val, boolean resume) { Ruby runtime = context.runtime; @@ -267,7 +279,7 @@ public void parse_main(ThreadContext context, IRubyObject tok, IRubyObject val, i = assert_integer(tmp); D_printf("read_next=%d\n", read_next); - if (read_next && (this.t != vFINAL_TOKEN)) { + if (read_next && (!this.t.equals(vFINAL_TOKEN))) { if (this.lex_is_iterator) { D_puts("resuming..."); if (this.fin != 0) throw runtime.newArgumentError("token given after EOF"); @@ -354,7 +366,21 @@ public void parse_main(ThreadContext context, IRubyObject tok, IRubyObject val, } else if (act < 0 && act > -(this.reduce_n)) { D_puts("reduce"); - REDUCE(context, act); + { // macro REDUCE + switch (reduce(context, act)) { + case 0: /* normal */ + break; + case 1: /* yyerror */ + branch = USER_YYERROR; + continue BRANCH; + case 2: /* yyaccept */ + D_puts("u accept"); + branch = ACCEPT; + continue BRANCH; + default: + break; + } + } } else if (act == -(this.reduce_n)) { branch = ERROR; continue BRANCH; @@ -367,6 +393,7 @@ else if (act == this.shift_n) { throw runtime.newRaiseException(RaccBug, "[Cparse Bug] unknown act value " + act); } + // fall through case ERROR_RECOVERED: if (this.debug) { @@ -389,9 +416,10 @@ else if (act == this.shift_n) { call_onerror.call(context, this.parser, this.parser, this.t, val, this.vstack); } + // fall through case USER_YYERROR: if (this.errstatus == 3) { - if (this.t == vFINAL_TOKEN) { + if (this.t.equals(vFINAL_TOKEN)) { this.retval = runtime.getFalse(); this.fin = CP_FIN_EOT; return; @@ -464,7 +492,21 @@ else if (act == this.shift_n) { } else if (act < 0 && act > -(this.reduce_n)) { D_puts("e reduce"); - REDUCE(context, act); + { // macro REDUCE + switch (reduce(context, act)) { + case 0: /* normal */ + break; + case 1: /* yyerror */ + branch = USER_YYERROR; + continue BRANCH; + case 2: /* yyaccept */ + D_puts("u accept"); + branch = ACCEPT; + continue BRANCH; + default: + break; + } + } } else if (act == this.shift_n) { D_puts("e accept"); @@ -489,17 +531,18 @@ private void shift(ThreadContext context, int act, IRubyObject tok, IRubyObject } private int reduce(ThreadContext context, int act) { - IRubyObject code; ruleno = -act * 3; IRubyObject tag = context.runtime.newSymbol("racc_jump"); - RubyContinuation rbContinuation = new RubyContinuation(context.runtime, context.runtime.newSymbol("racc_jump")); - try { - context.pushCatch(rbContinuation.getContinuation()); - code = reduce0(context); - errstatus = assert_integer(parser.getInstanceVariable(ID_ERRSTATUS)); - } finally { - context.popCatch(); - } + IRubyObject code = RubyKernel.rbCatch19(context, this, + tag, + CallBlock19.newCallClosure(this, getMetaClass(), Signature.NO_ARGUMENTS, + new BlockCallback() { + @Override + public IRubyObject call(ThreadContext context, IRubyObject[] args, Block block) { + return reduce0(context); + } + }, context)); + errstatus = assert_integer(parser.getInstanceVariable(ID_ERRSTATUS)); return assert_integer(code); } @@ -527,13 +570,13 @@ private IRubyObject reduce0(ThreadContext context) { /* call action */ if (len == 0) { tmp = context.nil; - if (mid != sym_noreduce) + if (!mid.equals(sym_noreduce)) tmp_v = runtime.newArray(); if (this.debug) tmp_t = runtime.newArray(); } else { - if (mid != sym_noreduce) { + if (!mid.equals(sym_noreduce)) { tmp_v = GET_TAIL(context, this.vstack, len); tmp = ((RubyArray)tmp_v).entry(0); } @@ -547,7 +590,7 @@ private IRubyObject reduce0(ThreadContext context) { } CUT_TAIL(context, this.state, len); } - if (mid != sym_noreduce) { + if (!mid.equals(sym_noreduce)) { if (this.use_result_var) { tmp = Helpers.invoke(context, this.parser, mid.toString(), tmp_v, this.vstack, tmp); } @@ -590,7 +633,7 @@ private IRubyObject reduce0(ThreadContext context) { D_puts("(goto) check[i] == nil"); branch = NOTFOUND; continue BRANCH; } - if (tmp != runtime.newFixnum(k1)) { + if (!tmp.equals(runtime.newFixnum(k1))) { D_puts("(goto) check[i] != table[i]"); branch = NOTFOUND; continue BRANCH; } @@ -759,7 +802,7 @@ public IRubyObject call(ThreadContext context, IRubyObject[] args, Block block) } }, context)); } catch (LexerUnroll maybeOurs) { - if (maybeOurs == lexerUnroll) { + if (maybeOurs.equals(lexerUnroll)) { return; } } diff --git a/ext/racc/cparse.c b/ext/racc/cparse.c index ee9afe1f..d5e367c0 100644 --- a/ext/racc/cparse.c +++ b/ext/racc/cparse.c @@ -1,9 +1,9 @@ /* cparse.c -- Racc Runtime Core - + Copyright (c) 1999-2006 Minero Aoki - + This library is free software. You can distribute/modify this program under the same terms of ruby. @@ -13,12 +13,17 @@ #include +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + /* ----------------------------------------------------------------------- Important Constants ----------------------------------------------------------------------- */ -#define RACC_VERSION "1.4.13" - #define DEFAULT_TOKEN -1 #define ERROR_TOKEN 1 #define FINAL_TOKEN 0 @@ -189,7 +194,7 @@ static VALUE racc_yyparse _((VALUE parser, VALUE lexer, VALUE lexmid, VALUE arg, VALUE sysdebug)); static void call_lexer _((struct cparse_params *v)); -static VALUE lexer_i _((VALUE block_args, VALUE data, VALUE self)); +static VALUE lexer_i _((RB_BLOCK_CALL_FUNC_ARGLIST(block_args, data))); static VALUE assert_array _((VALUE a)); static long assert_integer _((VALUE n)); @@ -197,6 +202,7 @@ static VALUE assert_hash _((VALUE h)); static VALUE initialize_params _((VALUE vparams, VALUE parser, VALUE arg, VALUE lexer, VALUE lexmid)); static void cparse_params_mark _((void *ptr)); +static size_t cparse_params_memsize _((const void *ptr)); static void parse_main _((struct cparse_params *v, VALUE tok, VALUE val, int resume)); @@ -214,35 +220,52 @@ static VALUE reduce0 _((VALUE block_args, VALUE data, VALUE self)); # define D_printf(fmt,arg) #endif +#undef RUBY_UNTYPED_DATA_WARNING +#define RUBY_UNTYPED_DATA_WARNING 1 + +static const rb_data_type_t cparse_params_type = { + "racc/cparse", + { + cparse_params_mark, + RUBY_TYPED_DEFAULT_FREE, + cparse_params_memsize, + }, +#ifdef RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, + RUBY_TYPED_FREE_IMMEDIATELY, +#endif +}; + static VALUE racc_cparse(VALUE parser, VALUE arg, VALUE sysdebug) { - volatile VALUE vparams; + VALUE vparams; struct cparse_params *v; - vparams = Data_Make_Struct(CparseParams, struct cparse_params, - cparse_params_mark, -1, v); + vparams = TypedData_Make_Struct(CparseParams, struct cparse_params, + &cparse_params_type, v); D_puts("starting cparse"); v->sys_debug = RTEST(sysdebug); vparams = initialize_params(vparams, parser, arg, Qnil, Qnil); - v->lex_is_iterator = Qfalse; + v->lex_is_iterator = FALSE; parse_main(v, Qnil, Qnil, 0); + RB_GC_GUARD(vparams); return v->retval; } static VALUE racc_yyparse(VALUE parser, VALUE lexer, VALUE lexmid, VALUE arg, VALUE sysdebug) { - volatile VALUE vparams; + VALUE vparams; struct cparse_params *v; - vparams = Data_Make_Struct(CparseParams, struct cparse_params, - cparse_params_mark, -1, v); + vparams = TypedData_Make_Struct(CparseParams, struct cparse_params, + &cparse_params_type, v); v->sys_debug = RTEST(sysdebug); D_puts("start C yyparse"); vparams = initialize_params(vparams, parser, arg, lexer, lexmid); - v->lex_is_iterator = Qtrue; + v->lex_is_iterator = TRUE; D_puts("params initialized"); parse_main(v, Qnil, Qnil, 0); call_lexer(v); @@ -251,6 +274,7 @@ racc_yyparse(VALUE parser, VALUE lexer, VALUE lexmid, VALUE arg, VALUE sysdebug) rb_id2name(v->lexmid)); } + RB_GC_GUARD(vparams); return v->retval; } @@ -264,9 +288,8 @@ call_lexer(struct cparse_params *v) static VALUE lexer_iter(VALUE data) { - struct cparse_params *v; + struct cparse_params *v = rb_check_typeddata(data, &cparse_params_type); - Data_Get_Struct(data, struct cparse_params, v); rb_funcall(v->lexer, v->lexmid, 0); return Qnil; } @@ -279,18 +302,17 @@ call_lexer(struct cparse_params *v) #endif static VALUE -lexer_i(VALUE block_args, VALUE data, VALUE self) +lexer_i(RB_BLOCK_CALL_FUNC_ARGLIST(block_args, data)) { - struct cparse_params *v; + struct cparse_params *v = rb_check_typeddata(data, &cparse_params_type); VALUE tok, val; - Data_Get_Struct(data, struct cparse_params, v); if (v->fin) rb_raise(rb_eArgError, "extra token after EndOfToken"); extract_user_token(v, block_args, &tok, &val); parse_main(v, tok, val, 1); if (v->fin && v->fin != CP_FIN_ACCEPT) - rb_iter_break(); + rb_iter_break(); return Qnil; } @@ -317,9 +339,8 @@ assert_integer(VALUE n) static VALUE initialize_params(VALUE vparams, VALUE parser, VALUE arg, VALUE lexer, VALUE lexmid) { - struct cparse_params *v; + struct cparse_params *v = rb_check_typeddata(vparams, &cparse_params_type); - Data_Get_Struct(vparams, struct cparse_params, v); v->value_v = vparams; v->parser = parser; v->lexer = lexer; @@ -348,7 +369,7 @@ initialize_params(VALUE vparams, VALUE parser, VALUE arg, VALUE lexer, VALUE lex v->use_result_var = RTEST(rb_ary_entry(arg, 13)); } else { - v->use_result_var = Qtrue; + v->use_result_var = TRUE; } v->tstack = v->debug ? NEW_STACK() : Qnil; @@ -364,7 +385,7 @@ initialize_params(VALUE vparams, VALUE parser, VALUE arg, VALUE lexer, VALUE lex v->retval = Qnil; v->fin = 0; - v->lex_is_iterator = Qfalse; + v->lex_is_iterator = FALSE; rb_iv_set(parser, "@vstack", v->vstack); if (v->debug) { @@ -402,6 +423,12 @@ cparse_params_mark(void *ptr) rb_gc_mark(v->retval); } +static size_t +cparse_params_memsize(const void *ptr) +{ + return sizeof(struct cparse_params); +} + static void extract_user_token(struct cparse_params *v, VALUE block_args, VALUE *tok, VALUE *val) @@ -413,12 +440,12 @@ extract_user_token(struct cparse_params *v, VALUE block_args, return; } - if (TYPE(block_args) != T_ARRAY) { + if (!RB_TYPE_P(block_args, T_ARRAY)) { rb_raise(rb_eTypeError, - "%s() %s %s (must be Array[2])", + "%s() %s %"PRIsVALUE" (must be Array[2])", v->lex_is_iterator ? rb_id2name(v->lexmid) : "next_token", v->lex_is_iterator ? "yielded" : "returned", - rb_class2name(CLASS_OF(block_args))); + rb_obj_class(block_args)); } if (RARRAY_LEN(block_args) != 2) { rb_raise(rb_eArgError, @@ -457,7 +484,7 @@ parse_main(struct cparse_params *v, VALUE tok, VALUE val, int resume) if (resume) goto resume; - + while (1) { D_puts(""); D_puts("---- enter new loop ----"); @@ -516,7 +543,7 @@ parse_main(struct cparse_params *v, VALUE tok, VALUE val, int resume) act_fixed: D_printf("act=%ld\n", act); goto handle_act; - + notfound: D_puts("(act) not found: use default"); act_value = AREF(v->action_default, v->curstate); @@ -617,7 +644,7 @@ parse_main(struct cparse_params *v, VALUE tok, VALUE val, int resume) D_puts("(err) found: can handle error token"); break; - + error_pop: D_puts("(err) act not found: can't handle error token; pop"); @@ -681,7 +708,7 @@ reduce(struct cparse_params *v, long act) static VALUE reduce0(VALUE val, VALUE data, VALUE self) { - struct cparse_params *v; + struct cparse_params *v = rb_check_typeddata(data, &cparse_params_type); VALUE reduce_to, reduce_len, method_id; long len; ID mid; @@ -689,7 +716,6 @@ reduce0(VALUE val, VALUE data, VALUE self) long i, k1, k2; VALUE goto_state; - Data_Get_Struct(data, struct cparse_params, v); reduce_len = rb_ary_entry(v->reduce_table, v->ruleno); reduce_to = rb_ary_entry(v->reduce_table, v->ruleno+1); method_id = rb_ary_entry(v->reduce_table, v->ruleno+2); @@ -791,6 +817,8 @@ reduce0(VALUE val, VALUE data, VALUE self) void Init_cparse(void) { +#undef rb_intern +#define rb_intern(str) rb_intern_const(str) VALUE Racc, Parser; ID id_racc = rb_intern("Racc"); @@ -804,12 +832,11 @@ Init_cparse(void) } rb_define_private_method(Parser, "_racc_do_parse_c", racc_cparse, 2); rb_define_private_method(Parser, "_racc_yyparse_c", racc_yyparse, 4); - rb_define_const(Parser, "Racc_Runtime_Core_Version_C", - rb_str_new2(RACC_VERSION)); - rb_define_const(Parser, "Racc_Runtime_Core_Id_C", - rb_str_new2("$originalId: cparse.c,v 1.8 2006/07/06 11:39:46 aamine Exp $")); CparseParams = rb_define_class_under(Racc, "CparseParams", rb_cObject); + rb_undef_alloc_func(CparseParams); + rb_undef_method(CparseParams, "initialize"); + rb_undef_method(CparseParams, "initialize_copy"); RaccBug = rb_eRuntimeError; diff --git a/ext/racc/depend b/ext/racc/depend index 7b06a880..441d4df0 100644 --- a/ext/racc/depend +++ b/ext/racc/depend @@ -1 +1,12 @@ -cparse.o: cparse.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h +# AUTOGENERATED DEPENDENCIES START +cparse.o: $(RUBY_EXTCONF_H) +cparse.o: $(arch_hdrdir)/ruby/config.h +cparse.o: $(hdrdir)/ruby/backward.h +cparse.o: $(hdrdir)/ruby/defines.h +cparse.o: $(hdrdir)/ruby/intern.h +cparse.o: $(hdrdir)/ruby/missing.h +cparse.o: $(hdrdir)/ruby/ruby.h +cparse.o: $(hdrdir)/ruby/st.h +cparse.o: $(hdrdir)/ruby/subst.h +cparse.o: cparse.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/racc/extconf.rb b/ext/racc/extconf.rb index 1e30abed..35bf7b17 100644 --- a/ext/racc/extconf.rb +++ b/ext/racc/extconf.rb @@ -1,7 +1,8 @@ -# $Id$ - require 'mkmf' +load File.join(File.dirname(__FILE__), '..', '..', 'lib', 'racc', 'info.rb') have_func('rb_ary_subseq') +$defs.push("-DRACC_VERSION=\"#{Racc::VERSION}\"") + create_makefile 'racc/cparse' diff --git a/fastcache/extconf.rb b/fastcache/extconf.rb deleted file mode 100644 index e010aa79..00000000 --- a/fastcache/extconf.rb +++ /dev/null @@ -1,2 +0,0 @@ -require 'mkmf' -create_makefile 'corecache' diff --git a/fastcache/fastcache.c b/fastcache/fastcache.c deleted file mode 100644 index 2656ce8d..00000000 --- a/fastcache/fastcache.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - $Id$ - - Copyright (C) 2005 Minero Aoki - - This program is free software. - You can distribute/modify this program under the terms of - the GNU LGPL, Lesser General Public Licese version 2.1. -*/ - -#include "ruby.h" - -static VALUE LALRcoreCache; - -struct item_holder { - unsigned long hashval; - VALUE core; - VALUE state; - struct item_holder *next; -}; - -struct lalr_state_cache { - struct item_holder **bin; - long size; - long num; -}; - -static void -lalrc_free(struct lalr_state_cache *p) -{ - struct item_holder *tmp; - long i; - - for (i = 0; i < p->size; i++) { - while (tmp = p->bin[i]) { - p->bin[i] = tmp->next; - free(tmp); - } - } - free(p->bin); - free(p); -} - -#define INIT_BIN 256 - -static VALUE -lalrc_s_new(VALUE self) -{ - struct lalr_state_cache *cache; - - cache = ALLOC_N(struct lalr_state_cache, 1); - cache->bin = ALLOC_N(struct item_holder*, INIT_BIN); - cache->size = INIT_BIN; - cache->num = 0; - return Data_Wrap_Struct(LALRcoreCache, 0, lalrc_free, cache); -} - -#define GET_LALRC(self, p) Data_Get_Struct(self, struct lalr_state_cache, p) - -static void -lalrc_rehash(struct lalr_state_cache *p) -{ - struct item_holder *top = 0, *tmp = 0; - long i; - - for (i = p->size / 2; i < p->size; i++) { - p->bin[i] = 0; - } - for (i = 0; i < p->size / 2; i++) { - if (!p->bin[i]) - continue; - - tmp = p->bin[i]; - while (tmp->next) - tmp = tmp->next; - tmp->next = top; - top = p->bin[i]; - p->bin[i] = 0; - } - - while (top) { - tmp = top; - top = tmp->next; - tmp->next = 0; - - i = tmp->hashval % p->size; - if (p->bin[i]) { - tmp->next = p->bin[i]; - p->bin[i] = tmp; - } - else { - p->bin[i] = tmp; - } - } -} - -static int -coreeql(VALUE a, VALUE b) -{ - long i; - - /* Check_Type(a, T_ARRAY); - Check_Type(b, T_ARRAY); */ - if (RARRAY(a)->len != RARRAY(b)->len) - return 0; - for (i = 0; i < RARRAY(a)->len; i++) - if (RARRAY(a)->ptr[i] != RARRAY(b)->ptr[i]) - return 0; - - return 1; -} - -static unsigned long -hashval(VALUE core) -{ - unsigned long v = 0; - long i, j; - - for (i = 0; i < RARRAY(core)->len; i++) { - v *= RARRAY(core)->ptr[i]; - v ^= RARRAY(core)->ptr[i]; - } - return v; -} - -static VALUE -lalrc_aref(VALUE self, VALUE core) -{ - struct lalr_state_cache *p; - unsigned long v; - long i; - struct item_holder *ad; - - /* Check_Type(core, T_ARRAY); */ - GET_LALRC(self, p); - v = hashval(core); - i = v % p->size; - ad = p->bin[i]; - while (ad) { - if (ad->hashval == v) { - if (coreeql(core, ad->core)) { - return ad->state; - } - else { -printf("."); - } - } - ad = ad->next; - } - return Qnil; -} - -static VALUE -lalrc_add_direct(VALUE self, VALUE core, VALUE state) -{ - struct lalr_state_cache *p; - struct item_holder *ad; - long i; - - GET_LALRC(self, p); - ad = ALLOC_N(struct item_holder, 1); - ad->hashval = hashval(core); - ad->core = core; - ad->state = state; - - i = ad->hashval % p->size; - ad->next = p->bin[i]; - p->bin[i] = ad; - p->num++; - if ((p->num / p->size) >= 1) { - REALLOC_N(p->bin, struct item_holder*, p->size * 2); - p->size *= 2; - lalrc_rehash(p); - } - return Qnil; -} - -void -Init_corecache(void) -{ - LALRcoreCache = rb_define_class("LALRcoreCache", rb_cObject); - rb_define_singleton_method(LALRcoreCache, "new", lalrc_s_new, 0); - rb_define_method(LALRcoreCache, "[]", lalrc_aref, 1); - rb_define_method(LALRcoreCache, "[]=", lalrc_add_direct, 2); -} diff --git a/lib/racc.rb b/lib/racc.rb index f6e4ac03..eefd0327 100644 --- a/lib/racc.rb +++ b/lib/racc.rb @@ -1,5 +1,3 @@ -require 'racc/compat' -require 'racc/debugflags' require 'racc/grammar' require 'racc/state' require 'racc/exception' diff --git a/lib/racc/color.rb b/lib/racc/color.rb new file mode 100644 index 00000000..27194f73 --- /dev/null +++ b/lib/racc/color.rb @@ -0,0 +1,65 @@ +module Racc + # Support module for printing colored text to an ANSI terminal + module Color + extend self + @color_enabled = false + + def self.enabled=(enabled) + @color_enabled = enabled + end + + def self.enabled? + @color_enabled + end + + def self.without_color + saved = @color_enabled + @color_enabled = false + yield + ensure + @color_enabled = saved + end + + def bright(text) + return text unless Color.enabled? + text = text.gsub(/\e\[.*?m[^\e]*\e\[0m/, "\e[0m\\0\e[1m") + String.new "\e[1m#{text}\e[0m" + end + + def red(text) + return text unless Color.enabled? + String.new "\e[31m#{text}\e[0m" + end + + def green(text) + return text unless Color.enabled? + String.new "\e[32m#{text}\e[0m" + end + + def violet(text) + return text unless Color.enabled? + String.new "\e[1;35m#{text}\e[0m" + end + + # Syntax highlighting for various types of symbols... + def nonterminal(text) + return text unless Color.enabled? + String.new "\e[1;34m#{text}\e[0m" # blue + end + + def terminal(text) + return text unless Color.enabled? + String.new "\e[1;36m\e[4m#{text}\e[0m" # cyan, with underline + end + + def string(text) + return text unless Color.enabled? + String.new "\e[1;33m#{text}\e[0m" # bright yellow + end + + def explicit_prec(text) + return text unless Color.enabled? + String.new "\e[1;31m#{text}\e[0m" # bright reddish orange + end + end +end diff --git a/lib/racc/compat.rb b/lib/racc/compat.rb deleted file mode 100644 index 14fa1118..00000000 --- a/lib/racc/compat.rb +++ /dev/null @@ -1,32 +0,0 @@ -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# - -unless Object.method_defined?(:__send) - class Object - alias __send __send__ - end -end - -unless Object.method_defined?(:__send!) - class Object - alias __send! __send__ - end -end - -unless Array.method_defined?(:map!) - class Array - if Array.method_defined?(:collect!) - alias map! collect! - else - alias map! filter - end - end -end diff --git a/lib/racc/debugflags.rb b/lib/racc/debugflags.rb deleted file mode 100644 index 74ff4369..00000000 --- a/lib/racc/debugflags.rb +++ /dev/null @@ -1,59 +0,0 @@ -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of LGPL, see the file "COPYING". -# - -module Racc - - class DebugFlags - def DebugFlags.parse_option_string(s) - parse = rule = token = state = la = prec = conf = false - s.split(//).each do |ch| - case ch - when 'p' then parse = true - when 'r' then rule = true - when 't' then token = true - when 's' then state = true - when 'l' then la = true - when 'c' then prec = true - when 'o' then conf = true - else - raise "unknown debug flag char: #{ch.inspect}" - end - end - new(parse, rule, token, state, la, prec, conf) - end - - def initialize(parse = false, rule = false, token = false, state = false, - la = false, prec = false, conf = false) - @parse = parse - @rule = rule - @token = token - @state = state - @la = la - @prec = prec - @any = (parse || rule || token || state || la || prec) - @status_logging = conf - end - - attr_reader :parse - attr_reader :rule - attr_reader :token - attr_reader :state - attr_reader :la - attr_reader :prec - - def any? - @any - end - - attr_reader :status_logging - end - -end diff --git a/lib/racc/directed_graph.rb b/lib/racc/directed_graph.rb new file mode 100644 index 00000000..df0c2566 --- /dev/null +++ b/lib/racc/directed_graph.rb @@ -0,0 +1,383 @@ +require 'racc/util' +require 'racc/color' +require 'tempfile' +require 'set' + +module Racc + module Graph + # Algorithms which work on any of the graph implementations below + module Algorithms + # shortest path between nodes; both start and end points are included + def shortest_path(start, dest) + # Dijkstra's algorithm + return [start] if start == dest + + visited = Set[start] + worklist = [start] + paths = {start => [start]} + + until visited.include?(dest) + return nil if worklist.empty? + node = worklist.shift + node_path = paths[node] + + children(node) do |child| + child_path = paths[child] + if child_path.nil? || child_path.size > node_path.size + 1 + paths[child] = node_path.dup << child + end + worklist << child unless visited.include?(child) + end + + visited << node + end + + paths[dest] + end + + # { node -> shortest path to it from start node } + # if a block is provided, it is a 'cost function' + # all paths include both start and end points + def shortest_paths + # again, Dijkstra's algorithm + paths = {@start => [0, @start]} # cache total path cost + + Racc.set_closure([@start]) do |node| + node_path = paths[node] + children(node) do |child| + child_path = paths[child] + cost = block_given? ? yield(node, child) : 1 + if child_path.nil? || child_path[0] > node_path[0] + cost + paths[child] = node_path.dup.tap { |p| p[0] += cost } << child + end + end + end + + paths.each_value { |p| p.shift } # drop cached total costs + paths + end + + # only paths with no loops will be found + # start and end points are included + # this can be very slow on graphs with a lot of transitions! + def all_paths(src, dest, current=src, traversed=[src], result=[]) + children(current) do |child| + if child == dest + result << (traversed.dup << child) + elsif !traversed.include?(child) + traversed.push(child) + all_paths(src, dest, child, traversed, result) + traversed.pop + end + end + result + end + + def to_gif(options={}) + filename = options[:filename] || "graph.gif" + filename <<= ".gif" unless filename.end_with?(".gif") + Tempfile.open("graph") do |f| + f.write(self.to_dot(options)) + f.flush + `dot -Tgif #{f.path} -o "#{filename}"` + end + end + + def to_dot(options={}) + s = "digraph {\n" + s <<= "graph [label=\"#{options[:title]}\"]\n" if options[:title] + (options[:highlight] || []).each do |node| + s <<= "\"#{node.hash}\" [style=filled fillcolor=gold]\n" + end + s <<= nodes.map do |node| + %{"#{node.hash}" [label="#{node_caption(node)}"]} << + children(node).map { |child| %{"#{node.hash}" -> "#{child.hash}"} }.join("\n") + end.join("\n") + s << "}" + end + end + + # An implementation which is fast when the exact number of nodes is known + # in advance, and each one can be identified by an integer + class Finite < Array + include Algorithms + + def initialize(size) + super(size) { Set.new } + @start = nil + end + + def start=(idx) + @start = idx + end + + def add_child(from, to) + self[from] << to + to + end + + def remove_child(from, to) + self[from].delete(to) + end + + alias nodes each_index + + def children(node, &block) + result = self[node] + result.each(&block) if block_given? + result + end + + def reachable + reachable_from([@start]) + end + + def reachable_from(nodes) + Racc.set_closure(nodes) { |node| self[node] } + end + + def leaves + reachable.select { |node| self[node].empty? } + end + + def dup + super.map!(&:dup) + end + + def freeze + each(&:freeze) + end + end + + # Like Graph::Finite, but with backpointers from children to parents as well + class Reversible < Finite + def initialize(size) + super(size * 2) + @offset = size + end + + def add_child(from, to) + self[from] << to + self[@offset + to] << from + to + end + + def remove_child(from, to) + self[from].delete(to) + self[@offset + to].delete(from) + end + + def remove_node(node) + self[node].each { |child| self[@offset + child].delete(node) }.clear + self[@offset + node].each { |parent| self[parent].delete(node) }.clear + end + + def nodes(&block) + result = 0...@offset + result.each(&block) if block_given? + result + end + + def parents(node, &block) + result = self[@offset + node] + result.each(&block) if block_given? + result + end + + # All nodes which can reach a node in `dests` (and `dests` themselves) + def can_reach(dests) + Racc.set_closure(dests) { |node| self[@offset + node] } + end + end + + # Each vector has a label; labels are unique for any source node + # There can be multiple vectors from one node to another, as long as + # each vector has a different label + class Labeled < Array + include Algorithms + + def initialize(size) + super(size) { {} } + concat(map { Set.new }) # backpointers + @start = nil + @offset = size + end + + attr_reader :start + + def start=(idx) + @start = idx + end + + def add_vector(from, to, label) + if self[from].key?(label) + raise "Vector #{label.inspect} from node #{from} already exists" + end + self[from][label] = to + self[to + @offset] << from + to + end + + def remove_vector(from, to, label) + self[from].delete(label) + self[to + @offset].delete(from) + end + + def nodes(&block) + result = 0...@offset + result.each(&block) if block_given? + result + end + + def children(node, &block) + result = self[node].values + result.each(&block) if block_given? + result + end + + def vectors(node, &block) + result = self[node] + result.each(&block) if block_given? + result + end + + def parents(node, &block) + result = self[@offset + node] + result.each(&block) if block_given? + result + end + + def reachable + reachable_from([@start]) + end + + def reachable_from(nodes) + Racc.set_closure(nodes) { |node| self[node].values } + end + + def leaves + reachable.select { |node| self[node].empty? } + end + + # like #all_paths, but return sequences of vector labels, not sequences + # of nodes + def all_vector_paths(src, dest, current=src, kill=0, path=[], result=[]) + vectors(current) do |label, child| + if child == dest + result << (path.dup << label) + elsif kill[child] == 0 + path.push(label) + all_vector_paths(src, dest, child, kill | (1 << child), path, result) + path.pop + end + end + result + end + + # like #shortest_paths, but return sequences of vector labels + def shortest_vector_paths + paths = {@start => [0]} # cache total path cost + + Racc.set_closure([@start]) do |node| + node_path = paths[node] + vectors(node) do |label, child| + child_path = paths[child] + cost = block_given? ? yield(label) : 1 + if child_path.nil? || child_path[0] > node_path[0] + cost + paths[child] = node_path.dup.tap { |p| p[0] += cost } << label + end + end + children(node) + end + + paths.each_value { |p| p.shift } # drop cached total costs + paths + end + + def dup + super.map!(&:dup) + end + + def freeze + each(&:freeze) + end + end + + # This implementation uses an object for each node, rather than identifying + # nodes by integers + # this means we can add as many nodes as we want + # Graph::Node can also be subclassed and have extra methods added + class Generic + include Algorithms + + def initialize + @nodes = Set.new + @start = nil + end + + attr_reader :nodes, :start + + def start=(node) + @nodes << node + @start = node + end + + def remove_node(node) + @start = nil if node == @start + @nodes.delete(node) + node.out.each { |other| other.in.delete?(node) } + node.in.each { |other| other.out.delete?(node) } + end + + def add_child(from, to) + @nodes << to + from.out << to + to.in << from + to + end + + def remove_child(from, to) + from.out.delete(to) + to.in.delete(from) + end + + def children(node, &block) + node.out.each(&block) if block_given? + node.out + end + + def reachable + reachable_from([@start]) + end + + def reachable_from(nodes) + Racc.set_closure(nodes) { |node| node.out } + end + + def can_reach(dests) + Racc.set_closure(dests) { |node| node.in } + end + + def leaves + @nodes.select { |node| node.out.empty? } + end + + def node_caption(node) + Color.without_color { node.ptr.to_s } + end + + def freeze + super + @nodes.each(&:freeze) + end + end + + class Node + def initialize + @out, @in = Set.new, Set.new + end + + attr_reader :out, :in + end + end +end diff --git a/lib/racc/dsl.rb b/lib/racc/dsl.rb new file mode 100644 index 00000000..d79623be --- /dev/null +++ b/lib/racc/dsl.rb @@ -0,0 +1,193 @@ +module Racc + # DSL for defining a grammar in code, rather than using a grammar file + module DSL + def self.define_grammar(&block) + env = DefinitionEnv.new + env.instance_eval(&block) + env.grammar + end + + # Methods are DSL 'keywords' which can be used in a `define_grammar` block + # + # Key method is `#seq`, which creates a `Rule` + # (`Rule` objects can be combined using `#|`, similar to how alternative + # derivations for a non-terminal are separated by | in a BNF grammar) + # + # Other key method is `#method_missing`, which is used to register rules: + # + # self.nonterminal_name = seq(:token, :another_token) | seq(:something_else) + # + class DefinitionEnv + def initialize + @grammar = Grammar.new + @seqs = Hash.new(0) + @delayed = [] + end + + def grammar + flush_delayed + @grammar.finished! + @grammar + end + + # Intercept calls to `self.non_terminal = ...`, and use them to register + # a new rule + def method_missing(mid, *args, &block) + unless mid.to_s[-1,1] == '=' + super # raises NoMethodError + end + target = @grammar.intern(mid.to_s.chop.intern) + unless args.size == 1 + raise ArgumentError, "too many arguments for #{mid} (#{args.size} for 1)" + end + _add(target, args.first) + end + + # We just received a call to `self.nonterminal = definition` + # But when we were executing that "definition", we didn't know what the + # nonterminal on the LHS would be + # Depending on the DSL method(s) which were used in the "definition", + # `rhs` may be: + # - A "placeholder" target symbol, which should be replaced with the + # "real" target in all the rules which the definition created + # - A `Rule`, whose target we didn't know at the time of definition. + # Its target will be `nil` right now; fix that up. + def _add(target, rhs) + case rhs + when Sym + @delayed.each do |rule| + rule.replace(rhs, target) if rule.target == rhs + end + @grammar.delete_symbol(rhs) + else + rhs.each_rule do |rule| + rule.target = target + @grammar.add(rule) + end + end + flush_delayed + end + + def _delayed_add(rule) + @delayed.push(rule) + end + + def _added?(sym) + @grammar.added?(sym) or @delayed.detect {|r| r.target == sym } + end + + def flush_delayed + return if @delayed.empty? + @delayed.each do |rule| + @grammar.add rule + end + @delayed.clear + end + + # Basic method for creating a new `Rule`. + def seq(*list, &block) + Rule.new(nil, list.map {|x| _intern(x) }, UserAction.proc(block)) + end + + # Create a null `Rule` (one with an empty RHS) + def null(&block) + seq(&block) + end + + # Create a `Rule` which can either be null (like an empty RHS in a BNF grammar), + # in which case the action will return `default`, or which can match a single + # `sym`. + def option(sym, default = nil, &block) + _defmetasyntax("option", _intern(sym), block) {|target| + seq() { default } | seq(sym) + } + end + + # Create a `Rule` which matches 0 or more instance of `sym` in a row. + def many(sym, &block) + _defmetasyntax("many", _intern(sym), block) {|target| + seq() { [] }\ + | seq(target, sym) {|list, x| list.push x; list } + } + end + + # Create a `Rule` which matches 1 or more instances of `sym` in a row. + def many1(sym, &block) + _defmetasyntax("many1", _intern(sym), block) {|target| + seq(sym) {|x| [x] }\ + | seq(target, sym) {|list, x| list.push x; list } + } + end + + # Create a `Rule` which matches 0 or more instances of `sym`, separated + # by `sep`. + def separated_by(sep, sym, &block) + option(separated_by1(sep, sym), [], &block) + end + + # Create a `Rule` which matches 1 or more instances of `sym`, separated + # by `sep`. + def separated_by1(sep, sym, &block) + _defmetasyntax("separated_by1", _intern(sym), block) {|target| + seq(sym) {|x| [x] }\ + | seq(target, sep, sym) {|list, _, x| list.push x; list } + } + end + + def _intern(x) + case x + when Symbol, String + @grammar.intern(x) + when Racc::Sym + x + else + raise TypeError, "wrong type #{x.class} (expected Symbol/String/Racc::Sym)" + end + end + + private + + # the passed block will define a `Rule` (which may be chained with + # 'alternative' `Rule`s) + # make all of those rules reduce to a placeholder nonterminal, + # executing `action` when they do so, + # and return the newly generated placeholder + # + # (when the placeholder is associated with a "real" nonterminal using the + # `self.non_terminal = ...` syntax, we will go through all the generated + # rules and rewrite the placeholder to the "real" nonterminal) + # + def _defmetasyntax(type, id, action, &block) + if action + idbase = :"#{type}@#{id}-#{@seqs[type] += 1}" + _regist(:"#{idbase}-core", &block) + _wrap(idbase, :"#{idbase}-core", action) + else + _regist(:"#{type}@#{id}", &block) + end + end + + def _regist(target) + sym = @grammar.intern(target) + unless _added?(sym) + yield(target).each_rule do |rule| + rule.target = sym + _delayed_add(rule) + end + end + sym + end + + # create a rule which reduces wrapped -> wrapper and executes an + # action at the same time + # (this is a way to make sure an action is executed everytime a + # reduction is done using a particular generated rule) + def _wrap(wrapper, wrapped, block) + wrapped = @grammar.intern(wrapped) + wrapper = @grammar.intern(wrapper) + _delayed_add Rule.new(wrapper, [wrapped], UserAction.proc(block)) + wrapper + end + end + end +end \ No newline at end of file diff --git a/lib/racc/exception.rb b/lib/racc/exception.rb index a26517cc..d6ef6fd5 100644 --- a/lib/racc/exception.rb +++ b/lib/racc/exception.rb @@ -1,15 +1,11 @@ -# -# $Id$ -# # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". module Racc - class Error < StandardError; end - class CompileError < Error; end + class CompileError < StandardError; end + class ScanError < CompileError; end + class ParseError < CompileError; end end diff --git a/lib/racc/grammar.rb b/lib/racc/grammar.rb index 733f7084..f1f16287 100644 --- a/lib/racc/grammar.rb +++ b/lib/racc/grammar.rb @@ -1,59 +1,63 @@ -# -# $Id$ -# # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". -require 'racc/compat' -require 'racc/iset' -require 'racc/sourcetext' -require 'racc/logfilegenerator' +require 'racc/source' require 'racc/exception' -require 'forwardable' +require 'racc/color' +require 'racc/warning' +require 'racc/util' +require 'set' module Racc - class Grammar + include Enumerable + + def initialize + @symbols = [] # all Syms used in a grammar + @cache = {} # map of String/Symbol name -> Sym + @rules = [] + @start = nil - def initialize(debug_flags = DebugFlags.new) - @symboltable = SymbolTable.new - @debug_symbol = debug_flags.token - @rules = [] # :: [Rule] - @start = nil @n_expected_srconflicts = nil + @prec_table = [] @prec_table_closed = false + @closed = false - @states = nil + + # 'dummy' and 'anchor' are used to make sure the parser runs over ALL the + # input tokens before concluding that the parse was successful + # an 'anchor' token is appended to the end of the token stream, and a + # 'dummy rule' is automatically added which looks like: + # dummy : start anchor anchor + # We never actually reduce to the dummy symbol; instead, we manually set + # 'dummy : start anchor . anchor' to be an 'accept state' + + @dummy = intern(:$start, true) + @anchor = intern(false, true) # Symbol ID = 0 + @error = intern(:error, true) # Symbol ID = 1 end attr_reader :start - attr_reader :symboltable - attr_accessor :n_expected_srconflicts + attr_reader :n_expected_srconflicts + attr_reader :terminals + attr_reader :nonterminals + attr_reader :symbols + attr_reader :dummy + attr_reader :anchor + attr_reader :error def [](x) @rules[x] end - def each_rule(&block) + def each(&block) @rules.each(&block) end - alias each each_rule - - def each_index(&block) - @rules.each_index(&block) - end - - def each_with_index(&block) - @rules.each_with_index(&block) - end - def size @rules.size end @@ -62,106 +66,88 @@ def to_s "" end - extend Forwardable - - def_delegator "@symboltable", :each, :each_symbol - def_delegator "@symboltable", :each_terminal - def_delegator "@symboltable", :each_nonterminal - - def intern(value, dummy = false) - @symboltable.intern(value, dummy) + def intern(val, generated = false) + if @closed + @cache[val] || (raise "No such symbol: #{val}") + else + @cache[val] ||= Sym.new(val, self, generated).tap { |sym| @symbols.push(sym) } + end end - def symbols - @symboltable.symbols + def delete_symbol(sym) + @symbols.delete(sym) + @cache.delete(sym.value) end - def nonterminal_base - @symboltable.nt_base + def states + raise 'Grammar not yet closed' unless @closed + @states ||= States.new(self) end - def useless_nonterminal_exist? - n_useless_nonterminals() != 0 + def sr_conflicts + states.sr_conflicts end - def n_useless_nonterminals - @n_useless_nonterminals ||= - begin - n = 0 - @symboltable.each_nonterminal do |sym| - n += 1 if sym.useless? - end - n - end + def rr_conflicts + states.rr_conflicts end - def useless_rule_exist? - n_useless_rules() != 0 - end - - def n_useless_rules - @n_useless_rules ||= - begin - n = 0 - each do |r| - n += 1 if r.useless? - end - n - end + def nonterminal_base + @terminals.size end - def nfa - (@states ||= States.new(self)).nfa + def locations + raise 'Grammar not yet closed' unless @closed + @locations ||= @rules.flat_map(&:ptrs) end - def dfa - (@states ||= States.new(self)).dfa + def n_expected_srconflicts=(value) + raise CompileError, "'expect' seen twice" if @n_expected_srconflicts + @n_expected_srconflicts = value end - alias states dfa - def state_transition_table - states().state_transition_table + states.state_transition_table end def parser_class - states = states() # cache - if $DEBUG - srcfilename = caller(1).first.slice(/\A(.*?):/, 1) - begin - write_log srcfilename + ".output" - rescue SystemCallError - end - report = lambda {|s| $stderr.puts "racc: #{srcfilename}: #{s}" } - if states.should_report_srconflict? - report["#{states.n_srconflicts} shift/reduce conflicts"] - end - if states.rrconflict_exist? - report["#{states.n_rrconflicts} reduce/reduce conflicts"] - end - g = states.grammar - if g.useless_nonterminal_exist? - report["#{g.n_useless_nonterminals} useless nonterminals"] - end - if g.useless_rule_exist? - report["#{g.n_useless_rules} useless rules"] + state_transition_table.parser_class + end + + def warnings(verbose) + warnings = Warnings.new + + useless_symbols.each do |sym| + if sym.locate.empty? + if sym.terminal? + warnings.add_for_symbol(sym, Warning::UnusedTerminal.new(sym)) + else + warnings.add_for_symbol(sym, Warning::UnusedNonterminal.new(sym)) + end + elsif !sym.reachable.include?(@start) && sym.reachable.include?(sym) + if sym.reachable.one? + warnings.add_for_symbol(sym, Warning.new(:useless_nonterminal, 'Useless ' \ + "nonterminal #{sym} only appears on the right side of its " \ + 'own rules.')) + else + warnings.add_for_symbol(sym, Warning::UnreachableNonterminal.new(sym)) + end + elsif !productive_symbols.include?(sym) + warnings.add_for_symbol(sym, Warning::InfiniteLoop.new(sym)) end end - states.state_transition_table.parser_class - end - def write_log(path) - File.open(path, 'w') {|f| - LogFileGenerator.new(states()).output f - } + select { |r| r.explicit_precedence && !r.explicit_precedence_used? }.each do |rule| + warnings.add_for_rule(rule, Warning::UselessPrecedence.new(rule)) + end + + states.warnings(warnings, verbose) end - # # Grammar Definition Interface - # def add(rule) - raise ArgumentError, "rule added after the Grammar closed" if @closed + raise ArgumentError, "rule added after Grammar closed" if @closed @rules.push rule end @@ -170,7 +156,7 @@ def added?(sym) end def start_symbol=(s) - raise CompileError, "start symbol set twice'" if @start + raise CompileError, "start symbol set twice" if @start @start = s end @@ -191,435 +177,218 @@ def end_precedence_declaration(reverse) end end - # - # Dynamic Generation Interface - # - - def Grammar.define(&block) - env = DefinitionEnv.new - env.instance_eval(&block) - env.grammar - end - - class DefinitionEnv - def initialize - @grammar = Grammar.new - @seqs = Hash.new(0) - @delayed = [] - end - - def grammar - flush_delayed - @grammar.each do |rule| - if rule.specified_prec - rule.specified_prec = @grammar.intern(rule.specified_prec) - end - end - @grammar.init - @grammar - end - - def precedence_table(&block) - env = PrecedenceDefinitionEnv.new(@grammar) - env.instance_eval(&block) - @grammar.end_precedence_declaration env.reverse - end - - def method_missing(mid, *args, &block) - unless mid.to_s[-1,1] == '=' - super # raises NoMethodError - end - target = @grammar.intern(mid.to_s.chop.intern) - unless args.size == 1 - raise ArgumentError, "too many arguments for #{mid} (#{args.size} for 1)" - end - _add target, args.first - end - - def _add(target, x) - case x - when Sym - @delayed.each do |rule| - rule.replace x, target if rule.target == x - end - @grammar.symboltable.delete x - else - x.each_rule do |r| - r.target = target - @grammar.add r - end - end - flush_delayed - end - - def _delayed_add(rule) - @delayed.push rule - end - - def _added?(sym) - @grammar.added?(sym) or @delayed.detect {|r| r.target == sym } - end - - def flush_delayed - return if @delayed.empty? - @delayed.each do |rule| - @grammar.add rule - end - @delayed.clear - end - - def seq(*list, &block) - Rule.new(nil, list.map {|x| _intern(x) }, UserAction.proc(block)) - end - - def null(&block) - seq(&block) - end - - def action(&block) - id = "@#{@seqs["action"] += 1}".intern - _delayed_add Rule.new(@grammar.intern(id), [], UserAction.proc(block)) - id - end - - alias _ action - - def option(sym, default = nil, &block) - _defmetasyntax("option", _intern(sym), block) {|target| - seq() { default } | seq(sym) - } - end - - def many(sym, &block) - _defmetasyntax("many", _intern(sym), block) {|target| - seq() { [] }\ - | seq(target, sym) {|list, x| list.push x; list } - } - end - - def many1(sym, &block) - _defmetasyntax("many1", _intern(sym), block) {|target| - seq(sym) {|x| [x] }\ - | seq(target, sym) {|list, x| list.push x; list } - } - end - - def separated_by(sep, sym, &block) - option(separated_by1(sep, sym), [], &block) - end - - def separated_by1(sep, sym, &block) - _defmetasyntax("separated_by1", _intern(sym), block) {|target| - seq(sym) {|x| [x] }\ - | seq(target, sep, sym) {|list, _, x| list.push x; list } - } - end - - def _intern(x) - case x - when Symbol, String - @grammar.intern(x) - when Racc::Sym - x - else - raise TypeError, "wrong type #{x.class} (expected Symbol/String/Racc::Sym)" - end - end + # Computation - private + def finished! + return if @closed + @closed = true - def _defmetasyntax(type, id, action, &block) - if action - idbase = "#{type}@#{id}-#{@seqs[type] += 1}" - target = _wrap(idbase, "#{idbase}-core", action) - _regist("#{idbase}-core", &block) - else - target = _regist("#{type}@#{id}", &block) - end - @grammar.intern(target) - end + # if 'start' nonterminal was not explicitly set, just take the first one + @start ||= map(&:target).detect { |sym| !sym.generated? } + fail CompileError, 'no rules in input' if @rules.empty? + add_start_rule - def _regist(target_name) - target = target_name.intern - unless _added?(@grammar.intern(target)) - yield(target).each_rule do |rule| - rule.target = @grammar.intern(target) - _delayed_add rule - end - end - target + @rules.freeze + @symbols.each do |sym| + sym.heads.freeze + sym.locate.freeze end + @cache.freeze - def _wrap(target_name, sym, block) - target = target_name.intern - _delayed_add Rule.new(@grammar.intern(target), - [@grammar.intern(sym.intern)], - UserAction.proc(block)) - target - end + fix_ident + check_terminals + check_rules end - class PrecedenceDefinitionEnv - def initialize(g) - @grammar = g - @prechigh_seen = false - @preclow_seen = false - @reverse = false - end - - attr_reader :reverse - - def higher - if @prechigh_seen - raise CompileError, "prechigh used twice" - end - @prechigh_seen = true - end - - def lower - if @preclow_seen - raise CompileError, "preclow used twice" - end - if @prechigh_seen - @reverse = true - end - @preclow_seen = true - end - - def left(*syms) - @grammar.declare_precedence :Left, syms.map {|s| @grammar.intern(s) } - end - - def right(*syms) - @grammar.declare_precedence :Right, syms.map {|s| @grammar.intern(s) } - end - - def nonassoc(*syms) - @grammar.declare_precedence :Nonassoc, syms.map {|s| @grammar.intern(s)} + # A useless symbol can never be a part of any valid parse tree, and is not + # used for a = precedence declaration either + def useless_symbols + raise 'Grammar not yet closed' unless @closed + @useless_symbols ||= begin + @symbols.select do |sym| + !sym.generated? && + sym != @start && + (!sym.reachable.include?(@start) || !productive_symbols.include?(sym)) && + none? { |rule| rule.explicit_precedence == sym } + end.freeze end end + # A 'nonproductive' Sym, if taken as a starting point and then converted + # into a series of tokens by repeated substitution, would get stuck in an + # infinite loop and never reach a point where only terminals were left + # A 'productive' Sym, on the other hand, is not 'stuck' in an infinite loop # - # Computation - # - - def init - return if @closed - @closed = true - @start ||= @rules.map {|r| r.target }.detect {|sym| not sym.dummy? } - raise CompileError, 'no rule in input' if @rules.empty? - add_start_rule - @rules.freeze - fix_ident - compute_hash - compute_heads - determine_terminals - compute_nullable_0 - @symboltable.fix - compute_locate - @symboltable.each_nonterminal {|t| compute_expand t } - compute_nullable - compute_useless + # (Even if it can be converted to an empty sequence of tokens; in other + # words, if it is nullable, then it is considered 'productive') + def productive_symbols + raise 'Grammar not yet closed' unless @closed + @productive_symbols ||= begin + Sym.set_closure(@terminals + nullable_symbols.to_a).freeze + end + end + + # Can an empty sequence of tokens reduce to this nonterminal? + # (Can it be produced out of "nothing"?) + def nullable_symbols + raise 'Grammar not yet closed' unless @closed + @nullable_symbols ||= Sym.set_closure( + @symbols.select { |nt| nt.heads.any?(&:reduce?) }).freeze + end + + # What is the shortest series of terminals which can reduce to each NT? + def shortest_productions + raise 'Grammar not yet closed' unless @closed + @shortest_productions ||= begin + # nullable symbols can expand to... nothing + # terminals just map to themselves + result = Hash[nullable_symbols.map { |sym| [sym, []] } + + terminals.map { |t| [t, [t]] }] + + worklist = result.keys + while sym = worklist.shift + sym.locate.each do |ptr| + target = ptr.target + rules = target.heads.map(&:rule) + rules.reject! { |r| r.symbols.any? { |rs| !result.key?(rs) }} + next if rules.empty? + best = rules.map { |r| r.symbols.flat_map { |rs| result[rs] }}.min_by(&:size) + if !result.key?(target) || best.size < result[target].size + result[target] = best + worklist.push(target) + end + end + end + result.freeze + end end private def add_start_rule - r = Rule.new(@symboltable.dummy, - [@start, @symboltable.anchor, @symboltable.anchor], - UserAction.empty) - r.ident = 0 - r.hash = 0 - r.precedence = nil - @rules.unshift r + # We don't ever actually reduce to the dummy symbol; it is just there + # because every rule must have a target + # When building the parser states, we manually set the state where the + # first 'anchor' symbol is shifted to an 'accept state' -- one which + # successfully ends the parse + @rules.unshift(Rule.new(@dummy, [@start, @anchor, @anchor], UserAction.empty)) end - # Rule#ident - # LocationPointer#ident def fix_ident - @rules.each_with_index do |rule, idx| - rule.ident = idx - end - end - - # Rule#hash - def compute_hash - hash = 4 # size of dummy rule - @rules.each do |rule| - rule.hash = hash - hash += (rule.size + 1) - end - end + @rules.each_with_index(&:ident=) + @rules.flat_map(&:ptrs).each_with_index(&:ident=) - # Sym#heads - def compute_heads - @rules.each do |rule| - rule.target.heads.push rule.ptrs[0] - end + @terminals, @nonterminals = @symbols.partition(&:terminal?) + @symbols = @terminals + @nonterminals + # number Syms so terminals have the lower numbers + @symbols.each_with_index(&:ident=) end - # Sym#terminal? - def determine_terminals - @symboltable.each do |s| - s.term = s.heads.empty? - end - end - - # Sym#self_null? - def compute_nullable_0 - @symboltable.each do |s| - if s.terminal? - s.snull = false - else - s.snull = s.heads.any? {|loc| loc.reduce? } + def check_terminals + # token declarations in Racc are optional + # however, if you declare some tokens, you must declare them all + if @symbols.any?(&:declared_as_terminal?) + # any symbol which has no derivation rules is a terminal + undeclared = terminals.reject do |t| + t.declared_as_terminal? || t.string_symbol? || t.locate.empty? + end + undeclared -= [@anchor, @error] + unless undeclared.empty? + locations = undeclared.flat_map(&:locate).map(&:rule).uniq + raise CompileError, "terminal#{'s' unless undeclared.one?} " \ + "#{Racc.to_sentence(undeclared)} #{undeclared.one? ? 'was' : 'were'} " \ + "not declared in a 'token' block:\n" + + Source::SparseLines.render(locations.map(&:source)) end - end - end - # Sym#locate - def compute_locate - @rules.each do |rule| - t = nil - rule.ptrs.each do |ptr| - unless ptr.reduce? - tok = ptr.dereference - tok.locate.push ptr - t = tok if tok.terminal? - end + wrongly_declared = nonterminals.select(&:declared_as_terminal?) + unless wrongly_declared.empty? + bad_rules = wrongly_declared.flat_map(&:heads).map(&:rule) + raise CompileError, "token#{'s' unless wrongly_declared.one?} " \ + "#{Racc.to_sentence(wrongly_declared)} were declared in a 'token'" \ + " block, but #{wrongly_declared.one? ? 'it also has' : 'they also have'}" \ + " derivation rules:\n" + Source::SparseLines.render(bad_rules.map(&:source)) end - rule.precedence = t end - end - - # Sym#expand - def compute_expand(t) - puts "expand> #{t.to_s}" if @debug_symbol - t.expand = _compute_expand(t, ISet.new, []) - puts "expand< #{t.to_s}: #{t.expand.to_s}" if @debug_symbol - end - def _compute_expand(t, set, lock) - if tmp = t.expand - set.update tmp - return set + bad_strings = @symbols.select { |s| s.string_symbol? && s.nonterminal? } + unless bad_strings.empty? + bad_rules = bad_strings.flat_map(&:heads).map(&:rule) + raise CompileError, 'you may not create derivation rules for a ' \ + "string literal:\n" + Source::SparseLines.render(bad_rules.map(&:source)) end - tok = nil - set.update_a t.heads - t.heads.each do |ptr| - tok = ptr.dereference - if tok and tok.nonterminal? - unless lock[tok.ident] - lock[tok.ident] = true - _compute_expand tok, set, lock - end - end - end - set - end - - # Sym#nullable?, Rule#nullable? - def compute_nullable - @rules.each {|r| r.null = false } - @symboltable.each {|t| t.null = false } - r = @rules.dup - s = @symboltable.nonterminals - begin - rs = r.size - ss = s.size - check_rules_nullable r - check_symbols_nullable s - end until rs == r.size and ss == s.size - end - - def check_rules_nullable(rules) - rules.delete_if do |rule| - rule.null = true - rule.symbols.each do |t| - unless t.nullable? - rule.null = false - break - end - end - rule.nullable? + + bad_prec = @symbols.select { |s| s.assoc && s.nonterminal? } + unless bad_prec.empty? + bad_rules = bad_prec.flat_map(&:heads).map(&:rule) + raise CompileError, "token#{'s' unless bad_prec.one?} " \ + "#{Racc.to_sentence(bad_prec)} appeared in a prechigh/preclow " \ + "block, but #{bad_prec.one? ? 'it is not a' : 'they are not'} " \ + "terminal#{'s' unless bad_prec.one?}:\n" + + Source::SparseLines.render(bad_rules.map(&:source)) end - end - def check_symbols_nullable(symbols) - symbols.delete_if do |sym| - sym.heads.each do |ptr| - if ptr.rule.nullable? - sym.null = true - break - end - end - sym.nullable? + bad_prec = @rules.select do |rule| + rule.explicit_precedence && rule.explicit_precedence.nonterminal? + end + unless bad_prec.empty? + raise CompileError, "The following rule#{'s' unless bad_prec.one?} " \ + "use#{'s' if bad_prec.one?} nonterminals for explicit precedence, " \ + "which is not allowed:\n" + + Source::SparseLines.render(bad_prec.map(&:source)) end end - # Sym#useless?, Rule#useless? - # FIXME: what means "useless"? - def compute_useless - @symboltable.each_terminal {|sym| sym.useless = false } - @symboltable.each_nonterminal {|sym| sym.useless = true } - @rules.each {|rule| rule.useless = true } - r = @rules.dup - s = @symboltable.nonterminals - begin - rs = r.size - ss = s.size - check_rules_useless r - check_symbols_useless s - end until r.size == rs and s.size == ss - end - - def check_rules_useless(rules) - rules.delete_if do |rule| - rule.useless = false - rule.symbols.each do |sym| - if sym.useless? - rule.useless = true - break - end + def check_rules + @rules.group_by(&:target).each_value do |same_lhs| + same_lhs.group_by { |r| r.symbols.reject(&:hidden?) }.each_value do |same_rhs| + next unless same_rhs.size > 1 + raise CompileError, "The following rules are duplicates:\n" + + Source::SparseLines.render(same_rhs.map(&:source)) end - not rule.useless? end - end - def check_symbols_useless(s) - s.delete_if do |t| - t.heads.each do |ptr| - unless ptr.rule.useless? - t.useless = false - break - end - end - not t.useless? + unless @error.heads.empty? + raise CompileError, "You cannot create rules for the error symbol:\n" + + Source::SparseLines.render(@error.heads.map { |ptr| ptr.rule.source} ) end end - - end # class Grammar - + end class Rule - - def initialize(target, syms, act) - @target = target - @symbols = syms - @action = act + def initialize(target, syms, act, source = nil, precedence = nil) + @target = target # LHS of rule (may be `nil` if not yet known) + @symbols = syms # RHS of rule + @action = act # run this code when reducing @alternatives = [] + @source = source @ident = nil - @hash = nil - @ptrs = nil - @precedence = nil - @specified_prec = nil - @null = nil - @useless = nil + @precedence = precedence + @precedence_used = false # does explicit precedence actually resolve conflicts? + + @ptrs = (0..@symbols.size).map { |idx| LocationPointer.new(self, idx) } + @ptrs.freeze + + # reverse lookup from each Sym in RHS to location in rule where it appears + @symbols.each_with_index { |sym, idx| sym.locate << @ptrs[idx] } + + # reverse lookup from LHS of rule to starting location in rule + @target.heads << @ptrs[0] if @target end - attr_accessor :target + attr_accessor :ident + attr_reader :source attr_reader :symbols attr_reader :action + attr_reader :target + attr_reader :ptrs + + def target=(target) + raise 'target already set' if @target + @target = target + @target.heads << @ptrs[0] + end def |(x) @alternatives.push x.rule @@ -635,54 +404,50 @@ def each_rule(&block) @alternatives.each(&block) end - attr_accessor :ident - - attr_reader :hash - attr_reader :ptrs - - def hash=(n) - @hash = n - ptrs = [] - @symbols.each_with_index do |sym, idx| - ptrs.push LocationPointer.new(self, idx, sym) - end - ptrs.push LocationPointer.new(self, @symbols.size, nil) - @ptrs = ptrs + def precedence + @precedence || @symbols.select(&:terminal?).last end - def precedence - @specified_prec || @precedence + def explicit_precedence + @precedence end - def precedence=(sym) - @precedence ||= sym + def explicit_precedence_used! + @precedence_used = true end - def prec(sym, &block) - @specified_prec = sym - if block - unless @action.empty? - raise CompileError, 'both of rule action block and prec block given' - end - @action = UserAction.proc(block) - end - self + def explicit_precedence_used? + @precedence_used end - attr_accessor :specified_prec + # higher-priority rules which prevent this one from reducing + # (keys are lookahead tokens at point where this rule is overridden) + def overridden_by + @overridden_by ||= Hash.new { |h,k| h[k] = Set.new } + end - def nullable?() @null end - def null=(n) @null = n end + def inspect + "#" + end - def useless?() @useless end - def useless=(u) @useless = u end + def to_s + if @source + @source.spifferific + else + display + end + end - def inspect - "#" + def display + rule = "#{@target} : #{@symbols.reject(&:hidden?).map(&:to_s).join(' ')}" + if @precedence + rule << ' ' << Color.explicit_prec('=' << @precedence.display_name) + end + rule end - def ==(other) - other.kind_of?(Rule) and @ident == other.ident + def each(&block) + @symbols.each(&block) end def [](idx) @@ -693,38 +458,26 @@ def size @symbols.size end - def empty? - @symbols.empty? - end - - def to_s - "#" - end - + # is this the 'end' rule which is applied last in a successful parse? def accept? - if tok = @symbols[-1] - tok.anchor? - else - false - end - end - - def each(&block) - @symbols.each(&block) + @symbols.last && @symbols.last.anchor? end - def replace(src, dest) - @target = dest - @symbols = @symbols.map {|s| s == src ? dest : s } + # sometimes a Rule is instantiated before the target is actually known + # it may be given a "placeholder" target first, which is later replaced + # with the real one + def replace(placeholder, actual) + raise 'wrong placeholder' if placeholder != @target + @target.heads.delete(ptrs[0]) if @target + @target = actual + @target.heads << @ptrs[0] + @symbols.map! { |s| s == placeholder ? actual : s } end - - end # class Rule - + end class UserAction - - def UserAction.source_text(src) - new(src, nil) + def UserAction.source_text(src, lineno) + new(src, nil).tap { |act| act.lineno = lineno } end def UserAction.proc(pr = nil, &block) @@ -747,98 +500,89 @@ def initialize(src, proc) attr_reader :source attr_reader :proc + attr_accessor :lineno def source? not @proc end - def proc? - not @source - end - def empty? not @proc and not @source end - def name + def to_s "{action type=#{@source || @proc || 'nil'}}" end - alias inspect name - + alias inspect to_s end - - class OrMark - def initialize(lineno) - @lineno = lineno - end - - def name + class OrMark < Struct.new(:lineno) + def to_s '|' end - - alias inspect name - - attr_reader :lineno end - - class Prec - def initialize(symbol, lineno) - @symbol = symbol - @lineno = lineno + class Prec < Struct.new(:symbol, :range) + def to_s + Color.explicit_prec(range.text) end - def name - "=#{@symbol}" + def lineno + range.lineno end - - alias inspect name - - attr_reader :symbol - attr_reader :lineno end - - # - # A set of rule and position in it's RHS. - # Note that the number of pointers is more than rule's RHS array, - # because pointer points right edge of the final symbol when reducing. + # A combination of a rule and a position in its RHS + # Note that the number of pointers is more than the rule's RHS array, + # because it points to the right edge of the final symbol when reducing # class LocationPointer - - def initialize(rule, i, sym) - @rule = rule - @index = i - @symbol = sym - @ident = @rule.hash + i - @reduce = sym.nil? + def initialize(rule, i) + @rule = rule + @index = i + @ident = nil # canonical ordering for all LocationPointers end attr_reader :rule attr_reader :index - attr_reader :symbol + attr_accessor :ident - alias dereference symbol + # Sym which immediately follows this position in RHS + # or nil if it points to the end of RHS + def symbol + @rule.symbols[@index] + end - attr_reader :ident - alias hash ident - attr_reader :reduce - alias reduce? reduce + def target + @rule.target + end - def to_s - sprintf('(%d,%d %s)', - @rule.ident, @index, (reduce?() ? '#' : @symbol.to_s)) + def preceding + @rule.symbols[0...@index] end - alias inspect to_s + def following + @rule.symbols[@index..-1] + end - def eql?(ot) - @hash == ot.hash + def to_s + result = String.new "#{@rule.target} : " + if @index > 0 + result << "#{preceding.reject(&:hidden?).map(&:to_s).join(' ')} ." + else + result << '.' + end + unless reduce? + result << " #{following.reject(&:hidden?).map(&:to_s).join(' ')}" + end + if sym = @rule.explicit_precedence + result << ' ' << Color.explicit_prec('=' << sym.display_name) + end + result end - alias == eql? + alias inspect to_s def head? @index == 0 @@ -848,227 +592,120 @@ def next @rule.ptrs[@index + 1] or ptr_bug! end - alias increment next - - def before(len) - @rule.ptrs[@index - len] or ptr_bug! + def reduce? + symbol.nil? end private - - def ptr_bug! - raise "racc: fatal: pointer not exist: self: #{to_s}" - end - - end # class LocationPointer - - - class SymbolTable - - include Enumerable - - def initialize - @symbols = [] # :: [Racc::Sym] - @cache = {} # :: {(String|Symbol) => Racc::Sym} - @dummy = intern(:$start, true) - @anchor = intern(false, true) # Symbol ID = 0 - @error = intern(:error, false) # Symbol ID = 1 - end - - attr_reader :dummy - attr_reader :anchor - attr_reader :error - - def [](id) - @symbols[id] - end - - def intern(val, dummy = false) - @cache[val] ||= - begin - sym = Sym.new(val, dummy) - @symbols.push sym - sym - end - end - attr_reader :symbols - alias to_a symbols - - def delete(sym) - @symbols.delete sym - @cache.delete sym.value - end - - attr_reader :nt_base - - def nt_max - @symbols.size - end - - def each(&block) - @symbols.each(&block) - end - - def terminals(&block) - @symbols[0, @nt_base] - end - - def each_terminal(&block) - @terms.each(&block) - end - - def nonterminals - @symbols[@nt_base, @symbols.size - @nt_base] - end - - def each_nonterminal(&block) - @nterms.each(&block) - end - - def fix - terms, nterms = @symbols.partition {|s| s.terminal? } - @symbols = terms + nterms - @terms = terms - @nterms = nterms - @nt_base = terms.size - fix_ident - check_terminals - end - - private - - def fix_ident - @symbols.each_with_index do |t, i| - t.ident = i - end - end - - def check_terminals - return unless @symbols.any? {|s| s.should_terminal? } - @anchor.should_terminal - @error.should_terminal - each_terminal do |t| - t.should_terminal if t.string_symbol? - end - each do |s| - s.should_terminal if s.assoc - end - terminals().reject {|t| t.should_terminal? }.each do |t| - raise CompileError, "terminal #{t} not declared as terminal" - end - nonterminals().select {|n| n.should_terminal? }.each do |n| - raise CompileError, "symbol #{n} declared as terminal but is not terminal" - end + def ptr_bug! + raise "racc: fatal: pointer doesn't exist: self: #{to_s}" end + end - end # class SymbolTable - - - # Stands terminal and nonterminal symbols. + # A terminal or nonterminal symbol class Sym + def initialize(value, grammar, generated) + @ident = nil + @value = value + @genned = generated + @grammar = grammar - def initialize(value, dummyp) - @ident = nil - @value = value - @dummyp = dummyp - - @term = nil - @nterm = nil - @should_terminal = false + @declared_terminal = false @precedence = nil + case value when Symbol - @to_s = value.to_s + @display_name = value.to_s @serialized = value.inspect @string = false when String - @to_s = value.inspect - @serialized = value.dump + @display_name = @serialized = value.inspect @string = true when false - @to_s = '$end' + @display_name = '$end' @serialized = 'false' @string = false - when ErrorSymbolValue - @to_s = 'error' - @serialized = 'Object.new' - @string = false else - raise ArgumentError, "unknown symbol value: #{value.class}" + raise ArgumentError, "illegal symbol value: #{value.class}" end - @heads = [] - @locate = [] - @snull = nil - @null = nil - @expand = nil - @useless = nil - end - - class << self - def once_writer(nm) - nm = nm.id2name - module_eval(<<-EOS) - def #{nm}=(v) - raise 'racc: fatal: @#{nm} != nil' unless @#{nm}.nil? - @#{nm} = v - end - EOS - end + @heads = [] # RHS of rules which can reduce to this Sym + @locate = [] # all locations where this Sym appears on RHS of a rule end - once_writer :ident - attr_reader :ident - + attr_reader :value + attr_accessor :ident alias hash ident - attr_reader :value + attr_accessor :display_name + attr_accessor :precedence + attr_accessor :assoc - def dummy? - @dummyp - end + # some tokens are written one way in the grammar, but the actual value + # expected from the lexer is different + # you can set this up using a 'convert' block + attr_accessor :serialized - def terminal? - @term - end + attr_reader :heads + attr_reader :locate - def nonterminal? - @nterm + # Find a set of Syms with a common property + # The property extends to any Sym, which has a derivation rule whose RHS + # consists entirely of Syms with the property + def self.set_closure(seed) + Racc.set_closure(seed) do |sym, set| + rules = sym.locate.map(&:rule) + rules.select { |r| r.symbols.all? { |s| set.include?(s) }}.map(&:target) + end end - def term=(t) - raise 'racc: fatal: term= called twice' unless @term.nil? - @term = t - @nterm = !t + def generated? + @genned end - def should_terminal - @should_terminal = true + # Don't show in diagnostic messages... EXCEPT very technical diagnostics + # which show the internal parser states + def hidden? + @genned && @value != :$start && @value != false && @value != :error end - def should_terminal? - @should_terminal + def terminal? + heads.empty? end - def string_symbol? - @string + def nonterminal? + !heads.empty? end - def serialize - @serialized + def declared_as_terminal! + @declared_terminal = true end - attr_writer :serialized + def declared_as_terminal? + @declared_terminal + end - attr_accessor :precedence - attr_accessor :assoc + # is this a terminal which is written as a string literal in the grammar? + # (if so, it shouldn't appear on the LHS of any rule) + def string_symbol? + @string + end def to_s - @to_s.dup + return @display_name.dup unless Color.enabled? + if string_symbol? + Color.string(@display_name) + elsif terminal? + Color.terminal(@display_name) + else + Color.nonterminal(@display_name) + end end - alias inspect to_s + def inspect + "" + end def |(x) rule() | x.rule @@ -1078,38 +715,44 @@ def rule Rule.new(nil, [self], UserAction.empty) end - # - # cache - # - - attr_reader :heads - attr_reader :locate - - def self_null? - @snull - end - - once_writer :snull - def nullable? - @null + @nullable ||= @grammar.nullable_symbols.include?(self) end - def null=(n) - @null = n + def shortest_production + @shortest_prod ||= @grammar.shortest_productions[self] end - attr_reader :expand - once_writer :expand - - def useless? - @useless + # What NTs can be reached from this symbol, by traversing from the RHS of + # a rule where the symbol appears, to the target of the rule, then to the + # RHS of its rules, and so on? + def reachable + @reachable ||= Racc.set_closure(@locate.map(&:target)) do |sym| + sym.locate.map(&:target) + end.freeze end - def useless=(f) - @useless = f + # If an instance of this NT comes next, then what rules could we be + # starting? + def expand + @expand ||= Racc.set_closure(@heads.dup) do |ptr| + if (sym = ptr.symbol) && sym.nonterminal? + sym.heads + end + end.freeze end - end # class Sym - -end # module Racc + # What terminals/NT could appear first in a series of terminals/NTs which + # reduce to this symbol? + def first_set + @first_set ||= Racc.set_closure([self]) do |sym| + sym.heads.each_with_object([]) do |ptr, next_syms| + while !ptr.reduce? + next_syms << ptr.symbol + ptr.symbol.nullable? ? ptr = ptr.next : break + end + end + end.freeze + end + end +end diff --git a/lib/racc/grammar_file_parser.rb b/lib/racc/grammar_file_parser.rb new file mode 100644 index 00000000..b0075d69 --- /dev/null +++ b/lib/racc/grammar_file_parser.rb @@ -0,0 +1,278 @@ +# Copyright (c) 1999-2006 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". + +require 'racc' +require 'racc/grammar' +require 'racc/grammar_file_scanner' +require 'racc/parser_file_generator' +require 'racc/source' +require 'racc/dsl' + +module Racc + + grammar = DSL.define_grammar do + g = self + + g.class = seq(:CLASS, :cname, many(:param), option(:rules), option(:END)) + + g.cname = seq(:rubyconst) { |name| + @result.params.classname = name + } \ + | seq(:rubyconst, "<", :rubyconst) { |c, _, s| + @result.params.classname = c + @result.params.superclass = s + } + + g.rubyconst = separated_by1(:colon2, :SYMBOL) { |syms| + syms.map(&:first).map(&:to_s).join('::') + } + + g.colon2 = seq(':', ':') + + g.param = seq(:CONV, many1(:convdef), :END) \ + | seq(:PRECHIGH, many1(:precdef), :PRECLOW) { |*| + @grammar.end_precedence_declaration(true) + } \ + | seq(:PRECLOW, many1(:precdef), :PRECHIGH) { |*| + @grammar.end_precedence_declaration(false) + } \ + | seq(:START, :symbol) { |_, (sym)| + @grammar.start_symbol = sym + } \ + | seq(:TOKEN, :symbols) { |_, syms| + syms.each(&:declared_as_terminal!) + } \ + | seq(:OPTION, :options) { |_, syms| + # TODO: pull setting of options into a separate methods + syms.each do |opt| + case opt + when 'result_var' + @result.params.result_var = true + when 'no_result_var' + @result.params.result_var = false + else + raise CompileError, "unknown option: #{opt}" + end + end + } \ + | seq(:EXPECT, :DIGIT) { |_, (num)| + @grammar.n_expected_srconflicts = num + } + + g.convdef = seq(:symbol, :STRING) { |(sym), (code)| + sym.serialized = code + } + + g.precdef = seq(:LEFT, :symbols) { |_, syms| + @grammar.declare_precedence :Left, syms + } \ + | seq(:RIGHT, :symbols) { |_, syms| + @grammar.declare_precedence :Right, syms + } \ + | seq(:NONASSOC, :symbols) { |_, syms| + @grammar.declare_precedence :Nonassoc, syms + } + + g.symbols = seq(:symbol) { |(sym)| [sym] } \ + | seq(:symbols, :symbol) { |list, (sym)| list << sym } \ + | seq(:symbols, "|") + + g.symbol = seq(:SYMBOL) { |(sym, range)| [@grammar.intern(sym, false), range] } \ + | seq(:STRING) { |(str, range)| [@grammar.intern(str, false), range] } + + g.options = many(:SYMBOL) { |syms| syms.map(&:first).map(&:to_s) } + + g.rules = seq(:RULE, option(:rules_core) { |list| add_rule_block(list) }) + + # a set of grammar rules with the same LHS, like: + # nonterminal: token1 token2 | token3 token4; + # the terminating ; is optional + g.rules_core = seq(:symbol) { |sym| [sym] } \ + | seq(:rules_core, :rule_item) { |list, i| list << i } \ + | seq(:rules_core, ';') { |list, _| + add_rule_block(list) + list.clear + } \ + | seq(:rules_core, ':') { |list, (_, colon_range)| + # terminating ; may have been missing, in which case the + # previous token was actually a new LHS + # if it wasn't missing, we will just call add_rule_block + # with an empty list, which won't do anything + next_target = list.pop + add_rule_block(list) + [next_target, [':', colon_range]] + } + + g.rule_item = seq(:symbol) \ + | seq("|") { |(_, range)| + [OrMark.new(range.lineno), range] + } \ + | seq("=", :symbol) { |(_, range1), (sym, range2)| + range = Source::Range.new(@file, range1.from, range2.to) + [Prec.new(sym, range), range] + } \ + | seq(:ACTION) { |(range)| + [UserAction.source_text(range, range.lineno), range] + } + end + + GrammarFileParser = grammar.parser_class + + if grammar.sr_conflicts.any? + raise 'Racc boot script fatal: S/R conflict in build' + end + if grammar.rr_conflicts.any? + raise 'Racc boot script fatal: R/R conflict in build' + end + + class GrammarFileParser # reopen + class Result + def initialize(grammar, file, encoding = nil) + @grammar = grammar + @params = ParserFileGenerator::Params.new + @params.file = file + @params.encoding = encoding + end + + attr_reader :grammar, :params + end + + def GrammarFileParser.parse_file(filename) + new.parse(File.read(filename), filename) + end + + def parse(src, filename = '-') + @file = Source::Buffer.new(filename, src) + @scanner = GrammarFileScanner.new(@file) + @grammar = Grammar.new + encoding = src[/\A\s*#\s*encoding:\s*(\S+)/, 1] + @result = Result.new(@grammar, @file, encoding) + @embedded_action_seq = 0 + + yyparse @scanner, :yylex + parse_user_code + + @grammar.finished! + @result + end + + private + + def on_error(_tok, val, _values) + fail(CompileError, "#{@scanner.lineno}: unexpected token #{val[0].inspect}") + end + + def add_rule_block(list) + return if list.empty? + target, target_range = *list.shift + target_range.highlights << Source::Highlight.new(target, 0, + target_range.to - target_range.from) + + if target.is_a?(OrMark) || target.is_a?(UserAction) || target.is_a?(Prec) + fail(CompileError, "#{target.lineno}: unexpected symbol #{target.name}") + end + + if list.empty? # only derivation rule is null + add_rule(target, [], target_range) + return + end + + # record highlights which will be used when printing out rules + block_end = list.last[1].to + block_end += 1 if list.last[0].is_a?(UserAction) # show terminating } + block_range = Source::Range.new(@file, target_range.from, block_end) + highlights = list + .select { |obj, r| obj.is_a?(Sym) || obj.is_a?(Prec) } + .map { |obj, r| Source::Highlight.new(obj, + r.from - block_range.from, + r.to - block_range.from) } + block_range.highlights = highlights.unshift(target_range.highlights[0]) + + groups = split_array(list) { |obj, r| obj.is_a?(OrMark) } + groups.each do |rule_items| + sprec, rule_items = rule_items.partition { |obj, r| obj.is_a?(Prec) } + items, ranges = *rule_items.transpose + + if items + items.shift # drop OrMark or ':' + ranges.shift unless ranges.one? + end + + if ranges + range = block_range.slice(ranges.map(&:from).min - block_range.from, + ranges.map(&:to).max - block_range.from) + range = Source::SparseLines.new(block_range, [target_range.lines, range.lines]) + end + + if sprec.empty? + add_rule(target, items || [], range) + elsif sprec.one? + add_rule(target, items || [], range, sprec[0][0].symbol) + else + fail(CompileError, "'=' used twice in one rule") + end + end + end + + def split_array(array) + chunk, index = [], 0 + results = [chunk] + while index < array.size + obj = array[index] + if yield obj + chunk = [obj] + results << chunk + else + chunk << obj + end + index += 1 + end + results + end + + def add_rule(target, list, range, prec = nil) + if list.last.kind_of?(UserAction) + act = list.pop + else + act = UserAction.empty + end + list.map! { |s| s.kind_of?(UserAction) ? embedded_action(s, target) : s } + @grammar.add(Rule.new(target, list, act, range, prec)) + end + + def embedded_action(act, target) + sym = @grammar.intern("@action#{@embedded_action_seq += 1}".to_sym, true) + @grammar.add(Rule.new(sym, [], act)) + sym + end + + # User Code Block + + def parse_user_code + epilogue = @scanner.epilogue + return unless epilogue.text + epilogue.text.scan(/^----([^\n\r]*)(?:\n|\r\n|\r)(.*?)(?=^----|\Z)/m) do + label = canonical_label($~[1]) + range = epilogue.slice($~.begin(2), $~.end(2)) + add_user_code(label, range) + end + end + + USER_CODE_LABELS = %w(header inner footer) + + def canonical_label(src) + label = src.to_s.strip.downcase.slice(/\w+/) + unless USER_CODE_LABELS.include?(label) + raise CompileError, "unknown user code type: #{label.inspect}" + end + label + end + + def add_user_code(label, src) + @result.params.send(label.to_sym).push(src) + end + end +end diff --git a/lib/racc/grammar_file_scanner.rl b/lib/racc/grammar_file_scanner.rl new file mode 100644 index 00000000..607b125f --- /dev/null +++ b/lib/racc/grammar_file_scanner.rl @@ -0,0 +1,228 @@ +%%machine lex; + +require 'ripper' +require 'racc/exception' +require 'racc/source' + +class Racc::GrammarFileScanner + ReservedWords = { + 'right' => :RIGHT, + 'left' => :LEFT, + 'nonassoc' => :NONASSOC, + 'preclow' => :PRECLOW, + 'prechigh' => :PRECHIGH, + 'token' => :TOKEN, + 'convert' => :CONV, + 'options' => :OPTION, + 'start' => :START, + 'expect' => :EXPECT, + 'class' => :CLASS, + 'rule' => :RULE, + 'end' => :END + } + + Delimiters = { + '{' => '}', + '<' => '>', + '[' => ']', + '(' => ')' + } + + attr_accessor :file + attr_accessor :lineno + attr_accessor :epilogue + + def initialize(file) + @file = file + @source = file.text.force_encoding(Encoding::ASCII_8BIT) + @eof = @source.length + @lineno = 1 + @linehead = true # are we at the beginning of a line? + @in_block = false # are we in a 'rule' or 'convert' block? + @epilogue = range(@eof, @eof) # empty by default + + # To make the parser generator output exactly match the legacy generator, + # collapse excess trailing newlines into just one + @source.sub!(/\n+\Z/, "\n") + + # Used by Ragel-generated code: + @data = @source.bytes.to_a + + %%write data; + end + + def yylex(&block) + %%write init; + eof = @eof + %%write exec; + yield nil + end + + def tok_src + @source[@ts...@te] + end + + def range(from, to) + Racc::Source::Range.new(@file, from, to) + end + + def token(type = nil, value = nil) + src_text = tok_src + next_line = @lineno + src_text.scan(/\n|\r\n|\r/).size + type ||= src_text + value ||= block_given? ? yield(src_text) : src_text + result = [type, [value, range(@ts, @te)]] + @lineno = next_line + result + end + + def scan_error!(message) + raise "Error in grammar: #{message}" + end + + %%{ + access @; + getkey (@data[p]); + + c_nl = '\n' | '\r\n' | '\r'; + c_space = [ \t\r\f\v]; + c_space_nl = c_space | c_nl; + + c_eof = 0x04 | 0x1a | 0 | zlen; + c_eol = c_nl | c_eof; + c_any = any - c_eof; + + c_nl_zlen = c_nl | zlen; + c_line = any - c_nl_zlen; + + c_unicode = c_any - 0x00..0x7f; + c_upper = [A-Z]; + c_lower = [a-z_] | c_unicode; + c_alpha = c_lower | c_upper; + c_alnum = c_alpha | [0-9]; + + ws_space = (c_space | '\\' c_nl)+; + ws_rbcomment = '#' c_line*; + ws_ccomment = '/*' (^'*' | '*' ^'/')* '*/'; + + ws = ws_space | ws_rbcomment | ws_ccomment; + symbol = /[a-zA-Z_][a-zA-Z0-9_]*/; + integer = digit+; + string = ("'" (^("'" | '\\') | '\\' c_any)* "'") | + ('"' (^('"' | '\\') | '\\' c_any)* '"'); + + #========================== + # main grammar file scanner + #========================== + + main := |* + ws => { @lineno += @source[@ts...@te].scan(/\n|\r\n|\r/).size }; + c_nl => { @lineno += 1; @linehead = true }; + + # start of user code sections + '----' => { + yield token(:END, :end) if @in_block # pretend block was closed properly + @epilogue = range(@ts, @eof) # save the remainder of the file + fbreak; # return from yylex + }; + + symbol => { + symbol_src = tok_src + if @linehead # reserved words are only meaningful at line head + if @in_block # in rule/convert block, 'end' is the only special word + if symbol_src == 'end' + yield token(:END, :end) + @in_block = false + else + yield token(:SYMBOL, &:to_sym) + end + elsif symbol_src == 'rule' || symbol_src == 'convert' + yield token(ReservedWords[symbol_src]) { @in_block = symbol_src.to_sym } + else + yield token(ReservedWords.fetch(symbol_src, :SYMBOL), &:to_sym) + end + else + yield token(:SYMBOL, &:to_sym) + end + @linehead = false + }; + + integer => { + yield token(:DIGIT, &:to_i) + @linehead = false + }; + string => { + yield token(:STRING) { |str_content| eval(str_content) } + @linehead = false + }; + + '{' => { + # an action block can only occur inside rule block + if @in_block == :rule + rl = RubyLexer.new(@source, p + 1) + code = range(p + 1, rl.position) + yield token(:ACTION, code) + @lineno += code.text.scan(/\n|\r\n|\r/).size + fexec rl.position + 1; # jump past the concluding '}' + else + yield token + end + }; + + c_any => { + @linehead = false if tok_src == '|' + yield token + }; + *|; + }%% + + class RubyLexer < Ripper + def initialize(src, position) + super(src[position..-1]) + + @source = src + @start = @position = position + @nesting = 0 + + catch(:please_stop) { parse } + + while @position < @source.length && @source[@position] =~ /\s/ + @position += 1 + end + + if @source[@position] != '}' + raise Racc::ScanError, "scan error in action block (expected closing brace, found #{@source[@position].inspect})" + end + end + + attr_reader :position + + (SCANNER_EVENTS - [:embexpr_beg, :embexpr_end, :lbrace, :rbrace]).each do |event| + class_eval("def on_#{event}(tok); @position += tok.bytesize; end") + end + + # On Ruby 2.0+, Ripper emits an embexpr_end token for the concluding } + # On Ruby 1.9, it's an rbrace + def on_embexpr_beg(tok) + @nesting += 1 + @position += tok.size + end + + def on_lbrace(tok) + @nesting += 1 + @position += tok.size + end + + def on_embexpr_end(tok) + @nesting -= 1 + throw :please_stop if @nesting < 0 + @position += tok.size + end + + def on_rbrace(tok) + @nesting -= 1 + throw :please_stop if @nesting < 0 + @position += tok.size + end + end +end \ No newline at end of file diff --git a/lib/racc/grammarfileparser.rb b/lib/racc/grammarfileparser.rb deleted file mode 100644 index 5e1871de..00000000 --- a/lib/racc/grammarfileparser.rb +++ /dev/null @@ -1,559 +0,0 @@ -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# - -require 'racc' -require 'racc/compat' -require 'racc/grammar' -require 'racc/parserfilegenerator' -require 'racc/sourcetext' -require 'stringio' - -module Racc - - grammar = Grammar.define { - g = self - - g.class = seq(:CLASS, :cname, many(:param), :RULE, :rules, option(:END)) - - g.cname = seq(:rubyconst) {|name| - @result.params.classname = name - }\ - | seq(:rubyconst, "<", :rubyconst) {|c, _, s| - @result.params.classname = c - @result.params.superclass = s - } - - g.rubyconst = separated_by1(:colon2, :SYMBOL) {|syms| - syms.map {|s| s.to_s }.join('::') - } - - g.colon2 = seq(':', ':') - - g.param = seq(:CONV, many1(:convdef), :END) {|*| - #@grammar.end_convert_block # FIXME - }\ - | seq(:PRECHIGH, many1(:precdef), :PRECLOW) {|*| - @grammar.end_precedence_declaration true - }\ - | seq(:PRECLOW, many1(:precdef), :PRECHIGH) {|*| - @grammar.end_precedence_declaration false - }\ - | seq(:START, :symbol) {|_, sym| - @grammar.start_symbol = sym - }\ - | seq(:TOKEN, :symbols) {|_, syms| - syms.each do |s| - s.should_terminal - end - }\ - | seq(:OPTION, :options) {|_, syms| - syms.each do |opt| - case opt - when 'result_var' - @result.params.result_var = true - when 'no_result_var' - @result.params.result_var = false - when 'omit_action_call' - @result.params.omit_action_call = true - when 'no_omit_action_call' - @result.params.omit_action_call = false - else - raise CompileError, "unknown option: #{opt}" - end - end - }\ - | seq(:EXPECT, :DIGIT) {|_, num| - if @grammar.n_expected_srconflicts - raise CompileError, "`expect' seen twice" - end - @grammar.n_expected_srconflicts = num - } - - g.convdef = seq(:symbol, :STRING) {|sym, code| - sym.serialized = code - } - - g.precdef = seq(:LEFT, :symbols) {|_, syms| - @grammar.declare_precedence :Left, syms - }\ - | seq(:RIGHT, :symbols) {|_, syms| - @grammar.declare_precedence :Right, syms - }\ - | seq(:NONASSOC, :symbols) {|_, syms| - @grammar.declare_precedence :Nonassoc, syms - } - - g.symbols = seq(:symbol) {|sym| - [sym] - }\ - | seq(:symbols, :symbol) {|list, sym| - list.push sym - list - }\ - | seq(:symbols, "|") - - g.symbol = seq(:SYMBOL) {|sym| @grammar.intern(sym) }\ - | seq(:STRING) {|str| @grammar.intern(str) } - - g.options = many(:SYMBOL) {|syms| syms.map {|s| s.to_s } } - - g.rules = option(:rules_core) {|list| - add_rule_block list unless list.empty? - nil - } - - g.rules_core = seq(:symbol) {|sym| - [sym] - }\ - | seq(:rules_core, :rule_item) {|list, i| - list.push i - list - }\ - | seq(:rules_core, ';') {|list, *| - add_rule_block list unless list.empty? - list.clear - list - }\ - | seq(:rules_core, ':') {|list, *| - next_target = list.pop - add_rule_block list unless list.empty? - [next_target] - } - - g.rule_item = seq(:symbol)\ - | seq("|") {|*| - OrMark.new(@scanner.lineno) - }\ - | seq("=", :symbol) {|_, sym| - Prec.new(sym, @scanner.lineno) - }\ - | seq(:ACTION) {|src| - UserAction.source_text(src) - } - } - - GrammarFileParser = grammar.parser_class - - if grammar.states.srconflict_exist? - raise 'Racc boot script fatal: S/R conflict in build' - end - if grammar.states.rrconflict_exist? - raise 'Racc boot script fatal: R/R conflict in build' - end - - class GrammarFileParser # reopen - - class Result - def initialize(grammar) - @grammar = grammar - @params = ParserFileGenerator::Params.new - end - - attr_reader :grammar - attr_reader :params - end - - def GrammarFileParser.parse_file(filename) - parse(File.read(filename), filename, 1) - end - - def GrammarFileParser.parse(src, filename = '-', lineno = 1) - new().parse(src, filename, lineno) - end - - def initialize(debug_flags = DebugFlags.new) - @yydebug = debug_flags.parse - end - - def parse(src, filename = '-', lineno = 1) - @filename = filename - @lineno = lineno - @scanner = GrammarFileScanner.new(src, @filename) - @scanner.debug = @yydebug - @grammar = Grammar.new - @result = Result.new(@grammar) - @embedded_action_seq = 0 - yyparse @scanner, :yylex - parse_user_code - @result.grammar.init - @result - end - - private - - def next_token - @scanner.scan - end - - def on_error(tok, val, _values) - if val.respond_to?(:id2name) - v = val.id2name - elsif val.kind_of?(String) - v = val - else - v = val.inspect - end - raise CompileError, "#{location()}: unexpected token '#{v}'" - end - - def location - "#{@filename}:#{@lineno - 1 + @scanner.lineno}" - end - - def add_rule_block(list) - sprec = nil - target = list.shift - case target - when OrMark, UserAction, Prec - raise CompileError, "#{target.lineno}: unexpected symbol #{target.name}" - end - curr = [] - list.each do |i| - case i - when OrMark - add_rule target, curr, sprec - curr = [] - sprec = nil - when Prec - raise CompileError, "'=' used twice in one rule" if sprec - sprec = i.symbol - else - curr.push i - end - end - add_rule target, curr, sprec - end - - def add_rule(target, list, sprec) - if list.last.kind_of?(UserAction) - act = list.pop - else - act = UserAction.empty - end - list.map! {|s| s.kind_of?(UserAction) ? embedded_action(s) : s } - rule = Rule.new(target, list, act) - rule.specified_prec = sprec - @grammar.add rule - end - - def embedded_action(act) - sym = @grammar.intern("@#{@embedded_action_seq += 1}".intern, true) - @grammar.add Rule.new(sym, [], act) - sym - end - - # - # User Code Block - # - - def parse_user_code - line = @scanner.lineno - _, *blocks = *@scanner.epilogue.split(/^----/) - blocks.each do |block| - header, *body = block.lines.to_a - label0, pathes = *header.sub(/\A-+/, '').split('=', 2) - label = canonical_label(label0) - (pathes ? pathes.strip.split(' ') : []).each do |path| - add_user_code label, SourceText.new(File.read(path), path, 1) - end - add_user_code label, SourceText.new(body.join(''), @filename, line + 1) - line += (1 + body.size) - end - end - - USER_CODE_LABELS = { - 'header' => :header, - 'prepare' => :header, # obsolete - 'inner' => :inner, - 'footer' => :footer, - 'driver' => :footer # obsolete - } - - def canonical_label(src) - label = src.to_s.strip.downcase.slice(/\w+/) - unless USER_CODE_LABELS.key?(label) - raise CompileError, "unknown user code type: #{label.inspect}" - end - label - end - - def add_user_code(label, src) - @result.params.send(USER_CODE_LABELS[label]).push src - end - - end - - - class GrammarFileScanner - - def initialize(str, filename = '-') - @lines = str.split(/\n|\r\n|\r/) - @filename = filename - @lineno = -1 - @line_head = true - @in_rule_blk = false - @in_conv_blk = false - @in_block = nil - @epilogue = '' - @debug = false - next_line - end - - attr_reader :epilogue - - def lineno - @lineno + 1 - end - - attr_accessor :debug - - def yylex(&block) - unless @debug - yylex0(&block) - else - yylex0 do |sym, tok| - $stderr.printf "%7d %-10s %s\n", lineno(), sym.inspect, tok.inspect - yield [sym, tok] - end - end - end - - private - - def yylex0 - begin - until @line.empty? - @line.sub!(/\A\s+/, '') - if /\A\#/ =~ @line - break - elsif /\A\/\*/ =~ @line - skip_comment - elsif s = reads(/\A[a-zA-Z_]\w*/) - yield [atom_symbol(s), s.intern] - elsif s = reads(/\A\d+/) - yield [:DIGIT, s.to_i] - elsif ch = reads(/\A./) - case ch - when '"', "'" - yield [:STRING, eval(scan_quoted(ch))] - when '{' - lineno = lineno() - yield [:ACTION, SourceText.new(scan_action(), @filename, lineno)] - else - if ch == '|' - @line_head = false - end - yield [ch, ch] - end - else - end - end - end while next_line() - yield nil - end - - def next_line - @lineno += 1 - @line = @lines[@lineno] - if not @line or /\A----/ =~ @line - @epilogue = @lines.join("\n") - @lines.clear - @line = nil - if @in_block - @lineno -= 1 - scan_error! sprintf('unterminated %s', @in_block) - end - false - else - @line.sub!(/(?:\n|\r\n|\r)\z/, '') - @line_head = true - true - end - end - - ReservedWord = { - 'right' => :RIGHT, - 'left' => :LEFT, - 'nonassoc' => :NONASSOC, - 'preclow' => :PRECLOW, - 'prechigh' => :PRECHIGH, - 'token' => :TOKEN, - 'convert' => :CONV, - 'options' => :OPTION, - 'start' => :START, - 'expect' => :EXPECT, - 'class' => :CLASS, - 'rule' => :RULE, - 'end' => :END - } - - def atom_symbol(token) - if token == 'end' - symbol = :END - @in_conv_blk = false - @in_rule_blk = false - else - if @line_head and not @in_conv_blk and not @in_rule_blk - symbol = ReservedWord[token] || :SYMBOL - else - symbol = :SYMBOL - end - case symbol - when :RULE then @in_rule_blk = true - when :CONV then @in_conv_blk = true - end - end - @line_head = false - symbol - end - - def skip_comment - @in_block = 'comment' - until m = /\*\//.match(@line) - next_line - end - @line = m.post_match - @in_block = nil - end - - $raccs_print_type = false - - def scan_action - buf = '' - nest = 1 - pre = nil - @in_block = 'action' - begin - pre = nil - if s = reads(/\A\s+/) - # does not set 'pre' - buf << s - end - until @line.empty? - if s = reads(/\A[^'"`{}%#\/\$]+/) - buf << (pre = s) - next - end - case ch = read(1) - when '{' - nest += 1 - buf << (pre = ch) - when '}' - nest -= 1 - if nest == 0 - @in_block = nil - return buf - end - buf << (pre = ch) - when '#' # comment - buf << ch << @line - break - when "'", '"', '`' - buf << (pre = scan_quoted(ch)) - when '%' - if literal_head? pre, @line - # % string, regexp, array - buf << ch - case ch = read(1) - when /[qQx]/n - buf << ch << (pre = scan_quoted(read(1), '%string')) - when /wW/n - buf << ch << (pre = scan_quoted(read(1), '%array')) - when /s/n - buf << ch << (pre = scan_quoted(read(1), '%symbol')) - when /r/n - buf << ch << (pre = scan_quoted(read(1), '%regexp')) - when /[a-zA-Z0-9= ]/n # does not include "_" - scan_error! "unknown type of % literal '%#{ch}'" - else - buf << (pre = scan_quoted(ch, '%string')) - end - else - # operator - buf << '||op->' if $raccs_print_type - buf << (pre = ch) - end - when '/' - if literal_head? pre, @line - # regexp - buf << (pre = scan_quoted(ch, 'regexp')) - else - # operator - buf << '||op->' if $raccs_print_type - buf << (pre = ch) - end - when '$' # gvar - buf << ch << (pre = read(1)) - else - raise 'racc: fatal: must not happen' - end - end - buf << "\n" - end while next_line() - raise 'racc: fatal: scan finished before parser finished' - end - - def literal_head?(pre, post) - (!pre || /[a-zA-Z_0-9]/n !~ pre[-1,1]) && - !post.empty? && /\A[\s\=]/n !~ post - end - - def read(len) - s = @line[0, len] - @line = @line[len .. -1] - s - end - - def reads(re) - m = re.match(@line) or return nil - @line = m.post_match - m[0] - end - - def scan_quoted(left, tag = 'string') - buf = left.dup - buf = "||#{tag}->" + buf if $raccs_print_type - re = get_quoted_re(left) - sv, @in_block = @in_block, tag - begin - if s = reads(re) - buf << s - break - else - buf << @line - end - end while next_line() - @in_block = sv - buf << "<-#{tag}||" if $raccs_print_type - buf - end - - LEFT_TO_RIGHT = { - '(' => ')', - '{' => '}', - '[' => ']', - '<' => '>' - } - - CACHE = {} - - def get_quoted_re(left) - term = Regexp.quote(LEFT_TO_RIGHT[left] || left) - CACHE[left] ||= /\A[^#{term}\\]*(?:\\.[^\\#{term}]*)*#{term}/ - end - - def scan_error!(msg) - raise CompileError, "#{lineno()}: #{msg}" - end - - end - -end # module Racc diff --git a/lib/racc/info.rb b/lib/racc/info.rb index 22e49836..8fe4d32f 100644 --- a/lib/racc/info.rb +++ b/lib/racc/info.rb @@ -1,16 +1,11 @@ -# -# $Id$ -# # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". module Racc - VERSION = '1.4.13' - Version = VERSION - Copyright = 'Copyright (c) 1999-2006 Minero Aoki' + VERSION = "2.0.0.dev" + CODENAME = 'Mecha Oishii' + COPYRIGHT = 'Copyright (c) 1999-2006 Minero Aoki' end diff --git a/lib/racc/iset.rb b/lib/racc/iset.rb deleted file mode 100644 index de638608..00000000 --- a/lib/racc/iset.rb +++ /dev/null @@ -1,91 +0,0 @@ -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# - -module Racc - - # An "indexed" set. All items must respond to :ident. - class ISet - - def initialize(a = []) - @set = a - end - - attr_reader :set - - def add(i) - @set[i.ident] = i - end - - def [](key) - @set[key.ident] - end - - def []=(key, val) - @set[key.ident] = val - end - - alias include? [] - alias key? [] - - def update(other) - s = @set - o = other.set - o.each_index do |idx| - if t = o[idx] - s[idx] = t - end - end - end - - def update_a(a) - s = @set - a.each {|i| s[i.ident] = i } - end - - def delete(key) - i = @set[key.ident] - @set[key.ident] = nil - i - end - - def each(&block) - @set.compact.each(&block) - end - - def to_a - @set.compact - end - - def to_s - "[#{@set.compact.join(' ')}]" - end - - alias inspect to_s - - def size - @set.nitems - end - - def empty? - @set.nitems == 0 - end - - def clear - @set.clear - end - - def dup - ISet.new(@set.dup) - end - - end # class ISet - -end # module Racc diff --git a/lib/racc/logfilegenerator.rb b/lib/racc/logfilegenerator.rb deleted file mode 100644 index a7e96636..00000000 --- a/lib/racc/logfilegenerator.rb +++ /dev/null @@ -1,211 +0,0 @@ -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# - -module Racc - - class LogFileGenerator - - def initialize(states, debug_flags = DebugFlags.new) - @states = states - @grammar = states.grammar - @debug_flags = debug_flags - end - - def output(out) - output_conflict out; out.puts - output_useless out; out.puts - output_rule out; out.puts - output_token out; out.puts - output_state out - end - - # - # Warnings - # - - def output_conflict(out) - @states.each do |state| - if state.srconf - out.printf "state %d contains %d shift/reduce conflicts\n", - state.stateid, state.srconf.size - end - if state.rrconf - out.printf "state %d contains %d reduce/reduce conflicts\n", - state.stateid, state.rrconf.size - end - end - end - - def output_useless(out) - @grammar.each do |rl| - if rl.useless? - out.printf "rule %d (%s) never reduced\n", - rl.ident, rl.target.to_s - end - end - @grammar.each_nonterminal do |t| - if t.useless? - out.printf "useless nonterminal %s\n", t.to_s - end - end - end - - # - # States - # - - def output_state(out) - out << "--------- State ---------\n" - - showall = @debug_flags.la || @debug_flags.state - @states.each do |state| - out << "\nstate #{state.ident}\n\n" - - (showall ? state.closure : state.core).each do |ptr| - pointer_out(out, ptr) if ptr.rule.ident != 0 or showall - end - out << "\n" - - action_out out, state - end - end - - def pointer_out(out, ptr) - buf = sprintf("%4d) %s :", ptr.rule.ident, ptr.rule.target.to_s) - ptr.rule.symbols.each_with_index do |tok, idx| - buf << ' _' if idx == ptr.index - buf << ' ' << tok.to_s - end - buf << ' _' if ptr.reduce? - out.puts buf - end - - def action_out(f, state) - sr = state.srconf && state.srconf.dup - rr = state.rrconf && state.rrconf.dup - acts = state.action - keys = acts.keys - keys.sort! {|a,b| a.ident <=> b.ident } - - [ Shift, Reduce, Error, Accept ].each do |klass| - keys.delete_if do |tok| - act = acts[tok] - if act.kind_of?(klass) - outact f, tok, act - if sr and c = sr.delete(tok) - outsrconf f, c - end - if rr and c = rr.delete(tok) - outrrconf f, c - end - - true - else - false - end - end - end - sr.each {|tok, c| outsrconf f, c } if sr - rr.each {|tok, c| outrrconf f, c } if rr - - act = state.defact - if not act.kind_of?(Error) or @debug_flags.any? - outact f, '$default', act - end - - f.puts - state.goto_table.each do |t, st| - if t.nonterminal? - f.printf " %-12s go to state %d\n", t.to_s, st.ident - end - end - end - - def outact(f, t, act) - case act - when Shift - f.printf " %-12s shift, and go to state %d\n", - t.to_s, act.goto_id - when Reduce - f.printf " %-12s reduce using rule %d (%s)\n", - t.to_s, act.ruleid, act.rule.target.to_s - when Accept - f.printf " %-12s accept\n", t.to_s - when Error - f.printf " %-12s error\n", t.to_s - else - raise "racc: fatal: wrong act for outact: act=#{act}(#{act.class})" - end - end - - def outsrconf(f, confs) - confs.each do |c| - r = c.reduce - f.printf " %-12s [reduce using rule %d (%s)]\n", - c.shift.to_s, r.ident, r.target.to_s - end - end - - def outrrconf(f, confs) - confs.each do |c| - r = c.low_prec - f.printf " %-12s [reduce using rule %d (%s)]\n", - c.token.to_s, r.ident, r.target.to_s - end - end - - # - # Rules - # - - def output_rule(out) - out.print "-------- Grammar --------\n\n" - @grammar.each do |rl| - if @debug_flags.any? or rl.ident != 0 - out.printf "rule %d %s: %s\n", - rl.ident, rl.target.to_s, rl.symbols.join(' ') - end - end - end - - # - # Tokens - # - - def output_token(out) - out.print "------- Symbols -------\n\n" - - out.print "**Nonterminals, with rules where they appear\n\n" - @grammar.each_nonterminal do |t| - tmp = <rubypath] [--embedded=rubypath] # [-v] [--verbose] # [-Ofilename] [--log-file=filename] -# [-g] [--debug] +# [-t] [--debug] # [-E] [--embedded] -# [-l] [--no-line-convert] -# [-c] [--line-convert-all] -# [-a] [--no-omit-actions] # [-C] [--check-only] -# [-S] [--output-status] # [--version] [--copyright] [--help] grammarfile # # [+filename+] -# Racc grammar file. Any extention is permitted. +# Racc grammar file. Any extension is permitted. # [-o+outfile+, --output-file=+outfile+] # A filename for output. default is <+filename+>.tab.rb # [-O+filename+, --log-file=+filename+] @@ -53,21 +42,13 @@ class ParseError < StandardError; end # output executable file(mode 755). where +path+ is the Ruby interpreter. # [-v, --verbose] # verbose mode. create +filename+.output file, like yacc's y.output file. -# [-g, --debug] -# add debug code to parser class. To display debuggin information, -# use this '-g' option and set @yydebug true in parser class. +# [-t, --debug] +# add debug code to parser class. To display debugging information, +# use this '-t' option and set @yydebug to true in parser class. # [-E, --embedded] # Output parser which doesn't need runtime files (racc/parser.rb). # [-C, --check-only] -# Check syntax of racc grammer file and quit. -# [-S, --output-status] -# Print messages time to time while compiling. -# [-l, --no-line-convert] -# turns off line number converting. -# [-c, --line-convert-all] -# Convert line number of actions, inner, header and footer. -# [-a, --no-omit-actions] -# Call all actions, even if an action is empty. +# Check syntax of racc grammar file and quit. # [--version] # print Racc version and quit. # [--copyright] @@ -75,9 +56,9 @@ class ParseError < StandardError; end # [--help] # Print usage and quit. # -# == Generating Parser Using Racc +# == Generating a Parser Using Racc # -# To compile Racc grammar file, simply type: +# To compile a Racc grammar file, simply type: # # $ racc parse.y # @@ -85,13 +66,13 @@ class ParseError < StandardError; end # # == Writing A Racc Grammar File # -# If you want your own parser, you have to write a grammar file. +# To generate your own parser, you have to write a grammar file. # A grammar file contains the name of your parser class, grammar for the parser, -# user code, and anything else. +# and user code. # When writing a grammar file, yacc's knowledge is helpful. # If you have not used yacc before, Racc is not too difficult. # -# Here's an example Racc grammar file. +# Here's an example Racc grammar file: # # class Calcparser # rule @@ -118,13 +99,13 @@ class ParseError < StandardError; end # # Racc::Parser#do_parse is simple. # -# It's yyparse() of yacc, and Racc::Parser#next_token is yylex(). -# This method must returns an array like [TOKENSYMBOL, ITS_VALUE]. +# It's the `yyparse` of yacc, and Racc::Parser#next_token is `yylex`. +# This method must return an array like [TOKENSYMBOL, ITS_VALUE]. # EOF is [false, false]. -# (TOKENSYMBOL is a Ruby symbol (taken from String#intern) by default. -# If you want to change this, see the grammar reference. +# (TOKENSYMBOL is a Ruby Symbol by default. +# If you want to change this, see the grammar reference.) # -# Racc::Parser#yyparse is little complicated, but useful. +# Racc::Parser#yyparse is a little complicated, but useful. # It does not use Racc::Parser#next_token, instead it gets tokens from any iterator. # # For example, yyparse(obj, :scan) causes @@ -132,21 +113,14 @@ class ParseError < StandardError; end # # == Debugging # -# When debugging, "-v" or/and the "-g" option is helpful. +# When debugging, "-v" or/and the "-t" option is helpful. # # "-v" creates verbose log file (.output). -# "-g" creates a "Verbose Parser". -# Verbose Parser prints the internal status when parsing. +# "-t" creates a "Verbose Parser". +# A verbose parser prints the internal status when parsing. # But it's _not_ automatic. -# You must use -g option and set +@yydebug+ to +true+ in order to get output. -# -g option only creates the verbose parser. -# -# === Racc reported syntax error. -# -# Isn't there too many "end"? -# grammar of racc file is changed in v0.10. -# -# Racc does not use '%' mark, while yacc uses huge number of '%' marks.. +# You must use -t option and set +@yydebug+ to +true+ in order to get output. +# -t option only creates a verbose parser. # # === Racc reported "XXXX conflicts". # @@ -155,70 +129,58 @@ class ParseError < StandardError; end # # === Generated parsers does not work correctly # -# Try "racc -g xxxx.y". -# This command let racc generate "debugging parser". +# Try "racc -t xxxx.y". +# This command makes racc generate a "debugging parser". # Then set @yydebug=true in your parser. # It produces a working log of your parser. # # == Re-distributing Racc runtime # -# A parser, which is created by Racc, requires the Racc runtime module; +# A parser, which is created by Racc, requires the Racc runtime module: # racc/parser.rb. # -# Ruby 1.8.x comes with Racc runtime module, -# you need NOT distribute Racc runtime files. +# Ruby 1.8+ comes with the Racc runtime module, +# so you need NOT distribute Racc runtime files. # -# If you want to include the Racc runtime module with your parser. -# This can be done by using '-E' option: +# If you want to include the Racc runtime module with your parser, +# this can be done by using the '-E' option: # -# $ racc -E -omyparser.rb myparser.y +# $ racc -E -o myparser.rb myparser.y # -# This command creates myparser.rb which `includes' Racc runtime. -# Only you must do is to distribute your parser file (myparser.rb). +# This command creates a parser with the Racc runtime embedded right in the +# parser source file, so it can run even if racc/parser.rb is not present. # -# Note: parser.rb is LGPL, but your parser is not. +# Note: parser.rb is ruby license, but your parser is not. # Your own parser is completely yours. module Racc - - unless defined?(Racc_No_Extentions) - Racc_No_Extentions = false # :nodoc: - end + Racc_No_Extensions = ENV['PURERUBY'] # :nodoc: class Parser - - Racc_Runtime_Version = ::Racc::VERSION - Racc_Runtime_Revision = '$Id$' - - Racc_Runtime_Core_Version_R = ::Racc::VERSION - Racc_Runtime_Core_Revision_R = '$Id$'.split[1] begin if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby' require 'racc/cparse-jruby.jar' - com.headius.racc.Cparse.new.load(JRuby.runtime, false) + if JRuby::Util.respond_to?(:load_ext) # JRuby 9.2 + JRuby::Util.load_ext('com.headius.racc.Cparse') + else; require 'jruby' + com.headius.racc.Cparse.new.load(JRuby.runtime, false) + end else require 'racc/cparse' end - # Racc_Runtime_Core_Version_C = (defined in extention) - Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split[2] + unless new.respond_to?(:_racc_do_parse_c, true) raise LoadError, 'old cparse.so' end - if Racc_No_Extentions + if Racc_No_Extensions raise LoadError, 'selecting ruby version of racc runtime core' end Racc_Main_Parsing_Routine = :_racc_do_parse_c # :nodoc: Racc_YY_Parse_Method = :_racc_yyparse_c # :nodoc: - Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C # :nodoc: - Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_C # :nodoc: Racc_Runtime_Type = 'c' # :nodoc: rescue LoadError -puts $! -puts $!.backtrace Racc_Main_Parsing_Routine = :_racc_do_parse_rb Racc_YY_Parse_Method = :_racc_yyparse_rb - Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R - Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R Racc_Runtime_Type = 'ruby' end @@ -267,9 +229,11 @@ def _racc_init_sysvars # def next_token # @q.shift # end + class_eval %{ def do_parse - __send__(Racc_Main_Parsing_Routine, _racc_setup(), false) + #{Racc_Main_Parsing_Routine}(_racc_setup(), false) end + } # The method to fetch next token. # If you use #do_parse method, you must implement #next_token. @@ -316,7 +280,6 @@ def _racc_do_parse_rb(arg, in_debug) act = action_default[@racc_state[-1]] end while act = _racc_evalact(act, arg) - ; end end } @@ -327,9 +290,11 @@ def _racc_do_parse_rb(arg, in_debug) # # RECEIVER#METHOD_ID is a method to get next token. # It must 'yield' the token, which format is [TOKEN-SYMBOL, VALUE]. + class_eval %{ def yyparse(recv, mid) - __send__(Racc_YY_Parse_Method, recv, mid, _racc_setup(), false) + #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), true) end + } def _racc_yyparse_rb(recv, mid, arg, c_debug) action_table, action_check, action_default, action_pointer, @@ -341,7 +306,6 @@ def _racc_yyparse_rb(recv, mid, arg, c_debug) catch(:racc_end_parse) { until i = action_pointer[@racc_state[-1]] while act = _racc_evalact(action_default[@racc_state[-1]], arg) - ; end end recv.__send__(mid) do |tok, val| @@ -360,7 +324,6 @@ def _racc_yyparse_rb(recv, mid, arg, c_debug) act = action_default[@racc_state[-1]] end while act = _racc_evalact(act, arg) - ; end while !(i = action_pointer[@racc_state[-1]]) || @@ -373,7 +336,6 @@ def _racc_yyparse_rb(recv, mid, arg, c_debug) act = action_default[@racc_state[-1]] end while act = _racc_evalact(act, arg) - ; end end end @@ -389,14 +351,13 @@ def _racc_evalact(act, arg) _, _, _, _, _, _, _, shift_n, reduce_n, * = arg - nerr = 0 # tmp if act > 0 and act < shift_n # # shift # if @racc_error_status > 0 - @racc_error_status -= 1 unless @racc_t == 1 # error token + @racc_error_status -= 1 unless @racc_t <= 1 # error token or EOF end @racc_vstack.push @racc_val @racc_state.push act @@ -437,14 +398,30 @@ def _racc_evalact(act, arg) # # error # + + # Like yacc, Racc calls `on_error` when an error occurs, and then starts + # to attempt auto-recovery by discarding states on the stack until it + # gets to a state where the 'error' token is acceptable + # + # Often, this leads to another error, and another, until all the tokens + # in the erroneous portion of input have been shifted (and then + # discarded by the auto-recovery code) + # + # So to avoid an outpouring of error messages, @racc_error_status is + # used to suppress 3 calls to `on_error` after each error is detected + # Each successful shift decrements @racc_error_status, so after the + # erroneous portion of input is cleared, it quickly returns to zero, + # and then Racc is ready to report another error again + case @racc_error_status when 0 - unless arg[21] # user_yyerror - nerr += 1 - on_error @racc_t, @racc_val, @racc_vstack + unless arg[21] # user_yyerror + on_error(@racc_t, @racc_val, @racc_vstack) end when 3 if @racc_t == 0 # is $ + # We're at EOF, and another error occurred immediately after + # attempting auto-recovery throw :racc_end_parse, nil end @racc_read_next = true @@ -541,7 +518,7 @@ def on_error(t, val, vstack) end # Enter error recovering mode. - # This method does not call #on_error. + # This method does not call `on_error`. def yyerror throw :racc_jump, 1 end @@ -552,7 +529,15 @@ def yyaccept throw :racc_jump, 2 end - # Leave error recovering mode. + # Leave error recovery mode. + # + # When in error recovery mode, Racc suppresses 3 errors after each error + # which is reported (by calling `on_error`). + # To get out of error recovery mode, normally Racc must successfully shift + # 3 tokens. + # You can call this from `on_error`, or from an action block, to immediately + # get out of error recovery and stop suppressing the reporting of further + # errors. def yyerrok @racc_error_status = 0 end @@ -580,6 +565,7 @@ def racc_reduce(toks, sim, tstack, vstack) toks.each {|t| out.print ' ', racc_token2str(t) } end out.puts " --> #{racc_token2str(sim)}" + racc_print_stacks tstack, vstack @racc_debug_out.puts end @@ -627,7 +613,5 @@ def racc_token2str(tok) def token_to_str(t) self.class::Racc_token_to_s_table[t] end - end - end diff --git a/lib/racc/parserfilegenerator.rb b/lib/racc/parser_file_generator.rb similarity index 61% rename from lib/racc/parserfilegenerator.rb rename to lib/racc/parser_file_generator.rb index f2d2788a..1d7d7dd6 100644 --- a/lib/racc/parserfilegenerator.rb +++ b/lib/racc/parser_file_generator.rb @@ -1,24 +1,14 @@ -# -# $Id$ -# # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". -require 'enumerator' -require 'racc/compat' -require 'racc/sourcetext' -require 'racc/parser-text' +require 'racc/source' require 'rbconfig' module Racc - class ParserFileGenerator - class Params def self.bool_attr(name) module_eval(<<-End) @@ -32,28 +22,20 @@ def #{name}=(b) End end - attr_accessor :filename - attr_accessor :classname - attr_accessor :superclass - bool_attr :omit_action_call + attr_accessor :file, :encoding, :classname, :superclass bool_attr :result_var - attr_accessor :header - attr_accessor :inner - attr_accessor :footer + attr_accessor :header, :inner, :footer bool_attr :debug_parser - bool_attr :convert_line - bool_attr :convert_line_all bool_attr :embed_runtime bool_attr :make_executable attr_accessor :interpreter def initialize # Parameters derived from parser - self.filename = nil + self.file = nil self.classname = nil self.superclass = 'Racc::Parser' - self.omit_action_call = true self.result_var = true self.header = [] self.inner = [] @@ -61,8 +43,6 @@ def initialize # Parameters derived from command line options self.debug_parser = false - self.convert_line = true - self.convert_line_all = false self.embed_runtime = false self.make_executable = false self.interpreter = nil @@ -88,30 +68,40 @@ def generate_parser def generate_parser_file(destpath) init_line_conversion_system - File.open(destpath, 'w') {|f| - @f = f + if destpath == '-' + @f = $stdout parser_file - } - File.chmod 0755, destpath if @params.make_executable? + else + File.open(destpath, 'w') do |f| + @f = f + parser_file + end + File.chmod(0755, destpath) if @params.make_executable? + end end private def parser_file - shebang @params.interpreter if @params.make_executable? - notice - line - if @params.embed_runtime? - embed_library runtime_source() - else - require 'racc/parser.rb' + Color.without_color do + shebang(@params.interpreter) if @params.make_executable? + encoding_comment(@params.encoding) if @params.encoding + notice + line + if @params.embed_runtime? + embed_library(read_source('info.rb')) + embed_library(read_source('exception.rb')) + embed_library(read_source('parser.rb')) + else + require 'racc/parser.rb' + end + header + parser_class(@params.classname, @params.superclass) do + inner + state_transition_table + end + footer end - header - parser_class(@params.classname, @params.superclass) { - inner - state_transition_table - } - footer end c = ::RbConfig::CONFIG @@ -121,25 +111,30 @@ def shebang(path) line '#!' + (path == 'ruby' ? RUBY_PATH : path) end + def encoding_comment(encoding) + line "# encoding: #{encoding}" + end + def notice line %q[#] line %q[# DO NOT MODIFY!!!!] - line %Q[# This file is automatically generated by Racc #{Racc::Version}] - line %Q[# from Racc grammer file "#{@params.filename}".] + line %Q[# This file was automatically generated by Racc #{Racc::VERSION}] + line %Q[# (codename: #{Racc::CODENAME}) from Racc grammar file "#{@params.file.name}".] line %q[#] end - def runtime_source - SourceText.new(::Racc::PARSER_TEXT, 'racc/parser.rb', 1) + def read_source(filename) + path = File.join(File.dirname(__FILE__), filename) + Source::Buffer.new("racc/#{filename}", File.read(path)) end def embed_library(src) - line %[###### #{src.filename} begin] - line %[unless $".index '#{src.filename}'] - line %[$".push '#{src.filename}'] - put src, @params.convert_line? + line %[###### #{src.name} begin] + line %[unless $".index '#{src.name}'] + line %[$".push '#{src.name}'] + put src line %[end] - line %[###### #{src.filename} end] + line %[###### #{src.name} end] end def require(feature) @@ -167,34 +162,30 @@ def parser_class(classname, superclass) def header @params.header.each do |src| line - put src, @params.convert_line_all? + put src end end def inner @params.inner.each do |src| line - put src, @params.convert_line? + put src end end def footer @params.footer.each do |src| line - put src, @params.convert_line_all? + put src end end # Low Level Routines - def put(src, convert_line = false) - if convert_line - replace_location(src) { - @f.puts src.text - } - else + def put(src) + replace_location(src) { @f.puts src.text - end + } end def line(str = '') @@ -224,30 +215,34 @@ def toplevel? def replace_location(src) sep = make_separator(src) - @f.print 'self.class.' if toplevel? - @f.puts "module_eval(<<'#{sep}', '#{src.filename}', #{src.lineno})" + @f.print 'Object.' if toplevel? + @f.puts "module_eval(<<'#{sep}', '#{src.name}', #{src.lineno})" yield @f.puts sep end def make_separator(src) - sep = unique_separator(src.filename) + sep = unique_separator(src.name) sep *= 2 while src.text.index(sep) sep end def unique_separator(id) sep = "...end #{id}/module_eval..." - while @used_separator.key?(sep) - sep.concat sprintf('%02x', rand(255)) + + if @used_separator.key?(sep) + suffix = 2 + while @used_separator.key?("#{sep}#{suffix}") + suffix += 1 + end + sep = "#{sep}#{suffix}" end + @used_separator[sep] = true sep end - # # State Transition Table Serialization - # public @@ -320,57 +315,8 @@ def state_transition_table end def integer_list(name, table) - if table.size > 2000 - serialize_integer_list_compressed name, table - else - serialize_integer_list_std name, table - end - end - - def serialize_integer_list_compressed(name, table) - # TODO: this can be made a LOT more clean with a simple split/map - sep = "\n" - nsep = ",\n" - buf = '' - com = '' - ncom = ',' - co = com - @f.print 'clist = [' - table.each do |i| - buf << co << i.to_s; co = ncom - if buf.size > 66 - @f.print sep; sep = nsep - @f.print "'", buf, "'" - buf = '' - co = com - end - end - unless buf.empty? - @f.print sep - @f.print "'", buf, "'" - end - line ' ]' - - @f.print(<<-End) - #{name} = arr = ::Array.new(#{table.size}, nil) - idx = 0 - clist.each do |str| - str.split(',', -1).each do |i| - arr[idx] = i.to_i unless i.empty? - idx += 1 - end - end - End - end - - def serialize_integer_list_std(name, table) - sep = '' - line "#{name} = [" - table.each_slice(10) do |ns| - @f.print sep; sep = ",\n" - @f.print ns.map {|n| sprintf('%6s', n ? n.to_s : 'nil') }.join(',') - end - line ' ]' + lines = table.inspect.split(/((?:\w+, ){15})/).reject { |s| s.empty? } + line "#{name} = #{lines.join("\n")}" end def i_i_sym_list(name, table) @@ -388,7 +334,7 @@ def sym_int_hash(name, h) @f.print "#{name} = {" h.to_a.sort_by {|sym, i| i }.each do |sym, i| @f.print sep; sep = ",\n" - @f.printf " %s => %d", sym.serialize, i + @f.printf " %s => %d", sym.serialized, i end line " }" end @@ -404,51 +350,36 @@ def string_list(name, list) end def actions - @grammar.each do |rule| - unless rule.action.source? - raise "racc: fatal: cannot generate parser file when any action is a Proc" - end + if @grammar.any? { |rule| !rule.action.source? } + raise "racc: fatal: cannot generate parser file when any action is a Proc" end if @params.result_var? decl = ', result' retval = "\n result" - default_body = '' else decl = '' retval = '' - default_body = 'val[0]' end @grammar.each do |rule| line - if rule.action.empty? and @params.omit_action_call? + if rule.action.empty? line "# reduce #{rule.ident} omitted" else - src0 = rule.action.source || SourceText.new(default_body, __FILE__, 0) - if @params.convert_line? - src = remove_blank_lines(src0) - delim = make_delimiter(src.text) - @f.printf unindent_auto(<<-End), - module_eval(<<'%s', '%s', %d) - def _reduce_%d(val, _values%s) - %s%s - end - %s - End - delim, src.filename, src.lineno - 1, - rule.ident, decl, - src.text, retval, - delim - else - src = remove_blank_lines(src0) - @f.printf unindent_auto(<<-End), + src0 = rule.action.source + src = src0.drop_leading_blank_lines + delim = make_delimiter(src.text) + @f.printf unindent_auto(<<-End), + module_eval(<<'%s', '%s', %d) def _reduce_%d(val, _values%s) - %s%s + %s%s end - End + %s + End + delim, src.name, src.lineno - 1, rule.ident, decl, - src.text, retval - end + src.text, retval, + delim end end line @@ -460,15 +391,6 @@ def _reduce_none(val, _values%s) line end - def remove_blank_lines(src) - body = src.text.dup - line = src.lineno - while body.slice!(/\A[ \t\f]*(?:\n|\r\n|\r)/) - line += 1 - end - SourceText.new(body, src.filename, line) - end - def make_delimiter(body) delim = '.,.,' while body.index(delim) @@ -506,7 +428,5 @@ def detab(str, ts = 8) ' ' * len } end - end - end diff --git a/lib/racc/pre-setup b/lib/racc/pre-setup deleted file mode 100644 index 5027d865..00000000 --- a/lib/racc/pre-setup +++ /dev/null @@ -1,13 +0,0 @@ -def generate_parser_text_rb(target) - return if File.exist?(srcfile(target)) - $stderr.puts "generating #{target}..." - File.open(target, 'w') {|f| - f.puts "module Racc" - f.puts " PARSER_TEXT = <<'__end_of_file__'" - f.puts File.read(srcfile('parser.rb')) - f.puts "__end_of_file__" - f.puts "end" - } -end - -generate_parser_text_rb 'parser-text.rb' diff --git a/lib/racc/rdoc/grammar.en.rdoc b/lib/racc/rdoc/grammar.en.rdoc new file mode 100644 index 00000000..af10803f --- /dev/null +++ b/lib/racc/rdoc/grammar.en.rdoc @@ -0,0 +1,219 @@ += Racc Grammar File Reference + +== Global Structure + +== Class Block and User Code Block + +There are two blocks on the toplevel. One is the 'class' block, the other is the 'user code' +block. The 'user code' block MUST be placed after the 'class' block. + +== Comments + +You can insert comments about all places. Two styles of comments can be used, Ruby style '#.....' and C style '/\*......*\/'. + +== Class Block + +The class block is formed like this: + + class CLASS_NAME + [precedence table] + [token declarations] + [expected number of S/R conflicts] + [options] + [semantic value conversion] + [start rule] + rule + GRAMMARS + +CLASS_NAME is a name of the parser class. This is the name of the generating parser +class. + +If CLASS_NAME includes '::', Racc outputs the module clause. For example, writing +"class M::C" causes the code below to be created: + + module M + class C + : + : + end + end + +== Grammar Block + +The grammar block describes grammar which is able to be understood by the parser. +Syntax is: + + (token): (token) (token) (token).... (action) + + (token): (token) (token) (token).... (action) + | (token) (token) (token).... (action) + | (token) (token) (token).... (action) + +(action) is an action which is executed when its (token)s are found. +(action) is a ruby code block, which is surrounded by braces: + + { print val[0] + puts val[1] } + +Note that you cannot use '%' string, here document, '%r' regexp in action. + +Actions can be omitted. When it is omitted, '' (empty string) is used. + +A return value of action is a value of the left side value ($$). It is the value of the +result, or the returned value by `return` statement. + +Here is an example of the whole grammar block. + + rule + goal: definition rules source { result = val } + + definition: /* none */ { result = [] } + | definition startdesig { result[0] = val[1] } + | definition + precrule # this line continues from upper line + { + result[1] = val[1] + } + + startdesig: START TOKEN + +You can use the following special local variables in action: + +* result ($$) + +The value of the left-hand side (lhs). A default value is val[0]. + +* val ($1,$2,$3...) + +An array of value of the right-hand side (rhs). + +* _values (...$-2,$-1,$0) + +A stack of values. DO NOT MODIFY this stack unless you know what you are doing. + +== Operator Precedence + +This function is equal to '%prec' in yacc. +To designate this block: + + prechigh + nonassoc '++' + left '*' '/' + left '+' '-' + right '=' + preclow + +`right` is yacc's %right, `left` is yacc's %left. + +`=` + (symbol) means yacc's %prec: + + prechigh + nonassoc UMINUS + left '*' '/' + left '+' '-' + preclow + + rule + exp: exp '*' exp + | exp '-' exp + | '-' exp =UMINUS # equals to "%prec UMINUS" + : + : + +== expect + +Racc has bison's "expect" directive. + + # Example + + class MyParser + rule + expect 3 + : + : + +This directive declares "expected" number of shift/reduce conflicts. If +"expected" number is equal to real number of conflicts, Racc does not print +conflict warning message. + +== Declaring Tokens + +By declaring tokens, you can avoid many meaningless bugs. If declared token +does not exist or existing token does not decleared, Racc output warnings. +Declaration syntax is: + + token TOKEN_NAME AND_IS_THIS + ALSO_THIS_IS AGAIN_AND_AGAIN THIS_IS_LAST + +== Options + +You can write options for Racc command in your Racc file. + + options OPTION OPTION ... + +Options are: + +* omit_action_call + +omits empty action call or not. + +* result_var + +uses local variable "result" or not. + +You can use 'no_' prefix to invert their meanings. + +== Converting Token Symbol + +Token symbols are, as default, + + * naked token string in Racc file (TOK, XFILE, this_is_token, ...) + --> symbol (:TOK, :XFILE, :this_is_token, ...) + * quoted string (':', '.', '(', ...) + --> same string (':', '.', '(', ...) + +You can change this default by "convert" block. +Here is an example: + + convert + PLUS 'PlusClass' # We use PlusClass for symbol of `PLUS' + MIN 'MinusClass' # We use MinusClass for symbol of `MIN' + end + +We can use almost all ruby value can be used by token symbol, +except 'false' and 'nil'. These cause unexpected parse error. + +If you want to use String as token symbol, special care is required. +For example: + + convert + class '"cls"' # in code, "cls" + PLUS '"plus\n"' # in code, "plus\n" + MIN "\"minus#{val}\"" # in code, \"minus#{val}\" + end + +== Start Rule + +'%start' in yacc. This changes start rule. + + start real_target + +== User Code Block + +"User Code Block" is a Ruby source code which is copied to output. There are +three user code blocks, "header" "inner" and "footer". + +Format of user code is like this: + + ---- header + ruby statement + ruby statement + ruby statement + + ---- inner + ruby statement + : + : + +If four '-' exist on the line head, Racc treats it as the beginning of the +user code block. The name of the user code block must be one word. diff --git a/lib/racc/simulated_automaton.rb b/lib/racc/simulated_automaton.rb new file mode 100644 index 00000000..2c29ab92 --- /dev/null +++ b/lib/racc/simulated_automaton.rb @@ -0,0 +1,151 @@ +require 'racc/state' +require 'racc/directed_graph' +require 'set' + +module Racc + class SimulatedAutomaton + def self.from_path(grammar, path) + path.each_with_object(self.new(grammar.states)) do |sym, automaton| + if sym.terminal? + automaton.consume!(sym) + else + automaton.goto!(sym) + end + end + end + + def initialize(states) + @states = states + @state = states.first + @sstack = [] # state stack + @error = false + end + + attr_reader :state + + def stack + @sstack + end + + def error? + @error + end + + # consuming a terminal may set off a series of reduces before the terminal + # is shifted + def consume!(token) + return self if @error + + action = @state.action[token] || @state.defact + case action + when Shift + @sstack.push(@state) + @state = action.goto_state + shifted(token) + when Reduce + reduce_by!(action.rule) + consume!(token) + when Accept + done + when Error + @error = true + error + else + raise "Illegal action type: #{action.class}" + end + + self + end + + def goto!(nt) + @sstack.push(@state) + @state = @state.gotos[nt].to_state + goto(nt) + self + end + + def reduce_by!(rule) + rule.symbols.size.times { @state = @sstack.pop } + reduced(rule.target) + goto!(rule.target) + end + + # Callbacks; can be overridden + + def shifted(symbol) + end + + def reduced(nt) + end + + def goto(nt) + end + + def done + end + + def error + end + + def path_to_success(traversed = Set.new) + # Find the shortest series of terminals/reduce operations which will take + # us to the accept state + return [] if @state.ident == 1 + return nil if @error + + # Don't go into an infinite loop exploring the same states + return unless traversed.add?(@sstack + [@state]) + + # The state stack will guide us + # How many symbols could we reduce the stack size by for each reduce + # reachable from this state? + core = @state.core.group_by { |ptr| [ptr.target, ptr.index] } + + core.map do |_, ptrs| + ptr = ptrs.min_by do |p| + # how many terminals will it take to reach reduce, if we try to + # follow this rule? + p.following.flat_map(&:shortest_production).size + end + + automaton = self.dup + path1 = automaton.follow_rule(ptr) + next if automaton.error? + + path2 = automaton.path_to_success(traversed) + # If that led to an infinite loop, `path2` will be `nil`. + path2 && path1.concat(path2) + end.compact.min_by(&:size) + end + + def follow_shortest_rule_for(sym) + rule = sym.heads.map(&:rule).min_by do |r| + r.symbols.flat_map(&:shortest_production).size + end + follow_rule(rule.ptrs[0]) + end + + def follow_rule(ptr) + actions = [] + initial_state = @state + + ptr.following.each do |sym| + if sym.terminal? + actions << sym + consume!(sym) + else + actions.concat(follow_shortest_rule_for(sym)) + end + end + + reduce_by!(ptr.rule) + actions << ReduceStep.new(initial_state, @state, ptr.rule, ptr.target) + end + + def dup + result = super + @sstack = @sstack.dup + result + end + end +end diff --git a/lib/racc/source.rb b/lib/racc/source.rb new file mode 100644 index 00000000..09163845 --- /dev/null +++ b/lib/racc/source.rb @@ -0,0 +1,265 @@ +# Copyright (c) 1999-2006 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". + +module Racc + module Source + NL = /\n|\r\n|\r/ + TAB_WIDTH = 8 + TAB_TO_SPACE = (' ' * TAB_WIDTH).freeze + TERM_WIDTH = 80 + + # methods which can be used on any object which represents source text + module Text + def drop_leading_blank_lines + if text =~ /\A(?:[ \t\f\v]*(?:#{NL}))+/ + slice($~.end(0), text.size) + else + self + end + end + + def location + "#{name}:#{lineno}" + end + + # display with color highlights... + def spiffy + highlights.sort_by!(&:from) + + raw = text + cooked = String.new + offset = 0 + + highlights.each do |hilite| + cooked << raw[offset...hilite.from] + cooked << hilite.to_s + offset = hilite.to + end + cooked << raw[offset...raw.size] + end + + # ...and with corrected indention... + def spiffier + cooked = spiffy + # convert leading tabs to spaces so we get indentation right + cooked.gsub!(/^ *(\t+)/) { TAB_TO_SPACE * $1.size } + cooked = (' ' * column) << cooked if column > 0 + cooked.gsub!(/^ {#{min_indent}}/, '') + cooked + end + + # ...and with location + def spifferific + loc = location << ': ' + # add extra indentation at every line start EXCEPT the first + # (to make everything line up) + cooked = spiffier + cooked.gsub!(/(?= from && t.to <= to } + .map { |h| Highlight.new(h.object, h.from - from, h.to - from ) } + end + end + + if Array.method_defined?(:bsearch) + def line_for(offset) + line, _ = line_offsets.bsearch { |lineno, start| start <= offset } + line + end + def column_for(offset) + _, column = line_offsets.bsearch { |lineno, start| start <= offset } + offset - column + end + else + def line_for(offset) + line, _ = line_offsets.find { |lineno, start| start <= offset } + line + end + def column_for(offset) + _, column = line_offsets.find { |lineno, start| start <= offset } + offset - column + end + end + + # line N starts at... + # (a newline is part of the preceding line) + def line_offsets + @line_offsets ||= begin + offsets = [[1, 0]] + index = 1 + text.scan(NL) { offsets.unshift([index += 1, $~.end(0)]) } + offsets + end + end + + def min_indent + @min_indent ||= begin + lines = text.lines.reject { |line| line =~ /\A\s*\Z/ } + lines.map { |line| line[/\A\s*/].gsub("\t", TAB_TO_SPACE).size }.min || 0 + end + end + end + + class Range + include Text + + def initialize(buffer, from, to) + @buffer = buffer + @from = from + @to = to + @highlights = [] + end + + attr_reader :from, :to + attr_accessor :highlights + + def text + @text ||= @buffer.text[@from...@to] + end + + def name + @buffer.name + end + + def lineno + @buffer.line_for(@from) + end + + def lines + (@buffer.line_for(@from))..(@buffer.line_for(@to)) + end + + def column + @buffer.column_for(@from) + end + + def slice(from, to) + raise 'slice end must be >= start' if from > to + max = @to - @from + to = max if to > max + from = max if from > max + Range.new(@buffer, @from + from, @from + to).tap do |range| + range.highlights = + @highlights + .select { |h| h.from >= from && h.to <= to } + .map { |h| Highlight.new(h.object, h.from - from, h.to - from) } + end + end + + def min_indent + @min_indent ||= begin + lines = text.lines.reject { |line| line =~ /\A\s*\Z/ } + widths = lines.map { |line| line[/\A\s*/].gsub("\t", TAB_TO_SPACE).size } + widths[0] += @buffer.column_for(@from) + widths.min || 0 + end + end + end + + class Highlight + def initialize(object, from, to) + @object = object # model object which this text represents + @from = from # offset WITHIN parent Buffer/Range + @to = to + freeze + end + + attr_reader :from, :to, :object + + def to_s + object.to_s # code objects print themselves with color highlighting + end + end + + # A (sparse) set of lines from a Buffer or Range + class SparseLines + def initialize(textobj, line_ranges) + @textobj = textobj + @lines = line_ranges.sort_by(&:begin) + freeze + end + + attr_reader :textobj, :lines + + def self.merge(sparse) + sparse.group_by(&:textobj).map do |textobj, slines| + SparseLines.new(textobj, slines.flat_map(&:lines)) + end + end + + def self.render(sparse) + merge(sparse).map(&:spifferific).join("\n\n") + end + + def spifferific + cooked = @textobj.spiffier.lines.map(&:chomp) + base_line = @textobj.lineno + ranges = canonicalize_ranges(@lines) + groups = ranges.map { |r| cooked[(r.begin - base_line)..(r.end - base_line)] } + groups = groups.map! { |g| g.join("\n") } + + loc_width = "#{@textobj.name}:#{ranges.last.begin}: ".length + + groups.zip(ranges).map! do |g, range| + g.gsub!(/(? last.end + (last.exclude_end? ? 0 : 1) + result << (last = range) + else + range_end = (range.end - (range.exclude_end? ? 1 : 0)) + last_end = (last.end - (last.exclude_end? ? 1 : 0)) + combined = last.begin..(range_end > last_end ? range_end : last_end) + result[-1] = last = combined + end + end + end + end + end +end diff --git a/lib/racc/sourcetext.rb b/lib/racc/sourcetext.rb deleted file mode 100644 index 3b2d89d9..00000000 --- a/lib/racc/sourcetext.rb +++ /dev/null @@ -1,34 +0,0 @@ -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of LGPL, see the file "COPYING". -# - -module Racc - - class SourceText - def initialize(text, filename, lineno) - @text = text - @filename = filename - @lineno = lineno - end - - attr_reader :text - attr_reader :filename - attr_reader :lineno - - def to_s - "#" - end - - def location - "#{@filename}:#{@lineno}" - end - end - -end diff --git a/lib/racc/state.rb b/lib/racc/state.rb index 735e622b..599f6fd7 100644 --- a/lib/racc/state.rb +++ b/lib/racc/state.rb @@ -1,42 +1,46 @@ -# -# $Id$ -# # Copyright (c) 1999-2006 Minero Aoki # # This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of the GNU LGPL, see the file "COPYING". -# +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". -require 'racc/iset' -require 'racc/statetransitiontable' +require 'racc/state_transition_table' require 'racc/exception' -require 'forwardable' +require 'racc/util' +require 'racc/directed_graph' -module Racc +require 'set' - # A table of LALR states. +module Racc class States - include Enumerable - def initialize(grammar, debug_flags = DebugFlags.new) + def initialize(grammar) @grammar = grammar - @symboltable = grammar.symboltable - @d_state = debug_flags.state - @d_la = debug_flags.la - @d_prec = debug_flags.prec - @states = [] - @statecache = {} - @actions = ActionTable.new(@grammar, self) - @nfa_computed = false - @dfa_computed = false + @states = [] + @gotos = [] # all state transitions performed when reducing + # Goto is also used for state transitions when shifting, + # but those objects don't go in this array + + generate_states + compute_lookahead + + @states.each { |state| resolve(state) } + set_accept + @states.each { |state| pack(state) } end attr_reader :grammar attr_reader :actions + def each(&block) + @states.each(&block) + end + + def [](idx) + @states[idx] + end + def size @states.size end @@ -47,876 +51,588 @@ def inspect alias to_s inspect - def [](i) - @states[i] - end - - def each_state(&block) - @states.each(&block) - end - - alias each each_state - - def each_index(&block) - @states.each_index(&block) - end - - extend Forwardable - - def_delegator "@actions", :shift_n - def_delegator "@actions", :reduce_n - def_delegator "@actions", :nt_base - def should_report_srconflict? - srconflict_exist? and - (n_srconflicts() != @grammar.n_expected_srconflicts) - end - - def srconflict_exist? - n_srconflicts() != 0 + sr_conflicts.any? && (sr_conflicts.size != @grammar.n_expected_srconflicts) end - def n_srconflicts - @n_srconflicts ||= inject(0) {|sum, st| sum + st.n_srconflicts } + def sr_conflicts + flat_map { |state| state.sr_conflicts.values } end - def rrconflict_exist? - n_rrconflicts() != 0 - end - - def n_rrconflicts - @n_rrconflicts ||= inject(0) {|sum, st| sum + st.n_rrconflicts } + def rr_conflicts + flat_map { |state| state.rr_conflicts.values } end def state_transition_table - @state_transition_table ||= StateTransitionTable.generate(self.dfa) - end - - # - # NFA (Non-deterministic Finite Automaton) Computation - # - - public - - def nfa - return self if @nfa_computed - compute_nfa - @nfa_computed = true - self + @state_transition_table ||= StateTransitionTable.generate(self) end private - def compute_nfa - @grammar.init - # add state 0 - core_to_state [ @grammar[0].ptrs[0] ] - # generate LALR states - cur = 0 - @gotos = [] - while cur < @states.size - generate_states @states[cur] # state is added here - cur += 1 - end - @actions.init - end + def generate_states + # create start state + start = State.new(0, Set[@grammar[0].ptrs[0]], self) - def generate_states(state) - puts "dstate: #{state}" if @d_state + @states << start + states = {start.core => start} + worklist = [start] - table = {} - state.closure.each do |ptr| - if sym = ptr.dereference - addsym table, sym, ptr.next - end - end - table.each do |sym, core| - puts "dstate: sym=#{sym} ncore=#{core}" if @d_state - - dest = core_to_state(core.to_a) - state.goto_table[sym] = dest - id = sym.nonterminal?() ? @gotos.size : nil - g = Goto.new(id, sym, state, dest) - @gotos.push g if sym.nonterminal? - state.gotos[sym] = g - puts "dstate: #{state.ident} --#{sym}--> #{dest.ident}" if @d_state - - # check infinite recursion - if state.ident == dest.ident and state.closure.size == 1 - raise CompileError, - sprintf("Infinite recursion: state %d, with rule %d", - state.ident, state.ptrs[0].rule.ident) - end - end - end + until worklist.empty? + state = worklist.shift - def addsym(table, sym, ptr) - unless s = table[sym] - table[sym] = s = ISet.new - end - s.add ptr - end + # build table of what the 'core' of the following state will be, if the + # next token appearing in the input was 'sym' + # + # a 'core' is a set of LocationPointers, indicating all the possible + # positions within the RHS of a rule where we could be right now + # convert core to a State object; if state does not exist, create it - def core_to_state(core) - # - # convert CORE to a State object. - # If matching state does not exist, create it and add to the table. - # - - k = fingerprint(core) - unless dest = @statecache[k] - # not registered yet - dest = State.new(@states.size, core) - @states.push dest - - @statecache[k] = dest - - puts "core_to_state: create state ID #{dest.ident}" if @d_state - else - if @d_state - puts "core_to_state: dest is cached ID #{dest.ident}" - puts "core_to_state: dest core #{dest.core.join(' ')}" + table = Hash.new { |h,k| h[k] = Set.new } + state.closure.each do |ptr| + table[ptr.symbol].add(ptr.next) unless ptr.reduce? end - end - - dest - end - def fingerprint(arr) - arr.map {|i| i.ident }.pack('L*') - end - - # - # DFA (Deterministic Finite Automaton) Generation - # - - public + table.each do |sym, core| + # each possible 'core' corresponds to one LALR state - def dfa - return self if @dfa_computed - nfa - compute_dfa - @dfa_computed = true - self - end + unless dest = states[core] + # not registered yet + dest = State.new(@states.size, core, self) + @states << dest + worklist << dest + states[core] = dest + end - private + goto = Goto.new(sym.nonterminal? && @gotos.size, sym, state, dest) + @gotos << goto if sym.nonterminal? + state.gotos[sym] = goto - def compute_dfa - la = lookahead() - @states.each do |state| - state.la = la - resolve state - end - set_accept - @states.each do |state| - pack state + if state.ident == dest.ident and state.closure.size == 1 + rule = state.ptrs[0].rule + raise CompileError, "Infinite recursion in rule: #{rule}" + end + end end - check_useless end - def lookahead - # + def compute_lookahead # lookahead algorithm ver.3 -- from bison 1.26 - # - - gotos = @gotos - if @d_la - puts "\n--- goto ---" - gotos.each_with_index {|g, i| print i, ' '; p g } - end - ### initialize_LA() - ### set_goto_map() - la_rules = [] - @states.each do |state| - state.check_la la_rules - end - - ### initialize_F() - f = create_tmap(gotos.size) - reads = [] - edge = [] - gotos.each do |goto| - goto.to_state.goto_table.each do |t, st| - if t.terminal? - f[goto.ident] |= (1 << t.ident) - elsif t.nullable? - edge.push goto.to_state.gotos[t].ident + # build a bitmap which shows which terminals could possibly appear next + # after each reduction in the grammar + # (we will use this information to decide which reduction to perform if + # two of them are possible, or whether to do a shift or a reduce if both + # are possible) + # (if both reductions A and B are possible, but we see that the next token + # can only validly appear after reduction A and not B, then we will choose + # to perform reduction A) + following_terminals = create_bitmap(@gotos.size) + look_past = Graph::Finite.new(@gotos.size) + @gotos.each do |goto| + goto.to_state.gotos.each do |tok, next_goto| + if tok.terminal? + # set bit for terminal which could be shifted after this reduction + following_terminals[goto.ident] |= (1 << tok.ident) + elsif tok.nullable? + # if a nullable NT could come next, then we have to look past it + # to see which terminals could appear next + look_past.add_child(goto.ident, next_goto.ident) end end - if edge.empty? - reads.push nil - else - reads.push edge - edge = [] - end - end - digraph f, reads - if @d_la - puts "\n--- F1 (reads) ---" - print_tab gotos, reads, f end - - ### build_relations() - ### compute_FOLLOWS - path = nil - edge = [] - lookback = Array.new(la_rules.size, nil) - includes = [] - gotos.each do |goto| + look_past.freeze + + # traverse graph with arrows connecting reductions which could occur + # directly after another without shifting any terminal first (because the + # reduced nonterminal is null) + walk_graph(following_terminals, look_past) + + # there is another case we have to consider to get the full set of tokens + # which can validly appear after each reduction... + # what if we do 2 reductions in a row? or 3, 4, 5...? + # if terminal T1 can appear after nonterminal A, and we can reduce to A + # immediately after reducing to B, that means terminal T1 could also + # appear after B + + # but that's not all! think about this: + # what if we have a rule like "A = BC", and we know terminal T1 can appear + # after A, *and C is nullable*? + # that means T1 can also appear after B, not just after C + + includes = Graph::Finite.new(@gotos.size) + # look at the state transition triggered by each reduction in the grammar + # (at each place in the state graph where that reduction can occur) + @gotos.each do |goto| + # look at RHS of each rule which could have lead to this reduction goto.symbol.heads.each do |ptr| - path = record_path(goto.from_state, ptr.rule) - lastgoto = path.last - st = lastgoto ? lastgoto.to_state : goto.from_state - if st.conflict? - addrel lookback, st.rruleid(ptr.rule), goto - end - path.reverse_each do |g| - break if g.symbol.terminal? - edge.push g.ident - break unless g.symbol.nullable? + # what sequence of state transitions would we have made to reach + # this reduction, if this is the rule that was used? + path(goto.from_state, ptr.rule).reverse_each do |preceding_goto| + break if preceding_goto.symbol.terminal? + includes.add_child(preceding_goto.ident, goto.ident) + break unless preceding_goto.symbol.nullable? end end - if edge.empty? - includes.push nil - else - includes.push edge - edge = [] - end - end - includes = transpose(includes) - digraph f, includes - if @d_la - puts "\n--- F2 (includes) ---" - print_tab gotos, includes, f end + includes.freeze - ### compute_lookaheads - la = create_tmap(la_rules.size) - lookback.each_with_index do |arr, i| - if arr - arr.each do |g| - la[i] |= f[g.ident] - end - end - end - if @d_la - puts "\n--- LA (lookback) ---" - print_tab la_rules, lookback, la - end - - la - end - - def create_tmap(size) - Array.new(size, 0) # use Integer as bitmap - end + walk_graph(following_terminals, includes) - def addrel(tbl, i, item) - if a = tbl[i] - a.push item - else - tbl[i] = [item] - end - end + # Now we know which terminals can follow each reduction + # But this lookahead information is only needed when there would otherwise + # be a S/R or R/R conflict - def record_path(begst, rule) - st = begst - path = [] - rule.symbols.each do |t| - goto = st.gotos[t] - path.push goto - st = goto.to_state - end - path - end + # So, find all the states leading to a possible reduce, where there is a + # S/R or R/R conflict, and copy the lookahead set for each reduce to the + # preceding state which has the conflict - def transpose(rel) - new = Array.new(rel.size, nil) - rel.each_with_index do |arr, idx| - if arr - arr.each do |i| - addrel new, i, idx + @gotos.each do |goto| + goto.symbol.heads.each do |ptr| + path = path(goto.from_state, ptr.rule) + prev_state = (path.last && path.last.to_state) || goto.from_state + if prev_state.conflict? + ritem = prev_state.ritems.find { |item| item.rule == ptr.rule } + ritem.lookahead |= following_terminals[goto.ident] end end end - new end - def digraph(map, relation) - n = relation.size - index = Array.new(n, nil) - vertices = [] - @infinity = n + 2 + def create_bitmap(size) + Array.new(size, 0) # use Integer as bitmap + end - index.each_index do |i| - if not index[i] and relation[i] - traverse i, index, vertices, map, relation - end + # Sequence of state transitions which would be taken when starting + # from 'state', then following the RHS of 'rule' right to the end + def path(state, rule) + rule.symbols.each_with_object([]) do |tok, path| + goto = state.gotos[tok] + path << goto + state = goto.to_state end end - def traverse(i, index, vertices, map, relation) - vertices.push i - index[i] = height = vertices.size + # traverse a directed graph + # each entry in 'bitmap' corresponds to a graph node + # after the traversal, the bitmap for each node will be the union of its + # original value, and ALL the values for all the nodes which are reachable + # from it + def walk_graph(bitmap, graph) + index = Array.new(graph.size, nil) + traversed = Set.new - if rp = relation[i] - rp.each do |proci| - unless index[proci] - traverse proci, index, vertices, map, relation - end - if index[i] > index[proci] - # circulative recursion !!! - index[i] = index[proci] - end - map[i] |= map[proci] - end + graph.nodes do |node| + next if traversed.include?(node) + traverse(node, traversed, index, [], bitmap, graph) end + end - if index[i] == height - while true - proci = vertices.pop - index[proci] = @infinity - break if i == proci + def traverse(node, traversed, index, stack, bitmap, graph) + traversed.add(node) + stack.push(node) + index[node] = stack_depth = stack.size - map[proci] |= map[i] + graph.children(node) do |next_node| + unless index[next_node] + traverse(next_node, traversed, index, stack, bitmap, graph) end - end - end - # for debug - def print_atab(idx, tab) - tab.each_with_index do |i,ii| - printf '%-20s', idx[ii].inspect - p i - end - end + if index[node] > index[next_node] + # there is a cycle in the graph + # we already passed through 'next_node' to reach here + index[node] = index[next_node] + end - def print_tab(idx, rel, tab) - tab.each_with_index do |bin,i| - print i, ' ', idx[i].inspect, ' << '; p rel[i] - print ' ' - each_t(@symboltable, bin) {|t| print ' ', t } - puts + bitmap[node] |= bitmap[next_node] end - end - # for debug - def print_tab_i(idx, rel, tab, i) - bin = tab[i] - print i, ' ', idx[i].inspect, ' << '; p rel[i] - print ' ' - each_t(@symboltable, bin) {|t| print ' ', t } - end + if index[node] == stack_depth + while true + next_node = stack.pop + index[next_node] = graph.size + 2 + break if node == next_node - # for debug - def printb(i) - each_t(@symboltable, i) do |t| - print t, ' ' + bitmap[next_node] |= bitmap[node] + end end - puts end - def each_t(tbl, set) - 0.upto( set.size ) do |i| - (0..7).each do |ii| - if set[idx = i * 8 + ii] == 1 - yield tbl[idx] - end + def resolve(state) + if state.conflict? + resolve_rr(state, state.ritems) + resolve_sr(state, state.stokens) + elsif state.rrules.empty? + # shift + state.stokens.each do |t| + state.action[t] = Shift.new(state.gotos[t].to_state) end + else + # only reduce is possible; we won't even bother looking at the next + # token in this state + state.defact = Reduce.new(state.rrules[0]) end end - # - # resolve - # + def resolve_rr(state, ritems) + rrules = Hash.new { |h,k| h[k] = [] } - def resolve(state) - if state.conflict? - resolve_rr state, state.ritems - resolve_sr state, state.stokens - else - if state.rrules.empty? - # shift - state.stokens.each do |t| - state.action[t] = @actions.shift(state.goto_table[t]) - end - else - # reduce - state.defact = @actions.reduce(state.rrules[0]) + ritems.each do |item| + item.each_lookahead_token(@grammar.symbols) do |sym| + rrules[sym] << item.rule end end - end - def resolve_rr(state, r) - r.each do |item| - item.each_la(@symboltable) do |t| - act = state.action[t] - if act - unless act.kind_of?(Reduce) - raise "racc: fatal: #{act.class} in action table" - end - # Cannot resolve R/R conflict (on t). - # Reduce with upper rule as default. - state.rr_conflict act.rule, item.rule, t - else - # No conflict. - state.action[t] = @actions.reduce(item.rule) + rrules.each do |sym, rules| + # If there is a conflict, reduce with the rule which appeared + # first in the source + state.action[sym] = Reduce.new(rules[0]) + if rules.size > 1 + state.rr_conflict!(sym, rules) + rules.drop(1).each do |rule| + rule.overridden_by[sym] << rules[0] end end end end - def resolve_sr(state, s) - s.each do |stok| - goto = state.goto_table[stok] + def resolve_sr(state, stokens) + stokens.each do |stok| + goto = state.gotos[stok] act = state.action[stok] unless act # no conflict - state.action[stok] = @actions.shift(goto) + state.action[stok] = Shift.new(goto.to_state) else - unless act.kind_of?(Reduce) - puts 'DEBUG -------------------------------' - p stok - p act - state.action.each do |k,v| - print k.inspect, ' ', v.inspect, "\n" - end - raise "racc: fatal: #{act.class} in action table" - end - - # conflict on stok - + # conflict rtok = act.rule.precedence - case do_resolve_sr(stok, rtok) + case do_resolve_sr(stok, rtok, act.rule) when :Reduce # action is already set when :Shift # overwrite - act.decref - state.action[stok] = @actions.shift(goto) + act.rule.overridden_by[stok].merge(state.srules[stok].map(&:rule)) + state.action[stok] = Shift.new(goto.to_state) when :Error - act.decref - state.action[stok] = @actions.error + state.action[stok] = Error.new when :CantResolve # shift as default - act.decref - state.action[stok] = @actions.shift(goto) - state.sr_conflict stok, act.rule + srules = state.srules[stok] + act.rule.overridden_by[stok].merge(srules.map(&:rule)) + state.action[stok] = Shift.new(goto.to_state) + state.sr_conflict!(stok, srules, act.rule) end end end end - + ASSOC = { :Left => :Reduce, :Right => :Shift, :Nonassoc => :Error } - - def do_resolve_sr(stok, rtok) - puts "resolve_sr: s/r conflict: rtok=#{rtok}, stok=#{stok}" if @d_prec - - unless rtok and rtok.precedence - puts "resolve_sr: no prec for #{rtok}(R)" if @d_prec - return :CantResolve - end - rprec = rtok.precedence - unless stok and stok.precedence - puts "resolve_sr: no prec for #{stok}(S)" if @d_prec - return :CantResolve - end - sprec = stok.precedence + def do_resolve_sr(stok, rtok, rrule) + return :CantResolve unless rtok && (rprec = rtok.precedence) + return :CantResolve unless stok && (sprec = stok.precedence) - ret = if rprec == sprec - ASSOC[rtok.assoc] or - raise "racc: fatal: #{rtok}.assoc is not Left/Right/Nonassoc" - else - (rprec > sprec) ? (:Reduce) : (:Shift) - end + rrule.explicit_precedence_used! - puts "resolve_sr: resolved as #{ret.id2name}" if @d_prec - ret + if rprec == sprec + ASSOC[rtok.assoc] || + (raise "racc: fatal: #{rtok}.assoc is not Left/Right/Nonassoc") + else + (rprec > sprec) ? :Reduce : :Shift + end end - # - # complete - # - def set_accept - anch = @symboltable.anchor - init_state = @states[0].goto_table[@grammar.start] + anch = @grammar.anchor + init_state = @states[0].gotos[@grammar.start].to_state targ_state = init_state.action[anch].goto_state acc_state = targ_state.action[anch].goto_state acc_state.action.clear - acc_state.goto_table.clear - acc_state.defact = @actions.accept + acc_state.defact = Accept.new end def pack(state) - ### find most frequently used reduce rule - act = state.action - arr = Array.new(@grammar.size, 0) - act.each do |t, a| - arr[a.ruleid] += 1 if a.kind_of?(Reduce) - end - i = arr.max - s = (i > 0) ? arr.index(i) : nil - - ### set & delete default action - if s - r = @actions.reduce(s) - if not state.defact or state.defact == r - act.delete_if {|t, a| a == r } - state.defact = r + # find most frequently used reduce rule, and make it the default action + state.defact ||= begin + freq = Hash.new(0) + state.action.each do |tok, act| + freq[act.rule] += 1 if act.is_a?(Reduce) end - else - state.defact ||= @actions.error - end - end - def check_useless - used = [] - @actions.each_reduce do |act| - if not act or act.refn == 0 - act.rule.useless = true + if freq.empty? + Error.new else - t = act.rule.target - used[t.ident] = t - end - end - @symboltable.nt_base.upto(@symboltable.nt_max - 1) do |n| - unless used[n] - @symboltable[n].useless = true + most_common = freq.keys.max_by { |rule| freq[rule] } + reduce = Reduce.new(most_common) + state.action.delete_if { |tok, act| act == reduce } + reduce end end end - end # class StateTable - - - # A LALR state. - class State - - def initialize(ident, core) - @ident = ident - @core = core - @goto_table = {} - @gotos = {} - @stokens = nil - @ritems = nil - @action = {} - @defact = nil - @rrconf = nil - @srconf = nil + public - @closure = make_closure(@core) + def useless_rules + used_rules = Set.new + @states.each do |state| + state.action.each do |tok, act| + used_rules << act.rule if act.is_a?(Reduce) + end + used_rules << state.defact.rule if state.defact.is_a?(Reduce) + end + Set.new(@grammar) - used_rules end - attr_reader :ident - alias stateid ident - alias hash ident - - attr_reader :core - attr_reader :closure - - attr_reader :goto_table - attr_reader :gotos - - attr_reader :stokens - attr_reader :ritems - attr_reader :rrules + def warnings(warnings, verbose = false) + useless_rules.each do |rule| + next unless warnings.for_rule(rule).empty? && + !rule.overridden_by.empty? + warnings.add_for_rule(rule, Warning::RuleAlwaysOverridden.new(rule)) + end - attr_reader :action - attr_accessor :defact # default action + if should_report_srconflict? + sr_conflicts.each do |sr| + warnings.add_for_state(sr.state, + Warning::SRConflict.new(sr, @grammar, verbose)) + end + end - attr_reader :rrconf - attr_reader :srconf + rr_conflicts.each do |rr| + warnings.add_for_state(rr.state, + Warning::RRConflict.new(rr, @grammar, verbose)) + end - def inspect - "" + warnings end - alias to_s inspect - - def ==(oth) - @ident == oth.ident + def transition_graph + # this graph does not have vectors for reduce operations -- rather, + # the nodes where the reduces go to have vectors for the reduced NTs + @tgraph ||= each_with_object(Graph::Labeled.new(size)) do |s, graph| + s.gotos.each do |tok, goto| + graph.add_vector(s.ident, goto.to_state.ident, tok) + end + end.tap { |graph| graph.start = 0 }.freeze end - alias eql? == - - def make_closure(core) - set = ISet.new - core.each do |ptr| - set.add ptr - if t = ptr.dereference and t.nonterminal? - set.update_a t.expand - end - end - set.to_a - end - - def check_la(la_rules) - @conflict = false - s = [] - r = [] - @closure.each do |ptr| - if t = ptr.dereference - if t.terminal? - s[t.ident] = t - if t.ident == 1 # $error - @conflict = true - end + # Like `transition_graph`, but rather than vectors labeled with NTs, we + # have vectors labeled with the shortest series of terminals and reduce + # operations which could take us through the same transition + def detailed_transition_graph + @dtgraph ||= each_with_object(Graph::Labeled.new(size)) do |s, graph| + s.gotos.each do |tok, goto| + path = if tok.terminal? + [tok] + else + actions_to_reach_reduce(s.ident, tok) end - else - r.push ptr.rule + graph.add_vector(s.ident, goto.to_state.ident, path) end + end.tap { |graph| graph.start = 0 }.freeze + end + + # What series of shifts/reduces can produce `target`, starting from state + # `state_idx`? + def actions_to_reach_reduce(state_idx, target) + rule = target.heads.map(&:rule).min_by do |r| + r.symbols.flat_map(&:shortest_production).size end - unless r.empty? - if not s.empty? or r.size > 1 - @conflict = true + + actions, cur_state = [], state_idx + rule.symbols.each do |sym| + if sym.terminal? + actions << sym + else + actions.concat(actions_to_reach_reduce(cur_state, sym)) end + cur_state = transition_graph[cur_state][sym] end - s.compact! - @stokens = s - @rrules = r - - if @conflict - @la_rules_i = la_rules.size - @la_rules = r.map {|i| i.ident } - la_rules.concat r - else - @la_rules_i = @la_rules = nil - end - end + cur_state = transition_graph[state_idx][target] - def conflict? - @conflict + actions << ReduceStep.new(state_idx, cur_state, rule, target) end - def rruleid(rule) - if i = @la_rules.index(rule.ident) - @la_rules_i + i - else - puts '/// rruleid' - p self - p rule - p @rrules - p @la_rules_i - raise 'racc: fatal: cannot get reduce rule id' - end + def shortest_summarized_paths + @shortest_spaths ||= transition_graph.shortest_vector_paths end - def la=(la) - return unless @conflict - i = @la_rules_i - @ritems = r = [] - @rrules.each do |rule| - r.push Item.new(rule, la[i]) - i += 1 + def shortest_detailed_paths + @shortest_dpaths ||= begin + paths = detailed_transition_graph.shortest_vector_paths(&:size) + Hash[paths.map { |state, steps| [state, steps.flatten] }] end end - def rr_conflict(high, low, ctok) - c = RRconflict.new(@ident, high, low, ctok) - - @rrconf ||= {} - if a = @rrconf[ctok] - a.push c - else - @rrconf[ctok] = [c] + def possible_reduce_destinations(state, rule) + # after popping states off the stack and following the goto, + # what states might we end up in? + graph = transition_graph + steps_back = rule.symbols.size + dest_indices = steps_back.times.reduce([state.ident]) do |dsts, _| + dsts.map { |dst| graph.parents(dst) }.reduce(Set.new, &:merge) end + dest_indices.map { |idx| self[idx].gotos[rule.target].to_state }.uniq end + end - def sr_conflict(shift, reduce) - c = SRconflict.new(@ident, shift, reduce) - - @srconf ||= {} - if a = @srconf[shift] - a.push c - else - @srconf[shift] = [c] - end + class State + def initialize(ident, core, states) + @ident = ident # ID number used to provide a canonical ordering + @core = core # LocationPointers to all the possible positions within the + # RHS of a rule where we could be when in this state + + @gotos = {} # Sym -> Goto describing state transition if we encounter + # that Sym next + @action = {} # Sym -> Shift/Reduce/Accept/Error describing what we will + # do if we encounter that Sym next + @defact = nil # if action table has no entry for a certain lookahead + # token, perform this action instead + # (if action table is empty, just perform this action + # without even checking the lookahead token) + @rr_conflicts = {} + @sr_conflicts = {} + @states = states + + @core.freeze end - def n_srconflicts - @srconf ? @srconf.size : 0 - end + attr_reader :ident + attr_reader :core + attr_reader :gotos + attr_reader :action + attr_accessor :defact # default action + attr_reader :rr_conflicts + attr_reader :sr_conflicts - def n_rrconflicts - @rrconf ? @rrconf.size : 0 + def inspect + "" end - end # class State - - - # - # Represents a transition on the grammar. - # "Real goto" means a transition by nonterminal, - # but this class treats also terminal's. - # If one is a terminal transition, .ident returns nil. - # - class Goto - def initialize(ident, sym, from, to) - @ident = ident - @symbol = sym - @from_state = from - @to_state = to - end + alias to_s inspect - attr_reader :ident - attr_reader :symbol - attr_reader :from_state - attr_reader :to_state - - def inspect - "(#{@from_state.ident}-#{@symbol}->#{@to_state.ident})" + def closure + # Say we know that we are at "A = B . C" right now; in other words, + # we know that we are parsing an "A", we have already finished the "B", + # and the "C" should be coming next + # If "C" is a non-terminal, then that means the RHS of one of the rules + # for C should come next (but we don't know which one) + # So we could possibly be beginning ANY of the rules for C here + # But if one of the rules for C itself starts with non-terminal "D"... + # well, to find all the possible positions where we could be in each + # rule, we have to recurse down into all the rules for D (and so on) + # This recursion has already been done and the result cached in Sym#expand + @closure ||= @core.each_with_object(Set.new) do |ptr, set| + set.add(ptr) + if sym = ptr.symbol and sym.nonterminal? + set.merge(sym.expand) + end + end.sort_by(&:ident) end - end - - # LALR item. A set of rule and its lookahead tokens. - class Item - def initialize(rule, la) - @rule = rule - @la = la + def stokens + @stokens ||= closure.reject(&:reduce?).map(&:symbol).select(&:terminal?) + .uniq.sort_by(&:ident) end - attr_reader :rule - attr_reader :la - - def each_la(tbl) - la = @la - 0.upto(la.size - 1) do |i| - (0..7).each do |ii| - if la[idx = i * 8 + ii] == 1 - yield tbl[idx] - end + # {Sym -> LocationPointers within rules which direct us to shift that Sym} + def srules + @srules ||= begin + closure.each_with_object(Hash.new { |h,k| h[k] = [] }) do |ptr, table| + next if ptr.reduce? || ptr.symbol.nonterminal? + table[ptr.symbol] << ptr end end end - end - - - # The table of LALR actions. Actions are either of - # Shift, Reduce, Accept and Error. - class ActionTable - - def initialize(rt, st) - @grammar = rt - @statetable = st - @reduce = [] - @shift = [] - @accept = nil - @error = nil + def rrules + @rrules ||= closure.select(&:reduce?).map(&:rule) end - def init - @grammar.each do |rule| - @reduce.push Reduce.new(rule) - end - @statetable.each do |state| - @shift.push Shift.new(state) + # would there be a S/R or R/R conflict IF lookahead was not used? + def conflict? + @conflict ||= begin + (rrules.size > 1) || + (stokens.any? { |tok| tok.ident == 1 }) || # $error symbol + (stokens.any? && rrules.any?) end - @accept = Accept.new - @error = Error.new end - def reduce_n - @reduce.size + # rules for which we need a lookahead set (to disambiguate which of them we + # should apply next) + def ritems + @ritems ||= conflict? ? rrules.map { |rule| Item.new(rule) } : [] end - def reduce(i) - case i - when Rule then i = i.ident - when Integer then ; - else - raise "racc: fatal: wrong class #{i.class} for reduce" - end - - r = @reduce[i] or raise "racc: fatal: reduce action #{i.inspect} not exist" - r.incref - r + def rr_conflict!(sym, rules) + @rr_conflicts[sym] = RRConflict.new(self, sym, rules) end - def each_reduce(&block) - @reduce.each(&block) + def sr_conflict!(token, srules, rrule) + @sr_conflicts[token] = SRConflict.new(self, token, srules, rrule) end - def shift_n - @shift.size + def shortest_summarized_path + # samples sequence of terminals/NTs which would lead here + # from start state (for diagnostics) + @sspath ||= @states.shortest_summarized_paths[@ident] end - def shift(i) - case i - when State then i = i.ident - when Integer then ; - else - raise "racc: fatal: wrong class #{i.class} for shift" + def shortest_detailed_path + # sample sequence of terminals/reduces which would lead here + # from start state (for diagnostics) + @sdpath ||= @states.shortest_detailed_paths[@ident].reject do |step| + step.is_a?(ReduceStep) && step.symbol.hidden? end - - @shift[i] or raise "racc: fatal: shift action #{i} does not exist" end - - def each_shift(&block) - @shift.each(&block) - end - - attr_reader :accept - attr_reader :error - end - - class Shift - def initialize(goto) - @goto_state = goto - end - - attr_reader :goto_state - - def goto_id - @goto_state.ident - end - + # Represents a transition between states in the grammar + # Descriptions of the LR algorithm only talk about doing a "goto" after + # reducing, but this class can also represent a state transition which occurs + # after shifting + # If 'symbol' is a terminal, then ident will be nil (there is no global + # ordering of such Gotos). + # + class Goto < Struct.new(:ident, :symbol, :from_state, :to_state) def inspect - "" + "(#{from_state.ident}-#{symbol}->#{to_state.ident})" end end - - class Reduce + # LALR item: a rule and its lookahead tokens + class Item def initialize(rule) @rule = rule - @refn = 0 + @lookahead = 0 # bitmap of terminal ID numbers (Sym#ident) end attr_reader :rule - attr_reader :refn + attr_accessor :lookahead - def ruleid - @rule.ident + def each_lookahead_token(tbl) + 0.upto((@lookahead.size * 8) - 1) do |idx| + yield tbl[idx] if @lookahead[idx] == 1 + end end + end + class Shift < Struct.new(:goto_state) def inspect - "" - end - - def incref - @refn += 1 + "" end + end - def decref - @refn -= 1 - raise 'racc: fatal: act.refn < 0' if @refn < 0 + class Reduce < Struct.new(:rule) + def inspect + "" end end @@ -932,40 +648,33 @@ def inspect end end - class SRconflict - def initialize(sid, shift, reduce) - @stateid = sid - @shift = shift - @reduce = reduce - end - - attr_reader :stateid - attr_reader :shift - attr_reader :reduce - + class SRConflict < Struct.new(:state, :symbol, :srules, :rrule) def to_s - sprintf('state %d: S/R conflict rule %d reduce and shift %s', - @stateid, @reduce.ruleid, @shift.to_s) + "state #{state.ident}: S/R conflict on #{symbol} between shift rules " \ + "#{srules} and reduce rule #{rrule}" end end - class RRconflict - def initialize(sid, high, low, tok) - @stateid = sid - @high_prec = high - @low_prec = low - @token = tok + class RRConflict < Struct.new(:state, :symbol, :rules) + def to_s + "state #{state.ident}: R/R conflict on #{symbol} between reduce rules " \ + "#{rrules}" end + end + + # Specifically for detailed_transition_graph + class ReduceStep + def initialize(from, to, rule, symbol) + @from = from + @to = to + @rule = rule + @symbol = symbol + end + + attr_reader :from, :to, :rule, :symbol - attr_reader :stateid - attr_reader :high_prec - attr_reader :low_prec - attr_reader :token - def to_s - sprintf('state %d: R/R conflict with rule %d and %d on %s', - @stateid, @high_prec.ident, @low_prec.ident, @token.to_s) + "(reduce to #{@symbol})" end end - end diff --git a/lib/racc/state_summary_generator.rb b/lib/racc/state_summary_generator.rb new file mode 100644 index 00000000..cc05d3bb --- /dev/null +++ b/lib/racc/state_summary_generator.rb @@ -0,0 +1,254 @@ +require 'racc/state' +require 'racc/directed_graph' +require 'racc/util' + +require 'erb' + +module Racc + class StateSummaryGenerator + def initialize(states, filename) + @states = states + @filename = filename + end + + def generate_summary_file(destpath) + if destpath == '-' + puts render + else + File.open(destpath, 'w') do |f| + f.write(render) + end + end + end + + def render + ERB.new(TEMPLATE, nil, nil, '@output').result(binding) + end + + private + + def print_state_title(state) + @output << "State #{state.ident}" + @output << ' (end state)' if state.defact.is_a?(Accept) + @output << ' (start state)' if state.ident == 0 + end + + def print_loc_ptr_as_tr(ptr) + rule = ptr.rule + + @output << '' + print_symbol(rule.target) + @output << ':' + ptr.preceding.reject(&:hidden?).each do |sym| + print_symbol(sym) + @output << ' ' + end + @output << '. ' + ptr.following.reject(&:hidden?).each do |sym| + print_symbol(sym) + @output << ' ' + end + if sym = rule.explicit_precedence + print_explicit_prec(sym) + end + @output << '' + end + + def print_rule(rule) + print_symbol(rule.target) + @output << ' :' + print_symbols(rule.symbols) + if sym = rule.explicit_precedence + @output << ' ' + print_explicit_prec(sym) + end + end + + def print_overridden_rule(rule, action) + @output << "
(Overridden: " + @output << action << ' by ' + print_rule(rule) + @output << ')' + end + + def print_overridden_rules(rules, action) + rules.each { |rule| print_overridden_rule(rule, action) } + end + + def print_symbols(syms) + syms.each do |sym| + next if sym.hidden? + @output << ' ' + print_symbol(sym) + end + end + + def print_symbol(sym) + if sym.string_symbol? + @output << "" \ + "#{sym.display_name}" \ + "" + elsif sym.terminal? + @output << "" \ + "#{sym.display_name}" \ + "" + else + @output << "" \ + "#{sym.display_name}" \ + "" + end + end + + def print_explicit_prec(sym) + @output << "" \ + "=#{sym.display_name}" \ + "" + end + + def print_shortest_path(state) + stack = [] + @output << 'Action:Stack:' + @output << '' + state.shortest_detailed_path.each do |step| + if step.is_a?(Sym) + stack << step + @output << 'Shift ' + print_symbol(step) + @output << '' + print_symbols(stack) + @output << '' + else + rhs = step.rule.symbols.reject(&:hidden?) + reduced = rhs.size.times.map { stack.pop }.reverse + stack << step.symbol + + @output << 'Reduce to ' + print_symbol(step.symbol) + @output << ' by:
' + print_rule(step.rule) + @output << '' + print_symbols(stack) + @output << '' + end + end + @output << '' + end + + def print_action_table(state) + @output << 'Lookahead tokenAction' + @output << '' + state.action.sort_by { |k,v| k.ident }.each do |tok, act| + @output << '' + print_symbol(tok) + @output << '' + print_action(state, tok, act) + @output << '' + end + if state.defact + @output << 'Other' + print_action(state, nil, state.defact) + @output << '' + end + @output << '' + end + + def print_action(state, token, action) + if action.is_a?(Reduce) + @output << 'Reduce by ' + print_rule(action.rule) + @output << '
' + print_state_links(@states.possible_reduce_destinations(state, action.rule)) + if sr = state.sr_conflicts[token] + print_overridden_rules(sr.srules, 'shift') + end + if rr = state.rr_conflicts[token] + print_overridden_rules(rr.rules.drop(1), 'reduce') + end + elsif action.is_a?(Shift) + n = action.goto_state.ident + @output << "Shift and go to state #{n}" + if rr = state.rr_conflicts[token] + print_overridden_rules(rr.rules, 'reduce') + elsif sr = state.sr_conflicts[token] + print_overridden_rule(sr.rrule, 'reduce') + end + elsif action.is_a?(Accept) + @output << 'Accept (success!)' + elsif action.is_a?(Error) + @output << 'Error' + end + end + + def print_action_phrase(action) + if action.is_a?(Reduce) + @output << 'reduce by ' + print_rule(action.rule) + elsif action.is_a?(Shift) + @output << "shift and go to state #{action.goto_state.ident}" + elsif action.is_a?(Accept) + @output << 'stop parsing and return success' + elsif action.is_a?(Error) + @output << 'throw an error' + end + end + + def print_state_links(states) + @output << (states.one? ? '(This takes us to ' : '(This can take us to ') + states = states.map { |s| "#{s.ident}" } + @output << Racc.to_sentence(states, 'or') + @output << ')' + end + + TEMPLATE = <<-END + + + + LR parser states for <%= @filename %> + + + + + <% @states.each do |state| %> +

<% print_state_title(state) %>

+ +

+ <% + state.core.each do |ptr| + print_loc_ptr_as_tr(ptr) + end + %> +

+ + <% unless state.shortest_detailed_path.empty? %>

+ This state can be reached from the start state by:
+ <% print_shortest_path(state) %>
+

<% end %> + +

+ <% if state.action.empty? %> + From here, we <% print_action_phrase(state.defact) %> regardless of what token + comes next.
+ <% if state.defact.is_a?(Reduce) %> + <% print_state_links(@states.possible_reduce_destinations(state, state.defact.rule)) %> + <% end %> + <% else %> + Action table:
+ <% print_action_table(state) %>
+ <% end %> +

+
+ <% end %> + + + + END + end +end \ No newline at end of file diff --git a/lib/racc/state_transition_table.rb b/lib/racc/state_transition_table.rb new file mode 100644 index 00000000..143c4102 --- /dev/null +++ b/lib/racc/state_transition_table.rb @@ -0,0 +1,316 @@ +# Copyright (c) 1999-2006 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". + +require 'racc/parser' + +module Racc + + TRANSITION_TABLE_ATTRS = + [:action_table, :action_check, :action_default, :action_pointer, + :goto_table, :goto_check, :goto_default, :goto_pointer, + :token_table, :reduce_table, :reduce_n, :shift_n, + :nt_base, :token_to_s_table, + :use_result_var, :debug_parser] + + class StateTransitionTable < Struct.new(*TRANSITION_TABLE_ATTRS) + def StateTransitionTable.generate(states) + StateTransitionTableGenerator.new(states).generate + end + + def initialize(states) + super() + @states = states + @grammar = states.grammar + self.use_result_var = true + self.debug_parser = true + end + + attr_reader :states + attr_reader :grammar + + def parser_class + ParserClassGenerator.new(@states).generate + end + + def token_value_table + Hash[token_table.map { |sym, i| [sym.value, i]}] + end + end + + class StateTransitionTableGenerator + def initialize(states) + @states = states + @grammar = states.grammar + end + + def generate + t = StateTransitionTable.new(@states) + gen_action_tables t, @states + gen_goto_tables t, @grammar + t.token_table = token_table(@grammar) + t.reduce_table = reduce_table(@grammar) + t.reduce_n = @grammar.size + t.shift_n = @states.size + t.nt_base = @grammar.nonterminal_base + t.token_to_s_table = @grammar.symbols.map {|sym| sym.to_s } + t + end + + def reduce_table(grammar) + # reduce_table has 3 items for each grammar rule: + # [number of items to pop off stack when reducing, + # ID number of non-terminal to push on stack after reducing, + # method to call to perform the rule's action] + t = [0, 0, :racc_error] + grammar.each_with_index do |rule, idx| + next if idx == 0 + t.push rule.size + t.push rule.target.ident + t.push(rule.action.empty? ? :_reduce_none : "_reduce_#{idx}".to_sym) + end + t + end + + def token_table(grammar) + Hash[grammar.terminals.map { |t| [t, t.ident]}] + end + + # The action and goto tables use a clever trick for compression + # Each state should have its own action table (one per lookahead token) + # Each nonterminal which we can reduce to also has its own goto table + # (with one entry per state which we can perform the reduction from) + # But those tables are very sparse (most entries are nil) + # + # So, to save space, we OVERLAY all the action tables into one big array + # And same with the goto tables + # We must choose an offset for each state, so its populated entries don't + # collide with the populated entries of any other state + # The chosen offsets go in the 'action_pointer' and 'goto_pointer' arrays + # At runtime, we will retrieve the offset for the current state, add the + # token number of the lookahead token, and index into the action/goto table + # + # BUT, what if the lookahead token is one which is illegal in this state? + # OR, what if it's legal, but its entry is the default entry (which does + # not explicitly appear in the main action/goto tables)? + # We could blindly hit an entry which belongs to a different state, and go + # off into some random sequence of states + # To prevent this, there are 'check' arrays with the state numbers which + # each action/goto entry belong to + # So before we retrieve an action/goto and use it, we see whether the + # corresponding 'check' number is the current state number + + def gen_action_tables(t, states) + t.action_default = states.map { |s| act2actid(s.defact) } + t.action_table = [] + t.action_check = [] + t.action_pointer = [] + + entries = [] + states.each do |state| + if state.action.empty? + # there is ONLY one default action in this state + # when the parser sees that the 'action pointer' (or offset) for this + # state is nil, it will just execute the default action + t.action_pointer << nil + else + # build the action table for this state + actions = [] + state.action.each do |tok, act| + actions[tok.ident] = act2actid(act) + end + # then store data which will be used when we overlay all the per-state + # action tables into one big action table + add_entry(entries, actions, state.ident, t.action_pointer) + end + end + + set_table(entries, t.action_table, t.action_check, t.action_pointer) + end + + def gen_goto_tables(t, grammar) + t.goto_table = [] + t.goto_check = [] + t.goto_pointer = [] + t.goto_default = [] + entries = [] + + # for each nonterminal, choose most common destination state after + # reduce as the default destination state + grammar.nonterminals.each do |tok| + freq = Hash.new(0) + @states.each do |state| + if goto = state.gotos[tok] + freq[goto.to_state.ident] += 1 + end + end + + most_common = freq.keys.max_by { |k| freq[k] } + if most_common && freq[most_common] > 1 + t.goto_default << most_common + else + t.goto_default << nil + end + end + + # now build goto table for each nonterminal, and record data which will + # be used when overlaying all the individual goto tables into the main + # goto table + grammar.nonterminals.zip(t.goto_default).each do |tok, default| + array = @states.map do |state| + if goto = state.gotos[tok] + to_state = goto.to_state.ident + to_state unless to_state == default + end + end + + if array.compact.empty? + # there is ONLY one destination state which we can transition to after + # reducing down to this nonterminal + t.goto_pointer << nil + else + array.pop until array.last || array.empty? + add_entry(entries, array, (tok.ident - grammar.nonterminal_base), + t.goto_pointer) + end + end + + set_table(entries, t.goto_table, t.goto_check, t.goto_pointer) + end + + def add_entry(all, array, chkval, ptr_array) + # array is an action/goto array for one state + # the array indices are token numbers + # prepare the data which will be needed when we overall ALL these arrays + # into one big array: + min = array.index { |item| item } + array = array.drop(min) + ptr_array << :just_reserving_space_and_will_be_overwritten + all << [array, chkval, mkmapexp(array), min, ptr_array.size - 1] + end + + n = 2 ** 16 + begin + Regexp.compile("a{#{n}}") + RE_DUP_MAX = n + rescue RegexpError + n /= 2 + retry + end + + def mkmapexp(arr) + map = String.new + maxdup = RE_DUP_MAX + + arr.chunk(&:nil?).each do |is_nil, items| + char = is_nil ? '.' : '-' + if (offset = items.size) == 1 + map << char + else + while offset > maxdup + map << "#{char}{#{maxdup}}" + offset -= maxdup + end + map << "#{char}{#{offset}}" if offset > 0 + end + end + + Regexp.compile(map, 'n') + end + + def set_table(entries, tbl, chk, ptr) + upper = 0 + map = '-' * 10240 + + # sort long to short + # we want a stable sort, so that the output will not be dependent on + # the sorting algorithm used by the underlying Ruby implementation + entries.each_with_index.map { |a, i| a.unshift(i) } + entries.sort! do |a, b| + # find space for the big ones first; it is more likely that the small + # ones will "fit in the cracks" + comp = (b[1].size <=> a[1].size) + comp = (a[0] <=> b[0]) if comp == 0 + comp + end + + entries.each do |_, arr, chkval, expr, min, ptri| + if upper + arr.size > map.size + map << '-' * (arr.size + 1024) + end + idx = map.index(expr) + ptr[ptri] = idx - min + arr.each_with_index do |item, i| + if item + i += idx + tbl[i] = item + chk[i] = chkval + map[i] = 'o' + end + end + upper = idx + arr.size + end + end + + def act2actid(act) + case act + when Shift then act.goto_state.ident + when Reduce then -act.rule.ident + when Accept then @states.size + when Error then @grammar.size * -1 + else + raise "racc: fatal: wrong act type #{act.class} in action table" + end + end + end + + class ParserClassGenerator + def initialize(states) + @states = states + @grammar = states.grammar + end + + def generate + table = @states.state_transition_table + c = Class.new(::Racc::Parser) + c.const_set :Racc_arg, [table.action_table, + table.action_check, + table.action_default, + table.action_pointer, + table.goto_table, + table.goto_check, + table.goto_default, + table.goto_pointer, + table.nt_base, + table.reduce_table, + table.token_value_table, + table.shift_n, + table.reduce_n, + false] + c.const_set :Racc_token_to_s_table, table.token_to_s_table + c.const_set :Racc_debug_parser, true + define_actions c + c + end + + private + + def define_actions(c) + c.module_eval "def _reduce_none(vals, vstack) vals[0] end" + @grammar.each do |rule| + if rule.action.empty? + c.__send__(:alias_method, "_reduce_#{rule.ident}", :_reduce_none) + else + c.__send__(:define_method, "_racc_action_#{rule.ident}", &rule.action.proc) + c.module_eval(<<-End, __FILE__, __LINE__ + 1) + def _reduce_#{rule.ident}(vals, vstack) + _racc_action_#{rule.ident}(*vals) + end + End + end + end + end + end +end diff --git a/lib/racc/statetransitiontable.rb b/lib/racc/statetransitiontable.rb deleted file mode 100644 index 4c5f4311..00000000 --- a/lib/racc/statetransitiontable.rb +++ /dev/null @@ -1,316 +0,0 @@ -# -# $Id$ -# -# Copyright (c) 1999-2006 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# For details of LGPL, see the file "COPYING". -# - -require 'racc/parser' - -unless Object.method_defined?(:funcall) - class Object - alias funcall __send__ - end -end - -module Racc - - StateTransitionTable = Struct.new(:action_table, - :action_check, - :action_default, - :action_pointer, - :goto_table, - :goto_check, - :goto_default, - :goto_pointer, - :token_table, - :reduce_table, - :reduce_n, - :shift_n, - :nt_base, - :token_to_s_table, - :use_result_var, - :debug_parser) - class StateTransitionTable # reopen - def StateTransitionTable.generate(states) - StateTransitionTableGenerator.new(states).generate - end - - def initialize(states) - super() - @states = states - @grammar = states.grammar - self.use_result_var = true - self.debug_parser = true - end - - attr_reader :states - attr_reader :grammar - - def parser_class - ParserClassGenerator.new(@states).generate - end - - def token_value_table - h = {} - token_table().each do |sym, i| - h[sym.value] = i - end - h - end - end - - - class StateTransitionTableGenerator - - def initialize(states) - @states = states - @grammar = states.grammar - end - - def generate - t = StateTransitionTable.new(@states) - gen_action_tables t, @states - gen_goto_tables t, @grammar - t.token_table = token_table(@grammar) - t.reduce_table = reduce_table(@grammar) - t.reduce_n = @states.reduce_n - t.shift_n = @states.shift_n - t.nt_base = @grammar.nonterminal_base - t.token_to_s_table = @grammar.symbols.map {|sym| sym.to_s } - t - end - - def reduce_table(grammar) - t = [0, 0, :racc_error] - grammar.each_with_index do |rule, idx| - next if idx == 0 - t.push rule.size - t.push rule.target.ident - t.push(if rule.action.empty? # and @params.omit_action_call? - then :_reduce_none - else "_reduce_#{idx}".intern - end) - end - t - end - - def token_table(grammar) - h = {} - grammar.symboltable.terminals.each do |t| - h[t] = t.ident - end - h - end - - def gen_action_tables(t, states) - t.action_table = yytable = [] - t.action_check = yycheck = [] - t.action_default = yydefact = [] - t.action_pointer = yypact = [] - e1 = [] - e2 = [] - states.each do |state| - yydefact.push act2actid(state.defact) - if state.action.empty? - yypact.push nil - next - end - vector = [] - state.action.each do |tok, act| - vector[tok.ident] = act2actid(act) - end - addent e1, vector, state.ident, yypact - end - set_table e1, e2, yytable, yycheck, yypact - end - - def gen_goto_tables(t, grammar) - t.goto_table = yytable2 = [] - t.goto_check = yycheck2 = [] - t.goto_pointer = yypgoto = [] - t.goto_default = yydefgoto = [] - e1 = [] - e2 = [] - grammar.each_nonterminal do |tok| - tmp = [] - - # decide default - freq = Array.new(@states.size, 0) - @states.each do |state| - st = state.goto_table[tok] - if st - st = st.ident - freq[st] += 1 - end - tmp[state.ident] = st - end - max = freq.max - if max > 1 - default = freq.index(max) - tmp.map! {|i| default == i ? nil : i } - else - default = nil - end - yydefgoto.push default - - # delete default value - tmp.pop until tmp.last or tmp.empty? - if tmp.compact.empty? - # only default - yypgoto.push nil - next - end - - addent e1, tmp, (tok.ident - grammar.nonterminal_base), yypgoto - end - set_table e1, e2, yytable2, yycheck2, yypgoto - end - - def addent(all, arr, chkval, ptr) - max = arr.size - min = nil - arr.each_with_index do |item, idx| - if item - min ||= idx - end - end - ptr.push(-7777) # mark - arr = arr[min...max] - all.push [arr, chkval, mkmapexp(arr), min, ptr.size - 1] - end - - n = 2 ** 16 - begin - Regexp.compile("a{#{n}}") - RE_DUP_MAX = n - rescue RegexpError - n /= 2 - retry - end - - def mkmapexp(arr) - i = ii = 0 - as = arr.size - map = '' - maxdup = RE_DUP_MAX - curr = nil - while i < as - ii = i + 1 - if arr[i] - ii += 1 while ii < as and arr[ii] - curr = '-' - else - ii += 1 while ii < as and not arr[ii] - curr = '.' - end - - offset = ii - i - if offset == 1 - map << curr - else - while offset > maxdup - map << "#{curr}{#{maxdup}}" - offset -= maxdup - end - map << "#{curr}{#{offset}}" if offset > 1 - end - i = ii - end - Regexp.compile(map, 'n') - end - - def set_table(entries, dummy, tbl, chk, ptr) - upper = 0 - map = '-' * 10240 - - # sort long to short - entries.sort! {|a,b| b[0].size <=> a[0].size } - - entries.each do |arr, chkval, expr, min, ptri| - if upper + arr.size > map.size - map << '-' * (arr.size + 1024) - end - idx = map.index(expr) - ptr[ptri] = idx - min - arr.each_with_index do |item, i| - if item - i += idx - tbl[i] = item - chk[i] = chkval - map[i] = ?o - end - end - upper = idx + arr.size - end - end - - def act2actid(act) - case act - when Shift then act.goto_id - when Reduce then -act.ruleid - when Accept then @states.shift_n - when Error then @states.reduce_n * -1 - else - raise "racc: fatal: wrong act type #{act.class} in action table" - end - end - - end - - - class ParserClassGenerator - - def initialize(states) - @states = states - @grammar = states.grammar - end - - def generate - table = @states.state_transition_table - c = Class.new(::Racc::Parser) - c.const_set :Racc_arg, [table.action_table, - table.action_check, - table.action_default, - table.action_pointer, - table.goto_table, - table.goto_check, - table.goto_default, - table.goto_pointer, - table.nt_base, - table.reduce_table, - table.token_value_table, - table.shift_n, - table.reduce_n, - false] - c.const_set :Racc_token_to_s_table, table.token_to_s_table - c.const_set :Racc_debug_parser, true - define_actions c - c - end - - private - - def define_actions(c) - c.module_eval "def _reduce_none(vals, vstack) vals[0] end" - @grammar.each do |rule| - if rule.action.empty? - c.funcall(:alias_method, "_reduce_#{rule.ident}", :_reduce_none) - else - c.funcall(:define_method, "_racc_action_#{rule.ident}", &rule.action.proc) - c.module_eval(<<-End, __FILE__, __LINE__ + 1) - def _reduce_#{rule.ident}(vals, vstack) - _racc_action_#{rule.ident}(*vals) - end - End - end - end - end - - end - -end # module Racc diff --git a/lib/racc/static.rb b/lib/racc/static.rb deleted file mode 100644 index bebbeb5a..00000000 --- a/lib/racc/static.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'racc' -require 'racc/parser' -require 'racc/grammarfileparser' -require 'racc/parserfilegenerator' -require 'racc/logfilegenerator' diff --git a/lib/racc/util.rb b/lib/racc/util.rb new file mode 100644 index 00000000..10a9fc8d --- /dev/null +++ b/lib/racc/util.rb @@ -0,0 +1,36 @@ +require 'set' + +module Racc + # Helper to implement set-building algorithms, whereby each member which is + # added to a set may result in still others being added, until the entire + # set is found + # Each member of the set (and the initial `worklist` if an explicit one is + # given) will be yielded once; the block should either return `nil`, or an + # `Enumerable` of more members + def self.set_closure(seed, worklist = seed) + worklist = worklist.is_a?(Array) ? worklist.dup : worklist.to_a + result = Set.new(seed) + + until worklist.empty? + if found = yield(worklist.shift, result) + found.each do |member| + worklist.push(member) if result.add?(member) + end + end + end + + result + end + + def self.to_sentence(words, conjunction = 'and') + raise "Can't make a sentence out of zero words" if words.none? + if words.one? + words[0] + elsif words.size == 2 + "#{words[0]} #{conjunction} #{words[1]}" + else + tail = words.pop + "#{words.join(', ')} #{conjunction} #{tail}" + end + end +end \ No newline at end of file diff --git a/lib/racc/warning.rb b/lib/racc/warning.rb new file mode 100644 index 00000000..b9e6486e --- /dev/null +++ b/lib/racc/warning.rb @@ -0,0 +1,303 @@ +require 'racc/color' +require 'racc/simulated_automaton' + +module Racc + include Racc::Color + + # Categorize warnings according to entity which warning relates to + # This can be used to avoid issuing a general warning when a more specific + # and informative warning has already been registered + class Warnings + include Enumerable + + def initialize + @rules = Hash.new { |h,k| h[k] = [] } + @states = Hash.new { |h,k| h[k] = [] } + @symbols = Hash.new { |h,k| h[k] = [] } + end + + def add_for_rule(rule, warning) + @rules[rule] << warning + end + + def add_for_state(state, warning) + @states[state] << warning + end + + def add_for_symbol(symbol, warning) + @symbols[symbol] << warning + end + + def each(&block) + @symbols.keys.sort_by(&:ident).each { |k| @symbols[k].each(&block) } + @rules.keys.sort_by(&:ident).each { |k| @rules[k].each(&block) } + @states.keys.sort_by(&:ident).each { |k| @states[k].each(&block) } + end + + def for_rule(rule) + @rules[rule] + end + + def for_state(state) + @states[state] + end + + def for_symbol(symbol) + @symbols[symbol] + end + end + + class Warning < Struct.new(:type, :title, :details) + def initialize(type, title, details = nil) + super + end + + def to_s + msg = violet('Warning: ') + bright(title) + msg << "\n" << details if details + msg + end + + # Would this warning contain more details in verbose mode? + def verbose_details? + type == :sr_conflict || type == :rr_conflict + end + + class UnusedTerminal < Warning + def initialize(sym) + @sym = sym + end + + def title + "Useless terminal #{@sym} does not appear on the right side of any rule" + end + + def type + :useless_terminal + end + end + + class UnusedNonterminal < Warning + def initialize(sym) + @sym = sym + end + + def title + "Useless nonterminal #{@sym} does not appear on the right side of " \ + "any rule, neither is it the start symbol" + end + + def type + :useless_nonterminal + end + end + + class InfiniteLoop < Warning + def initialize(sym) + @sym = sym + end + + def title + "Useless nonterminal #{@sym} can never be produced from a finite sequence of tokens" + end + + def details + "Its derivation rule#{'s all' unless @sym.heads.one?} contain" \ + "#{'s' if @sym.heads.one?} #{'an ' if @sym.heads.one?}infinite loop" \ + "#{'s' unless @sym.heads.one?}:\n" + + @sym.heads.map { |ptr| ptr.rule.to_s }.join("\n") + end + + def type + :useless_nonterminal + end + end + + class UnreachableNonterminal < Warning + def initialize(sym) + @sym = sym + end + + def title + "Useless nonterminal #{sym} cannot be part of a valid parse tree, " \ + 'since there is no sequence of reductions from it to the start symbol.' + end + + def details + "It can only reduce to: #{sym.reachable.map(&:to_s).join(', ')}" + end + + def type + :useless_nonterminal + end + end + + class UselessPrecedence < Warning + def initialize(rule) + @rule = rule + end + + def title + 'The explicit precedence declaration on this rule does not resolve ' \ + 'any conflicts and can be removed:' + end + + def details + @rule.to_s + end + + def type + :useless_prec + end + end + + class RuleAlwaysOverridden < Warning + def initialize(rule) + @rule = rule + end + + def title + 'This rule will never be used due to low precedence:' + end + + def details + @rule.to_s << "\n\n" << @rule.overridden_by.group_by do |token, rules| + rules + end.map do |rules, tokens| + tokens = tokens.map(&:first) + connective = if tokens.one? + '' + elsif tokens.size == 2 + 'either ' + else + 'any of ' + end + + "When the next token is #{connective}#{Racc.to_sentence(tokens, 'or')}" \ + ", it is overridden by #{rules.one? ? 'this' : 'these'} " \ + "higher-precedence rule#{'s' unless rules.one?}:\n" + + Source::SparseLines.render(rules.map(&:source)) + end.join("\n\n") + end + + def type + :useless_rule + end + end + + class SRConflict < Warning + def initialize(conflict, grammar, verbose) + @grammar = grammar + @path = conflict.state.shortest_summarized_path + @srules = conflict.srules + @rrule = conflict.rrule + @sym = conflict.symbol + @verbose = verbose + end + + def title + "Shift/reduce conflict on #{@sym}," + + (@path.reject(&:hidden?).empty? ? + ' at the beginning of the parse.' : + ' after the following input:') + end + + def details + if @path.reject(&:hidden?).empty? + result = String.new + else + result = @path.reject(&:hidden?).map(&:to_s).join(' ') << "\n" + end + + result << "\nThe following rule#{'s' unless @srules.one?} " \ + "direct#{'s' if @srules.one?} me to shift:\n" << + @srules.map { |ptr| ptr.rule.to_s }.join("\n") << + "\nThe following rule directs me to reduce:\n" << + @rrule.to_s + + if @verbose + sauto = SimulatedAutomaton.from_path(@grammar, @path).consume!(@sym) + result << "\n\nAfter shifting #{@sym}, one path to a successful " \ + "parse would be:\n" << sauto.path_to_success.map(&:to_s).join(' ') + + rauto = SimulatedAutomaton.from_path(@grammar, @path) + .reduce_by!(@rrule).consume!(@sym) + path = rauto.path_to_success + if path + result << "\n\nAfter reducing to #{@rrule.target}, one path to a " \ + "successful parse would be:\n" << path.unshift(@sym).map(&:to_s).join(' ') + else + result << "\n\nI can't see any way that reducing to " \ + "#{@rrule.target} could possibly lead to a successful parse " \ + 'from this situation. But maybe if this parser state was ' \ + "reached through a different input sequence, it could. I'm " \ + 'just a LALR parser generator and I can be pretty daft sometimes.' + end + end + + result + end + + def type + :sr_conflict + end + end + + class RRConflict < Warning + def initialize(conflict, grammar, verbose) + @grammar = grammar + @path = conflict.state.shortest_summarized_path + @sym = conflict.symbol + @rules = conflict.rules + @verbose = verbose + end + + def title + "Reduce/reduce conflict on #{@sym}," + + (@path.reject(&:hidden?).empty? ? + ' at the beginning of the parse.' : + ' after the following input:') + end + + def details + if @path.reject(&:hidden?).empty? + result = String.new + else + result = @path.reject(&:hidden?).map(&:to_s).join(' ') << "\n" + end + + result << "\nIt is possible to reduce by " \ + "#{@rules.size == 2 ? 'either' : 'any'} of these rules:\n" << + @rules.map(&:to_s).join("\n") + + if @verbose + targets = @rules.group_by(&:target) + if targets.size > 1 + targets.each do |target, rules| + rauto = SimulatedAutomaton.from_path(@grammar, @path) + .reduce_by!(rules.first).consume!(@sym) + path = rauto.path_to_success + if path + result << "\n\nAfter reducing to #{target}, one path to a " \ + "successful parse would be:\n" << + path.unshift(@sym).map(&:to_s).join(' ') + else + result << "\n\nI can't see any way that reducing to " \ + "#{target} could possibly lead to a successful parse " \ + 'from this situation. But maybe if this parser state was ' \ + "reached through a different input sequence, it could. I'm " \ + 'just a LALR parser generator and I can be pretty daft sometimes.' + end + end + end + end + + result + end + + def type + :rr_conflict + end + end + end +end diff --git a/misc/dist.sh b/misc/dist.sh deleted file mode 100644 index 6df8d1ba..00000000 --- a/misc/dist.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -rm -rf tmp -mkdir tmp -cd tmp - -# racc, raccrt -cvs -Q export -r`echo V$version | tr . -` -d racc-$version racc -cd racc-$version - make bootstrap lib/racc/parser-text.rb doc - rm -r doc web bits fastcache -cd .. -mkdir -p raccrt-$version/lib/racc -mv racc-$version/lib/racc/parser.rb raccrt-$version/lib/racc -mv racc-$version/ext raccrt-$version -cp racc-$version/setup.rb raccrt-$version -cp racc-$version/README.* raccrt-$version -cp racc-$version/COPYING raccrt-$version -tar czf $ardir/racc/racc-$version.tar.gz racc-$version -tar czf $ardir/raccrt/raccrt-$version.tar.gz raccrt-$version - -# -all -mkdir -p racc-$version-all/packages -cp racc-$version/setup.rb racc-$version-all -cp racc-$version/README.* racc-$version-all -mv racc-$version racc-$version-all/packages/racc -mv raccrt-$version racc-$version-all/packages/raccrt -tar czf $ardir/racc/racc-$version-all.tar.gz racc-$version-all - -cd .. -rm -rf tmp diff --git a/rdoc/en/grammar.en.rdoc b/rdoc/en/grammar.en.rdoc index b15c6e6b..34377493 100644 --- a/rdoc/en/grammar.en.rdoc +++ b/rdoc/en/grammar.en.rdoc @@ -4,227 +4,360 @@ == Class Block and User Code Block -There's two block on toplevel. -one is 'class' block, another is 'user code' block. 'user code' block MUST -places after 'class' block. +There are two blocks at the top level. +One is the 'class' block and the other is the 'user' block. +You MUST write the 'user' block after the 'class' block. +The 'class' block can also be called the 'rule' block or the 'class definition' +block. -== Comment +== Comments -You can insert comment about all places. Two style comment can be used, -Ruby style (#.....) and C style (/*......*/) . +You can insert comments anywhere you like. +There are two possible comment styles, + Ruby style (#.....) and C style (/*......*/) . == Class Block The class block is formed like this: --- -class CLASS_NAME - [precedance table] - [token declearations] - [expected number of S/R conflict] - [options] - [semantic value convertion] - [start rule] -rule - GRAMMARS --- -CLASS_NAME is a name of parser class. -This is the name of generating parser class. - -If CLASS_NAME includes '::', Racc outputs module clause. -For example, writing "class M::C" causes creating the code bellow: --- -module M - class C - : - : + + class CLASS_NAME + [precedence table] + [token declarations] + [expected number of S/R conflict] + [options] + [semantic value conversion] + [start rule] + rule + GRAMMARS + +CLASS_NAME is the name of the parser class to be defined. +This is used as the name of the parser class in the generated file +which is written in Ruby. + +If CLASS_NAME includes '::', Racc outputs a module clause. +For example, when CLASS_NAME is "M::C", +the parser class is defined as follows in the generated file: + + module M + class C + : + : + end end -end --- == Grammar Block -The grammar block discripts grammar which is able -to be understood by parser. Syntax is: --- -(token): (token) (token) (token).... (action) - -(token): (token) (token) (token).... (action) - | (token) (token) (token).... (action) - | (token) (token) (token).... (action) --- -(action) is an action which is executed when its (token)s are found. -(action) is a ruby code block, which is surrounded by braces: --- -{ print val[0] - puts val[1] } --- -Note that you cannot use '%' string, here document, '%r' regexp in action. - -Actions can be omitted. -When it is omitted, '' (empty string) is used. - -A return value of action is a value of left side value ($$). -It is value of result, or returned value by "return" statement. +The grammar block is where you write the grammar rules understood by the +generated parser. +It is written between the reserved words 'rule' and 'end' and its syntax is +as follows: + + (token): (token) (token) (token).... (action) + + (token): (token) (token) (token).... (action) + | (token) (token) (token).... (action) + | (token) (token) (token).... (action) + +(action) is executed when its (token)s are found. +(action) is basically a Ruby code block which is surrounded by braces: + + { print val[0] + puts val[1] } + +The return value of an action is the left-hand side (lhs) value of the rule. +This is $$ in yacc. + +The way to return the value depends on the options you set. +By default, the 'result' local variable (this is val[0] by default) represents +the left-hand side value, thus the value stored in the 'result' variable +is the left-hand side value. + +Alternatively, you can explicitly 'return' the value desired. + +Or, when you set the 'no_result_var' option via options, +the LHS value is the value of the last statement in the action block (same as +Ruby methods). + +In any case, you can omit actions. +When an action is omitted, the left-hand side value is always val[0]. Here is an example of whole grammar block. --- -rule - goal: definition ruls source { result = val } - - definition: /* none */ { result = [] } - | definition startdesig { result[0] = val[1] } - | definition - precrule # this line continue from upper line - { - result[1] = val[1] - } - - startdesig: START TOKEN --- -You can use following special local variables in action. + + rule + goal: definition ruls source { result = val } + + definition: /* none */ { result = [] } + | definition startdesig { result[0] = val[1] } + | definition + precrule # this line continue from upper line + { + result[1] = val[1] + } + + startdesig: START TOKEN + +You can use the following special local variables inside actions. +The symbols shown in parentheses are how they are represented when using +yacc. * result ($$) -The value of left-hand side (lhs). A default value is val[0]. +The value of left-hand side (lhs). This is val[0] by default. * val ($1,$2,$3...) -An array of value of right-hand side (rhs). +An array of the right-hand side (rhs) values. +This is generated every time, so you can freely modify or discard it. * _values (...$-2,$-1,$0) -A stack of values. -DO NOT MODIFY this stack unless you know what you are doing. - -== Operator Precedance - -This function is equal to '%prec' in yacc. -To designate this block: --- -prechigh - nonassoc '++' - left '*' '/' - left '+' '-' - right '=' -preclow --- -`right' is yacc's %right, `left' is yacc's %left. - -`=' + (symbol) means yacc's %prec: --- -prechigh - nonassoc UMINUS - left '*' '/' - left '+' '-' -preclow - -rule - exp: exp '*' exp - | exp '-' exp - | '-' exp =UMINUS # equals to "%prec UMINUS" - : - : --- +A stack of values used by Racc. +DO NOT MODIFY the _values stack unless you know what you are doing. -== expect +There is also a special form of action which is called an embedded action. +An embedded action can be written wherever you like in the middle of the +token sequence. +Here is an example of the embedded action: -Racc has bison's "expect" directive. --- -# Example - -class MyParser -rule - expect 3 - : - : --- -This directive declears "expected" number of shift/reduce conflict. -If "expected" number is equal to real number of conflicts, -racc does not print confliction warning message. + target: A B { puts 'test test' } C D { normal action } + +When a rule is written like this, +the action written between B and C is executed immediately after both A and B +are found. +An embedded action itself has a value, as you can see in the following example: + + target: A { result = 1 } B { p val[1] } + +When the last action block { p val[1] } is executed, +it shows 1 that is the value of the embedded action and not the value of B. + +In effect, writing an embedded action is the same as adding a nonterminal +symbol whose rule is empty. The above example and the following code are +equivalent. + + target : A nonterm B { p val[1] } + nonterm : /* empty rule */ { result = 1 } + +== Operator Precedence + +When there's a shift/reduce conflict on a token, +sometimes the conflict can be eliminated by defining operator precedence. +A famous example of such a case are arithmetic operators and if-else syntax. + +This doesn't mean setting operator precedence is necessary to resolve conflicts +because usually it can also be solved by changing the way rules are +constructed. +However, in most cases using operator precedence results in more simple grammar +syntax. + +When shift/reduce conflicts occur, Racc first investigates whether or not the +precedence is set on the rule. The precedence of a rule is equal to the +precedence of the last terminal symbol of the rule. +For instance, + + target: TERM_A nonterm_a TERM_B nonterm_b + +the precedence of this rule is the precedence of TERM_B. +If no precedence is set on TERM_B, +Racc would be unable to solve the conflict by precedence and report +"Shift/Reduce conflict". + +Here we can see how to designate operator precedence: + + prechigh + nonassoc '++' + left '*' '/' + left '+' '-' + right '=' + preclow + +The token written in the line closer to prechigh has the higher precedence. +You can also write this in reverse order, such as defining preclow before +prechigh at the bottom. + +Left, right and nonassoc represent associativity. +When a conflict occurs between operators whose precedence is equal, their +associativity is used to decide whether to shift or reduce. + +For instance, think of the following case: + + a - b - c + +When the "-" operator is left-associative this is interpreted as follows: + + (a - b) - c + +For instance, arithmetic operators are usually left-associative. + +On the other hand, +if the "-" operator is right-associative it is interpreted as follows: + + a - (b - c) + +When an operator is not allowed to be written in succession like this in the +first place, it is nonassoc. For instance, the "++" operator in the C language +and unary minus are nonassoc. + +The left, right, nonassoc are %left, %right and %nonassoc in yacc. + +By the way, the precedence of the rule to be reduced is usually the precedence +of the last token. (The term "token" is used here to represent the terminal +symbol.) But sometimes we want to change the precedence of a particular token +only inside a particular rule. For example, the precedence of unary minus must +be higher than the precedence of minus for subtraction. + +In such case, you can use %prec in yacc and you can do the same thing by using +'=' + (symbol) with racc. + + prechigh + nonassoc UMINUS + left '*' '/' + left '+' '-' + preclow + + rule + exp: exp '*' exp + | exp '-' exp + | '-' exp =UMINUS # changing the precedence of - only here + : + : + +In the above example, the precedence of the '-' exp rule is equal to the +precedence of UMINUS and higher than the precedence of '*', as we intended. == Declaring Tokens -By declaring tokens, you can avoid many meanless bugs. -If decleared token does not exist/existing token does not decleared, -Racc output warnings. Declearation syntax is: --- -token TOKEN_NAME AND_IS_THIS - ALSO_THIS_IS AGAIN_AND_AGAIN THIS_IS_LAST --- +By explicitly declaring tokens, +you can avoid many meaningless bugs, especially typos. +If a declared token does not exist or an existing token is not declared, +Racc outputs warnings. Such as: + + token TOKEN_NAME AND_IS_THIS + ALSO_THIS_IS AGAIN_AND_AGAIN THIS_IS_LAST + +This feature is similar to %token in yacc but slightly different. +With racc, this is not required and even if the tokens are declared, it does not +cause errors but only warnings. + +Please notice that you can write declarations spanning over multiple lines. + +Racc does have reserved words but they are only considered as reserved +words when they are written at the beginning of the line. Therefore, for +instance, prechigh can also be used as a symbol. However, for an abyssal +reason, no matter what we do, we cannot use 'end' as a symbol. == Options -You can write options for racc command in your racc file. --- -options OPTION OPTION ... --- -Options are: +There are some options you can write in your racc grammar file. +The syntax is: + + options OPTION OPTION ... + +The currently available options are: + + * [no_]result_var + +This is `result_var` by default, which makes the `result` special variable +available in each action block. As also described in the Grammar Block section, +when this is `no_result_var`, the value of the last statement in each action +block is used as the lhs value. + +== expect + +Racc has bison's "expect" directive. - * omit_action_call +A practical parser usually contains non-harmful shift/reduce conflicts. +It's acceptable for the author of the grammar because they already know about +it. However, if Racc reports "conflicts" after a user processed the grammar +file, they might be anxious. -omit empty action call or not. +In that case, you can declare the expected number of the conflicts to suppress +the warning message. - * result_var + # Example -use/does not use local variable "result" + class MyParser + rule + expect 3 + : + : -You can use 'no_' prefix to invert its meanings. +When you declared the expected number of shift/reduce conflicts as 3 like the +above code, the number of conflicts should exactly be 3. +If it was not 3 (even it was zero), racc would print the warning message. -== Converting Token Symbol +Besides, you cannot suppress warning messages for reduce/reduce conflicts. -Token symbols are, as default, +== Converting Token Symbols + +Token symbols abide by the following rules: * naked token string in racc file (TOK, XFILE, this_is_token, ...) - --> symbol (:TOK, :XFILE, :this_is_token, ...) + --> symbol (:TOK, :XFILE, :this_is_token, ...) * quoted string (':', '.', '(', ...) - --> same string (':', '.', '(', ...) + --> same string (':', '.', '(', ...) + +This can be inconvenient when you already have a scanner returning values in a +different form. In that case, you can change this using a "convert" block. -You can change this default by "convert" block. Here is an example: --- -convert - PLUS 'PlusClass' # We use PlusClass for symbol of `PLUS' - MIN 'MinusClass' # We use MinusClass for symbol of `MIN' -end --- -We can use almost all ruby value can be used by token symbol, -except 'false' and 'nil'. These are causes unexpected parse error. - -If you want to use String as token symbol, special care is required. + + convert + PLUS 'PlusClass' # We use PlusClass for symbol of `PLUS' + MIN 'MinusClass' # We use MinusClass for symbol of `MIN' + end + +By default, the value of the token symbol PLUS is :PLUS. +However, when interpreting the above definition it becomes PlusClass. + +We can use all ruby values as token symbol values +except 'false' and 'nil'. + +If you want to use a String as a token symbol, special care is required. For example: --- -convert - class '"cls"' # in code, "cls" - PLUS '"plus\n"' # in code, "plus\n" - MIN "\"minus#{val}\"" # in code, \"minus#{val}\" -end --- + + convert + class '"cls"' # in code, "cls" + PLUS '"plus\n"' # in code, "plus\n" + MIN "\"minus#{val}\"" # in code, \"minus#{val}\" + end == Start Rule -'%start' in yacc. This changes start rule. --- -start real_target --- -This statement will not be used forever, I think. +In order to create a parser, you need to tell Racc the first rule to start. +The start rule is a way to write it explicitly. + + start real_target + +This is usually omitted and in that case, the start rule is the first rule in +the file. + +In yacc, this is '%start'. == User Code Block -"User Code Block" is a Ruby source code which is copied to output. -There are three user code block, "header" "inner" and "footer". +A "User Code Block" is a block of Ruby source code which is copied to the +output file. + +There can be up to three user code blocks: "header", "inner" and "footer". + +The code written in the "header" block is copied to just before the parser class +definition. "inner" is for inside (and the beginning of) the class definition, +and "footer" is after the definition. Format of user code is like this: --- ----- header - ruby statement - ruby statement - ruby statement - ----- inner - ruby statement - : - : --- -If four '-' exist on line head, -racc treat it as beginning of user code block. -A name of user code must be one word. + + ---- header + ruby statement + ruby statement + ruby statement + + ---- inner + ruby statement + : + : + +If there are four '-' at line head, Racc treats this case as the beginning of a +user code block. + +The name of a user code block must be one word. diff --git a/rdoc/ja/grammar.ja.rdoc b/rdoc/ja/grammar.ja.rdoc index c366130e..8cbb1a39 100644 --- a/rdoc/ja/grammar.ja.rdoc +++ b/rdoc/ja/grammar.ja.rdoc @@ -248,10 +248,6 @@ options オプション オプション … -- 現在ここで使えるのは - * omit_action_call - -空のアクション呼び出しを省略する - * result_var 変数 result を使う diff --git a/sample/array.y b/sample/array.y index ce0590e6..2c365315 100644 --- a/sample/array.y +++ b/sample/array.y @@ -1,5 +1,3 @@ -# $Id$ -# # convert Array-like string into Ruby's Array. class ArrayParser diff --git a/sample/array2.y b/sample/array2.y index 639f7936..7932007b 100644 --- a/sample/array2.y +++ b/sample/array2.y @@ -1,7 +1,5 @@ -# $Id$ -# # Converting Array-like string into Ruby's Array, version 2. -# This grammer uses no_result_var. +# This grammar uses no_result_var. class ArrayParser2 options no_result_var diff --git a/sample/calc-ja.y b/sample/calc-ja.y index d6e3eed8..a1c11e93 100644 --- a/sample/calc-ja.y +++ b/sample/calc-ja.y @@ -1,5 +1,5 @@ -# $Id$ -# +# encoding: EUC-JP + # A simple calculator, version 2. # This file contains Japanese characters (encoding=EUC-JP). @@ -23,10 +23,8 @@ rule | NUMBER end ----- header -# $Id$ ---- inner - + def evaluate(str) @tokens = [] until str.empty? diff --git a/sample/calc.y b/sample/calc.y index 8d9c581d..655aecd8 100644 --- a/sample/calc.y +++ b/sample/calc.y @@ -1,5 +1,3 @@ -# $Id$ -# # Very simple calculater. class Calcp @@ -21,8 +19,6 @@ rule | NUMBER end ----- header -# $Id$ ---- inner def parse(str) diff --git a/sample/conflict.y b/sample/conflict.y index 28d7799d..04f6058c 100644 --- a/sample/conflict.y +++ b/sample/conflict.y @@ -1,7 +1,5 @@ -# $Id$ -# -# Example of conflicted grammer. -# This grammer contains 1 Shift/Reduce conflict and 1 Reduce/Reduce conflict. +# Example of conflicted grammar. +# This grammar contains 1 Shift/Reduce conflict and 1 Reduce/Reduce conflict. class A rule diff --git a/sample/hash.y b/sample/hash.y index bec25d61..56db0f4c 100644 --- a/sample/hash.y +++ b/sample/hash.y @@ -1,5 +1,3 @@ -# $Id$ -# # Converting Hash-like string into Ruby's Hash. class HashParser diff --git a/sample/lalr.y b/sample/lalr.y index 0566d6be..6279c845 100644 --- a/sample/lalr.y +++ b/sample/lalr.y @@ -1,6 +1,4 @@ -# $Id$ -# -# This is LALR grammer, and not LL/SLR. +# This is LALR grammar, and not LL/SLR. class A rule diff --git a/sample/lists.y b/sample/lists.y index 6ec9066c..208a0b00 100644 --- a/sample/lists.y +++ b/sample/lists.y @@ -1,5 +1,3 @@ -# $Id$ -# # Rules for verious lists. # This file is just an example, you cannot compile this file. diff --git a/sample/syntax.y b/sample/syntax.y index 6bef1e9c..fbdf1805 100644 --- a/sample/syntax.y +++ b/sample/syntax.y @@ -1,6 +1,4 @@ -# $Id$ -# -# Racc syntax checker. This grammer file generates +# Racc syntax checker. This grammar file generates # invalid ruby program, you cannot run this parser. class P @@ -14,7 +12,7 @@ class P left B preclow - options omit_action_call + options result_var start target rule diff --git a/sample/yyerr.y b/sample/yyerr.y index 99220e0a..2edf145d 100644 --- a/sample/yyerr.y +++ b/sample/yyerr.y @@ -1,6 +1,4 @@ -# $Id$ -# -# Test grammer file for error handling. +# Test grammar file for error handling. class A rule diff --git a/setup.rb b/setup.rb deleted file mode 100644 index 66271348..00000000 --- a/setup.rb +++ /dev/null @@ -1,1587 +0,0 @@ -# -# setup.rb -# -# Copyright (c) 2000-2006 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# - -unless Enumerable.method_defined?(:map) # Ruby 1.4.6 - module Enumerable - alias map collect - end -end - -unless File.respond_to?(:read) # Ruby 1.6 - def File.read(fname) - open(fname) {|f| - return f.read - } - end -end - -unless Errno.const_defined?(:ENOTEMPTY) # Windows? - module Errno - class ENOTEMPTY - # We do not raise this exception, implementation is not needed. - end - end -end - -def File.binread(fname) - open(fname, 'rb') {|f| - return f.read - } -end - -# for corrupted Windows' stat(2) -def File.dir?(path) - File.directory?((path[-1,1] == '/') ? path : path + '/') -end - - -class ConfigTable - - include Enumerable - - def initialize(rbconfig) - @rbconfig = rbconfig - @items = [] - @table = {} - # options - @install_prefix = nil - @config_opt = nil - @verbose = true - @no_harm = false - end - - attr_accessor :install_prefix - attr_accessor :config_opt - - attr_writer :verbose - - def verbose? - @verbose - end - - attr_writer :no_harm - - def no_harm? - @no_harm - end - - def [](key) - lookup(key).resolve(self) - end - - def []=(key, val) - lookup(key).set val - end - - def names - @items.map {|i| i.name } - end - - def each(&block) - @items.each(&block) - end - - def key?(name) - @table.key?(name) - end - - def lookup(name) - @table[name] or setup_rb_error "no such config item: #{name}" - end - - def add(item) - @items.push item - @table[item.name] = item - end - - def remove(name) - item = lookup(name) - @items.delete_if {|i| i.name == name } - @table.delete_if {|name, i| i.name == name } - item - end - - def load_script(path, inst = nil) - if File.file?(path) - MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path - end - end - - def savefile - '.config' - end - - def load_savefile - begin - File.foreach(savefile()) do |line| - k, v = *line.split(/=/, 2) - self[k] = v.strip - end - rescue Errno::ENOENT - setup_rb_error $!.message + "\n#{File.basename($0)} config first" - end - end - - def save - @items.each {|i| i.value } - File.open(savefile(), 'w') {|f| - @items.each do |i| - f.printf "%s=%s\n", i.name, i.value if i.value? and i.value - end - } - end - - def load_standard_entries - standard_entries(@rbconfig).each do |ent| - add ent - end - end - - def standard_entries(rbconfig) - c = rbconfig - - rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT']) - - major = c['MAJOR'].to_i - minor = c['MINOR'].to_i - teeny = c['TEENY'].to_i - version = "#{major}.#{minor}" - - # ruby ver. >= 1.4.4? - newpath_p = ((major >= 2) or - ((major == 1) and - ((minor >= 5) or - ((minor == 4) and (teeny >= 4))))) - - if c['rubylibdir'] - # V > 1.6.3 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = c['rubylibdir'] - librubyverarch = c['archdir'] - siteruby = c['sitedir'] - siterubyver = c['sitelibdir'] - siterubyverarch = c['sitearchdir'] - elsif newpath_p - # 1.4.4 <= V <= 1.6.3 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = "#{c['prefix']}/lib/ruby/#{version}" - librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" - siteruby = c['sitedir'] - siterubyver = "$siteruby/#{version}" - siterubyverarch = "$siterubyver/#{c['arch']}" - else - # V < 1.4.4 - libruby = "#{c['prefix']}/lib/ruby" - librubyver = "#{c['prefix']}/lib/ruby/#{version}" - librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" - siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby" - siterubyver = siteruby - siterubyverarch = "$siterubyver/#{c['arch']}" - end - parameterize = lambda {|path| - path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix') - } - - if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } - makeprog = arg.sub(/'/, '').split(/=/, 2)[1] - else - makeprog = 'make' - end - - [ - ExecItem.new('installdirs', 'std/site/home', - 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\ - {|val, table| - case val - when 'std' - table['rbdir'] = '$librubyver' - table['sodir'] = '$librubyverarch' - when 'site' - table['rbdir'] = '$siterubyver' - table['sodir'] = '$siterubyverarch' - when 'home' - setup_rb_error '$HOME was not set' unless ENV['HOME'] - table['prefix'] = ENV['HOME'] - table['rbdir'] = '$libdir/ruby' - table['sodir'] = '$libdir/ruby' - end - }, - PathItem.new('prefix', 'path', c['prefix'], - 'path prefix of target environment'), - PathItem.new('bindir', 'path', parameterize.call(c['bindir']), - 'the directory for commands'), - PathItem.new('libdir', 'path', parameterize.call(c['libdir']), - 'the directory for libraries'), - PathItem.new('datadir', 'path', parameterize.call(c['datadir']), - 'the directory for shared data'), - PathItem.new('mandir', 'path', parameterize.call(c['mandir']), - 'the directory for man pages'), - PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), - 'the directory for system configuration files'), - PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']), - 'the directory for local state data'), - PathItem.new('libruby', 'path', libruby, - 'the directory for ruby libraries'), - PathItem.new('librubyver', 'path', librubyver, - 'the directory for standard ruby libraries'), - PathItem.new('librubyverarch', 'path', librubyverarch, - 'the directory for standard ruby extensions'), - PathItem.new('siteruby', 'path', siteruby, - 'the directory for version-independent aux ruby libraries'), - PathItem.new('siterubyver', 'path', siterubyver, - 'the directory for aux ruby libraries'), - PathItem.new('siterubyverarch', 'path', siterubyverarch, - 'the directory for aux ruby binaries'), - PathItem.new('rbdir', 'path', '$siterubyver', - 'the directory for ruby scripts'), - PathItem.new('sodir', 'path', '$siterubyverarch', - 'the directory for ruby extentions'), - PathItem.new('rubypath', 'path', rubypath, - 'the path to set to #! line'), - ProgramItem.new('rubyprog', 'name', rubypath, - 'the ruby program using for installation'), - ProgramItem.new('makeprog', 'name', makeprog, - 'the make program to compile ruby extentions'), - SelectItem.new('shebang', 'all/ruby/never', 'ruby', - 'shebang line (#!) editing mode'), - BoolItem.new('without-ext', 'yes/no', 'no', - 'does not compile/install ruby extentions') - ] - end - private :standard_entries - - def load_multipackage_entries - multipackage_entries().each do |ent| - add ent - end - end - - def multipackage_entries - [ - PackageSelectionItem.new('with', 'name,name...', '', 'ALL', - 'package names that you want to install'), - PackageSelectionItem.new('without', 'name,name...', '', 'NONE', - 'package names that you do not want to install') - ] - end - private :multipackage_entries - - ALIASES = { - 'std-ruby' => 'librubyver', - 'stdruby' => 'librubyver', - 'rubylibdir' => 'librubyver', - 'archdir' => 'librubyverarch', - 'site-ruby-common' => 'siteruby', # For backward compatibility - 'site-ruby' => 'siterubyver', # For backward compatibility - 'bin-dir' => 'bindir', - 'bin-dir' => 'bindir', - 'rb-dir' => 'rbdir', - 'so-dir' => 'sodir', - 'data-dir' => 'datadir', - 'ruby-path' => 'rubypath', - 'ruby-prog' => 'rubyprog', - 'ruby' => 'rubyprog', - 'make-prog' => 'makeprog', - 'make' => 'makeprog' - } - - def fixup - ALIASES.each do |ali, name| - @table[ali] = @table[name] - end - end - - def options_re - /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/ - end - - def parse_opt(opt) - m = options_re().match(opt) or setup_rb_error "config: unknown option #{opt}" - m.to_a[1,2] - end - - def dllext - @rbconfig['DLEXT'] - end - - def value_config?(name) - lookup(name).value? - end - - class Item - def initialize(name, template, default, desc) - @name = name.freeze - @template = template - @value = default - @default = default - @description = desc - end - - attr_reader :name - attr_reader :description - - attr_accessor :default - alias help_default default - - def help_opt - "--#{@name}=#{@template}" - end - - def value? - true - end - - def value - @value - end - - def resolve(table) - @value.gsub(%r<\$([^/]+)>) { table[$1] } - end - - def set(val) - @value = check(val) - end - - private - - def check(val) - setup_rb_error "config: --#{name} requires argument" unless val - val - end - end - - class BoolItem < Item - def config_type - 'bool' - end - - def help_opt - "--#{@name}" - end - - private - - def check(val) - return 'yes' unless val - case val - when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes' - when /\An(o)?\z/i, /\Af(alse)\z/i then 'no' - else - setup_rb_error "config: --#{@name} accepts only yes/no for argument" - end - end - end - - class PathItem < Item - def config_type - 'path' - end - - private - - def check(path) - setup_rb_error "config: --#{@name} requires argument" unless path - path[0,1] == '$' ? path : File.expand_path(path) - end - end - - class ProgramItem < Item - def config_type - 'program' - end - end - - class SelectItem < Item - def initialize(name, selection, default, desc) - super - @ok = selection.split('/') - end - - def config_type - 'select' - end - - private - - def check(val) - unless @ok.include?(val.strip) - setup_rb_error "config: use --#{@name}=#{@template} (#{val})" - end - val.strip - end - end - - class ExecItem < Item - def initialize(name, selection, desc, &block) - super name, selection, nil, desc - @ok = selection.split('/') - @action = block - end - - def config_type - 'exec' - end - - def value? - false - end - - def resolve(table) - setup_rb_error "$#{name()} wrongly used as option value" - end - - undef set - - def evaluate(val, table) - v = val.strip.downcase - unless @ok.include?(v) - setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})" - end - @action.call v, table - end - end - - class PackageSelectionItem < Item - def initialize(name, template, default, help_default, desc) - super name, template, default, desc - @help_default = help_default - end - - attr_reader :help_default - - def config_type - 'package' - end - - private - - def check(val) - unless File.dir?("packages/#{val}") - setup_rb_error "config: no such package: #{val}" - end - val - end - end - - class MetaConfigEnvironment - def initialize(config, installer) - @config = config - @installer = installer - end - - def config_names - @config.names - end - - def config?(name) - @config.key?(name) - end - - def bool_config?(name) - @config.lookup(name).config_type == 'bool' - end - - def path_config?(name) - @config.lookup(name).config_type == 'path' - end - - def value_config?(name) - @config.lookup(name).config_type != 'exec' - end - - def add_config(item) - @config.add item - end - - def add_bool_config(name, default, desc) - @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) - end - - def add_path_config(name, default, desc) - @config.add PathItem.new(name, 'path', default, desc) - end - - def set_config_default(name, default) - @config.lookup(name).default = default - end - - def remove_config(name) - @config.remove(name) - end - - # For only multipackage - def packages - raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer - @installer.packages - end - - # For only multipackage - def declare_packages(list) - raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer - @installer.packages = list - end - end - -end # class ConfigTable - - -# This module requires: #verbose?, #no_harm? -module FileOperations - - def mkdir_p(dirname, prefix = nil) - dirname = prefix + File.expand_path(dirname) if prefix - $stderr.puts "mkdir -p #{dirname}" if verbose? - return if no_harm? - - # Does not check '/', it's too abnormal. - dirs = File.expand_path(dirname).split(%r<(?=/)>) - if /\A[a-z]:\z/i =~ dirs[0] - disk = dirs.shift - dirs[0] = disk + dirs[0] - end - dirs.each_index do |idx| - path = dirs[0..idx].join('') - Dir.mkdir path unless File.dir?(path) - end - end - - def rm_f(path) - $stderr.puts "rm -f #{path}" if verbose? - return if no_harm? - force_remove_file path - end - - def rm_rf(path) - $stderr.puts "rm -rf #{path}" if verbose? - return if no_harm? - remove_tree path - end - - def remove_tree(path) - if File.symlink?(path) - remove_file path - elsif File.dir?(path) - remove_tree0 path - else - force_remove_file path - end - end - - def remove_tree0(path) - Dir.foreach(path) do |ent| - next if ent == '.' - next if ent == '..' - entpath = "#{path}/#{ent}" - if File.symlink?(entpath) - remove_file entpath - elsif File.dir?(entpath) - remove_tree0 entpath - else - force_remove_file entpath - end - end - begin - Dir.rmdir path - rescue Errno::ENOTEMPTY - # directory may not be empty - end - end - - def move_file(src, dest) - force_remove_file dest - begin - File.rename src, dest - rescue - File.open(dest, 'wb') {|f| - f.write File.binread(src) - } - File.chmod File.stat(src).mode, dest - File.unlink src - end - end - - def force_remove_file(path) - begin - remove_file path - rescue - end - end - - def remove_file(path) - File.chmod 0777, path - File.unlink path - end - - def install(from, dest, mode, prefix = nil) - $stderr.puts "install #{from} #{dest}" if verbose? - return if no_harm? - - realdest = prefix ? prefix + File.expand_path(dest) : dest - realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) - str = File.binread(from) - if diff?(str, realdest) - verbose_off { - rm_f realdest if File.exist?(realdest) - } - File.open(realdest, 'wb') {|f| - f.write str - } - File.chmod mode, realdest - - File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| - if prefix - f.puts realdest.sub(prefix, '') - else - f.puts realdest - end - } - end - end - - def diff?(new_content, path) - return true unless File.exist?(path) - new_content != File.binread(path) - end - - def command(*args) - $stderr.puts args.join(' ') if verbose? - system(*args) or raise RuntimeError, - "system(#{args.map{|a| a.inspect }.join(' ')}) failed" - end - - def ruby(*args) - command config('rubyprog'), *args - end - - def make(task = nil) - command(*[config('makeprog'), task].compact) - end - - def extdir?(dir) - File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb") - end - - def files_of(dir) - Dir.open(dir) {|d| - return d.select {|ent| File.file?("#{dir}/#{ent}") } - } - end - - DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn ) - - def directories_of(dir) - Dir.open(dir) {|d| - return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT - } - end - -end - - -# This module requires: #srcdir_root, #objdir_root, #relpath -module HookScriptAPI - - def get_config(key) - @config[key] - end - - alias config get_config - - # obsolete: use metaconfig to change configuration - def set_config(key, val) - @config[key] = val - end - - # - # srcdir/objdir (works only in the package directory) - # - - def curr_srcdir - "#{srcdir_root()}/#{relpath()}" - end - - def curr_objdir - "#{objdir_root()}/#{relpath()}" - end - - def srcfile(path) - "#{curr_srcdir()}/#{path}" - end - - def srcexist?(path) - File.exist?(srcfile(path)) - end - - def srcdirectory?(path) - File.dir?(srcfile(path)) - end - - def srcfile?(path) - File.file?(srcfile(path)) - end - - def srcentries(path = '.') - Dir.open("#{curr_srcdir()}/#{path}") {|d| - return d.to_a - %w(. ..) - } - end - - def srcfiles(path = '.') - srcentries(path).select {|fname| - File.file?(File.join(curr_srcdir(), path, fname)) - } - end - - def srcdirectories(path = '.') - srcentries(path).select {|fname| - File.dir?(File.join(curr_srcdir(), path, fname)) - } - end - -end - - -class ToplevelInstaller - - Version = '3.4.1' - Copyright = 'Copyright (c) 2000-2006 Minero Aoki' - - TASKS = [ - [ 'all', 'do config, setup, then install' ], - [ 'config', 'saves your configurations' ], - [ 'show', 'shows current configuration' ], - [ 'setup', 'compiles ruby extentions and others' ], - [ 'install', 'installs files' ], - [ 'test', 'run all tests in test/' ], - [ 'clean', "does `make clean' for each extention" ], - [ 'distclean',"does `make distclean' for each extention" ] - ] - - def ToplevelInstaller.invoke - config = ConfigTable.new(load_rbconfig()) - config.load_standard_entries - config.load_multipackage_entries if multipackage? - config.fixup - klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller) - klass.new(File.dirname($0), config).invoke - end - - def ToplevelInstaller.multipackage? - File.dir?(File.dirname($0) + '/packages') - end - - def ToplevelInstaller.load_rbconfig - if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } - ARGV.delete(arg) - load File.expand_path(arg.split(/=/, 2)[1]) - $".push 'rbconfig.rb' - else - require 'rbconfig' - end - ::Config::CONFIG - end - - def initialize(ardir_root, config) - @ardir = File.expand_path(ardir_root) - @config = config - # cache - @valid_task_re = nil - end - - def config(key) - @config[key] - end - - def inspect - "#<#{self.class} #{__id__()}>" - end - - def invoke - run_metaconfigs - case task = parsearg_global() - when nil, 'all' - parsearg_config - init_installers - exec_config - exec_setup - exec_install - else - case task - when 'config', 'test' - ; - when 'clean', 'distclean' - @config.load_savefile if File.exist?(@config.savefile) - else - @config.load_savefile - end - __send__ "parsearg_#{task}" - init_installers - __send__ "exec_#{task}" - end - end - - def run_metaconfigs - @config.load_script "#{@ardir}/metaconfig" - end - - def init_installers - @installer = Installer.new(@config, @ardir, File.expand_path('.')) - end - - # - # Hook Script API bases - # - - def srcdir_root - @ardir - end - - def objdir_root - '.' - end - - def relpath - '.' - end - - # - # Option Parsing - # - - def parsearg_global - while arg = ARGV.shift - case arg - when /\A\w+\z/ - setup_rb_error "invalid task: #{arg}" unless valid_task?(arg) - return arg - when '-q', '--quiet' - @config.verbose = false - when '--verbose' - @config.verbose = true - when '--help' - print_usage $stdout - exit 0 - when '--version' - puts "#{File.basename($0)} version #{Version}" - exit 0 - when '--copyright' - puts Copyright - exit 0 - else - setup_rb_error "unknown global option '#{arg}'" - end - end - nil - end - - def valid_task?(t) - valid_task_re() =~ t - end - - def valid_task_re - @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/ - end - - def parsearg_no_options - unless ARGV.empty? - task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1) - setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}" - end - end - - alias parsearg_show parsearg_no_options - alias parsearg_setup parsearg_no_options - alias parsearg_test parsearg_no_options - alias parsearg_clean parsearg_no_options - alias parsearg_distclean parsearg_no_options - - def parsearg_config - evalopt = [] - set = [] - @config.config_opt = [] - while i = ARGV.shift - if /\A--?\z/ =~ i - @config.config_opt = ARGV.dup - break - end - name, value = *@config.parse_opt(i) - if @config.value_config?(name) - @config[name] = value - else - evalopt.push [name, value] - end - set.push name - end - evalopt.each do |name, value| - @config.lookup(name).evaluate value, @config - end - # Check if configuration is valid - set.each do |n| - @config[n] if @config.value_config?(n) - end - end - - def parsearg_install - @config.no_harm = false - @config.install_prefix = '' - while a = ARGV.shift - case a - when '--no-harm' - @config.no_harm = true - when /\A--prefix=/ - path = a.split(/=/, 2)[1] - path = File.expand_path(path) unless path[0,1] == '/' - @config.install_prefix = path - else - setup_rb_error "install: unknown option #{a}" - end - end - end - - def print_usage(out) - out.puts 'Typical Installation Procedure:' - out.puts " $ ruby #{File.basename $0} config" - out.puts " $ ruby #{File.basename $0} setup" - out.puts " # ruby #{File.basename $0} install (may require root privilege)" - out.puts - out.puts 'Detailed Usage:' - out.puts " ruby #{File.basename $0} " - out.puts " ruby #{File.basename $0} [] []" - - fmt = " %-24s %s\n" - out.puts - out.puts 'Global options:' - out.printf fmt, '-q,--quiet', 'suppress message outputs' - out.printf fmt, ' --verbose', 'output messages verbosely' - out.printf fmt, ' --help', 'print this message' - out.printf fmt, ' --version', 'print version and quit' - out.printf fmt, ' --copyright', 'print copyright and quit' - out.puts - out.puts 'Tasks:' - TASKS.each do |name, desc| - out.printf fmt, name, desc - end - - fmt = " %-24s %s [%s]\n" - out.puts - out.puts 'Options for CONFIG or ALL:' - @config.each do |item| - out.printf fmt, item.help_opt, item.description, item.help_default - end - out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" - out.puts - out.puts 'Options for INSTALL:' - out.printf fmt, '--no-harm', 'only display what to do if given', 'off' - out.printf fmt, '--prefix=path', 'install path prefix', '' - out.puts - end - - # - # Task Handlers - # - - def exec_config - @installer.exec_config - @config.save # must be final - end - - def exec_setup - @installer.exec_setup - end - - def exec_install - @installer.exec_install - end - - def exec_test - @installer.exec_test - end - - def exec_show - @config.each do |i| - printf "%-20s %s\n", i.name, i.value if i.value? - end - end - - def exec_clean - @installer.exec_clean - end - - def exec_distclean - @installer.exec_distclean - end - -end # class ToplevelInstaller - - -class ToplevelInstallerMulti < ToplevelInstaller - - include FileOperations - - def initialize(ardir_root, config) - super - @packages = directories_of("#{@ardir}/packages") - raise 'no package exists' if @packages.empty? - @root_installer = Installer.new(@config, @ardir, File.expand_path('.')) - end - - def run_metaconfigs - @config.load_script "#{@ardir}/metaconfig", self - @packages.each do |name| - @config.load_script "#{@ardir}/packages/#{name}/metaconfig" - end - end - - attr_reader :packages - - def packages=(list) - raise 'package list is empty' if list.empty? - list.each do |name| - raise "directory packages/#{name} does not exist"\ - unless File.dir?("#{@ardir}/packages/#{name}") - end - @packages = list - end - - def init_installers - @installers = {} - @packages.each do |pack| - @installers[pack] = Installer.new(@config, - "#{@ardir}/packages/#{pack}", - "packages/#{pack}") - end - with = extract_selection(config('with')) - without = extract_selection(config('without')) - @selected = @installers.keys.select {|name| - (with.empty? or with.include?(name)) \ - and not without.include?(name) - } - end - - def extract_selection(list) - a = list.split(/,/) - a.each do |name| - setup_rb_error "no such package: #{name}" unless @installers.key?(name) - end - a - end - - def print_usage(f) - super - f.puts 'Inluded packages:' - f.puts ' ' + @packages.sort.join(' ') - f.puts - end - - # - # Task Handlers - # - - def exec_config - run_hook 'pre-config' - each_selected_installers {|inst| inst.exec_config } - run_hook 'post-config' - @config.save # must be final - end - - def exec_setup - run_hook 'pre-setup' - each_selected_installers {|inst| inst.exec_setup } - run_hook 'post-setup' - end - - def exec_install - run_hook 'pre-install' - each_selected_installers {|inst| inst.exec_install } - run_hook 'post-install' - end - - def exec_test - run_hook 'pre-test' - each_selected_installers {|inst| inst.exec_test } - run_hook 'post-test' - end - - def exec_clean - rm_f @config.savefile - run_hook 'pre-clean' - each_selected_installers {|inst| inst.exec_clean } - run_hook 'post-clean' - end - - def exec_distclean - rm_f @config.savefile - run_hook 'pre-distclean' - each_selected_installers {|inst| inst.exec_distclean } - run_hook 'post-distclean' - end - - # - # lib - # - - def each_selected_installers - Dir.mkdir 'packages' unless File.dir?('packages') - @selected.each do |pack| - $stderr.puts "Processing the package `#{pack}' ..." if verbose? - Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") - Dir.chdir "packages/#{pack}" - yield @installers[pack] - Dir.chdir '../..' - end - end - - def run_hook(id) - @root_installer.run_hook id - end - - # module FileOperations requires this - def verbose? - @config.verbose? - end - - # module FileOperations requires this - def no_harm? - @config.no_harm? - end - -end # class ToplevelInstallerMulti - - -class Installer - - FILETYPES = %w( bin lib ext data conf man ) - - include FileOperations - include HookScriptAPI - - def initialize(config, srcroot, objroot) - @config = config - @srcdir = File.expand_path(srcroot) - @objdir = File.expand_path(objroot) - @currdir = '.' - end - - def inspect - "#<#{self.class} #{File.basename(@srcdir)}>" - end - - def noop(rel) - end - - # - # Hook Script API base methods - # - - def srcdir_root - @srcdir - end - - def objdir_root - @objdir - end - - def relpath - @currdir - end - - # - # Config Access - # - - # module FileOperations requires this - def verbose? - @config.verbose? - end - - # module FileOperations requires this - def no_harm? - @config.no_harm? - end - - def verbose_off - begin - save, @config.verbose = @config.verbose?, false - yield - ensure - @config.verbose = save - end - end - - # - # TASK config - # - - def exec_config - exec_task_traverse 'config' - end - - alias config_dir_bin noop - alias config_dir_lib noop - - def config_dir_ext(rel) - extconf if extdir?(curr_srcdir()) - end - - alias config_dir_data noop - alias config_dir_conf noop - alias config_dir_man noop - - def extconf - ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt - end - - # - # TASK setup - # - - def exec_setup - exec_task_traverse 'setup' - end - - def setup_dir_bin(rel) - files_of(curr_srcdir()).each do |fname| - update_shebang_line "#{curr_srcdir()}/#{fname}" - end - end - - alias setup_dir_lib noop - - def setup_dir_ext(rel) - make if extdir?(curr_srcdir()) - end - - alias setup_dir_data noop - alias setup_dir_conf noop - alias setup_dir_man noop - - def update_shebang_line(path) - return if no_harm? - return if config('shebang') == 'never' - old = Shebang.load(path) - if old - $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1 - new = new_shebang(old) - return if new.to_s == old.to_s - else - return unless config('shebang') == 'all' - new = Shebang.new(config('rubypath')) - end - $stderr.puts "updating shebang: #{File.basename(path)}" if verbose? - open_atomic_writer(path) {|output| - File.open(path, 'rb') {|f| - f.gets if old # discard - output.puts new.to_s - output.print f.read - } - } - end - - def new_shebang(old) - if /\Aruby/ =~ File.basename(old.cmd) - Shebang.new(config('rubypath'), old.args) - elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby' - Shebang.new(config('rubypath'), old.args[1..-1]) - else - return old unless config('shebang') == 'all' - Shebang.new(config('rubypath')) - end - end - - def open_atomic_writer(path, &block) - tmpfile = File.basename(path) + '.tmp' - begin - File.open(tmpfile, 'wb', &block) - File.rename tmpfile, File.basename(path) - ensure - File.unlink tmpfile if File.exist?(tmpfile) - end - end - - class Shebang - def Shebang.load(path) - line = nil - File.open(path) {|f| - line = f.gets - } - return nil unless /\A#!/ =~ line - parse(line) - end - - def Shebang.parse(line) - cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ') - new(cmd, args) - end - - def initialize(cmd, args = []) - @cmd = cmd - @args = args - end - - attr_reader :cmd - attr_reader :args - - def to_s - "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}") - end - end - - # - # TASK install - # - - def exec_install - rm_f 'InstalledFiles' - exec_task_traverse 'install' - end - - def install_dir_bin(rel) - install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755 - end - - def install_dir_lib(rel) - install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644 - end - - def install_dir_ext(rel) - return unless extdir?(curr_srcdir()) - install_files rubyextentions('.'), - "#{config('sodir')}/#{File.dirname(rel)}", - 0555 - end - - def install_dir_data(rel) - install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644 - end - - def install_dir_conf(rel) - # FIXME: should not remove current config files - # (rename previous file to .old/.org) - install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644 - end - - def install_dir_man(rel) - install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644 - end - - def install_files(list, dest, mode) - mkdir_p dest, @config.install_prefix - list.each do |fname| - install fname, dest, mode, @config.install_prefix - end - end - - def libfiles - glob_reject(%w(*.y *.output), targetfiles()) - end - - def rubyextentions(dir) - ents = glob_select("*.#{@config.dllext}", targetfiles()) - if ents.empty? - setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" - end - ents - end - - def targetfiles - mapdir(existfiles() - hookfiles()) - end - - def mapdir(ents) - ents.map {|ent| - if File.exist?(ent) - then ent # objdir - else "#{curr_srcdir()}/#{ent}" # srcdir - end - } - end - - # picked up many entries from cvs-1.11.1/src/ignore.c - JUNK_FILES = %w( - core RCSLOG tags TAGS .make.state - .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb - *~ *.old *.bak *.BAK *.orig *.rej _$* *$ - - *.org *.in .* - ) - - def existfiles - glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.'))) - end - - def hookfiles - %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| - %w( config setup install clean distclean ).map {|t| sprintf(fmt, t) } - }.flatten - end - - def glob_select(pat, ents) - re = globs2re([pat]) - ents.select {|ent| re =~ ent } - end - - def glob_reject(pats, ents) - re = globs2re(pats) - ents.reject {|ent| re =~ ent } - end - - GLOB2REGEX = { - '.' => '\.', - '$' => '\$', - '#' => '\#', - '*' => '.*' - } - - def globs2re(pats) - /\A(?:#{ - pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|') - })\z/ - end - - # - # TASK test - # - - TESTDIR = 'test' - - def exec_test - unless File.directory?('test') - $stderr.puts 'no test in this package' if verbose? - return - end - $stderr.puts 'Running tests...' if verbose? - begin - require 'test/unit' - rescue LoadError - setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.' - end - runner = Test::Unit::AutoRunner.new(true) - runner.to_run << TESTDIR - runner.run - end - - # - # TASK clean - # - - def exec_clean - exec_task_traverse 'clean' - rm_f @config.savefile - rm_f 'InstalledFiles' - end - - alias clean_dir_bin noop - alias clean_dir_lib noop - alias clean_dir_data noop - alias clean_dir_conf noop - alias clean_dir_man noop - - def clean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'clean' if File.file?('Makefile') - end - - # - # TASK distclean - # - - def exec_distclean - exec_task_traverse 'distclean' - rm_f @config.savefile - rm_f 'InstalledFiles' - end - - alias distclean_dir_bin noop - alias distclean_dir_lib noop - - def distclean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'distclean' if File.file?('Makefile') - end - - alias distclean_dir_data noop - alias distclean_dir_conf noop - alias distclean_dir_man noop - - # - # Traversing - # - - def exec_task_traverse(task) - run_hook "pre-#{task}" - FILETYPES.each do |type| - if type == 'ext' and config('without-ext') == 'yes' - $stderr.puts 'skipping ext/* by user option' if verbose? - next - end - traverse task, type, "#{task}_dir_#{type}" - end - run_hook "post-#{task}" - end - - def traverse(task, rel, mid) - dive_into(rel) { - run_hook "pre-#{task}" - __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') - directories_of(curr_srcdir()).each do |d| - traverse task, "#{rel}/#{d}", mid - end - run_hook "post-#{task}" - } - end - - def dive_into(rel) - return unless File.dir?("#{@srcdir}/#{rel}") - - dir = File.basename(rel) - Dir.mkdir dir unless File.dir?(dir) - prevdir = Dir.pwd - Dir.chdir dir - $stderr.puts '---> ' + rel if verbose? - @currdir = rel - yield - Dir.chdir prevdir - $stderr.puts '<--- ' + rel if verbose? - @currdir = File.dirname(rel) - end - - def run_hook(id) - path = [ "#{curr_srcdir()}/#{id}", - "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) } - return unless path - $stderr.puts "invoking hook script #{path}" if verbose? - begin - instance_eval File.read(path), path, 1 - rescue - raise if $DEBUG - setup_rb_error "hook #{path} failed:\n" + $!.message - end - end - -end # class Installer - - -class SetupError < StandardError; end - -def setup_rb_error(msg) - raise SetupError, msg -end - -if $0 == __FILE__ - begin - ToplevelInstaller.invoke - rescue SetupError - raise if $DEBUG - $stderr.puts $!.message - $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." - exit 1 - end -end diff --git a/tasks/doc.rb b/tasks/doc.rb deleted file mode 100644 index 73eaab52..00000000 --- a/tasks/doc.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'rake/rdoctask' - -Rake::RDocTask.new(:docs) do |rd| - rd.main = "README.en.rdoc" - rd.rdoc_files.include(SPEC.files.find_all { |file_name| - file_name =~ /^(bin|lib|ext)/ || file_name !~ /\// - }) - - title = "#{SPEC.name}-#{SPEC.version} Documentation" - - rd.options << "-t #{title}" -end diff --git a/tasks/email.rb b/tasks/email.rb deleted file mode 100644 index 8ba58d16..00000000 --- a/tasks/email.rb +++ /dev/null @@ -1,55 +0,0 @@ -class EmailTask - def initialize language, readme, changelog - @language = language - @readme = readme - @changelog = changelog - @languages = { - :en => { - :release => 'release', - :released => 'has been released', - }, - :ja => { - :release => 'リリース', - :released => 'はリリースしました', - } - } - define_tasks - end - - private - def define_tasks - namespace :email do - task @language do - subject = "#{SPEC.name} #{SPEC.version} #{@languages[@language][:release]}" - title = "#{SPEC.name} #{SPEC.version} #{@languages[@language][:released]}!" - readme = Hash[*(File.read(@readme).split(/^(=+ .*)$/)[1..-1])] - description = readme[readme.keys.find { |x| x =~ /description/i }] - description = description.split(/\n\n+/).find { |x| - x.length > 0 - }.gsub(/^\s*/, '') - urls = readme[readme.keys.find { |x| x =~ /#{SPEC.name}/i }] - urls = urls.strip.gsub(/\*\s/, '').split(/\n/).map { |s| "* <#{s}>" } - File.open("email.#{@language}.txt", "wb") { |file| - file.puts(<<-eomail) -Subject: [ANN] #{subject} - -#{title} - -#{urls.join("\n")} - -#{description} - -Changes: - -#{File.read(@changelog).split(/^(===.*)/)[1..2].join.strip.gsub(/=/, '#')} - -#{urls.join("\n")} -eomail - } - end - end - end -end - -EmailTask.new(:en, 'README.en.rdoc', 'doc/en/NEWS.en.rdoc') -EmailTask.new(:ja, 'README.ja.rdoc', 'doc/ja/NEWS.ja.rdoc') diff --git a/test/assets/badprec1.y b/test/assets/badprec1.y new file mode 100644 index 00000000..1ff0823e --- /dev/null +++ b/test/assets/badprec1.y @@ -0,0 +1,11 @@ +class A + +token A B C + +rule +targ : A B =blah + | blah + +blah: A B + +end diff --git a/test/assets/badprec2.y b/test/assets/badprec2.y new file mode 100644 index 00000000..1f977c30 --- /dev/null +++ b/test/assets/badprec2.y @@ -0,0 +1,16 @@ +class A + +prechigh + left blah + nonassoc A B C +preclow + +token A B C + +rule +targ : A B + | blah + +blah: B C + +end diff --git a/test/assets/badrule1.y b/test/assets/badrule1.y new file mode 100644 index 00000000..7696634f --- /dev/null +++ b/test/assets/badrule1.y @@ -0,0 +1,4 @@ +class A +rule + 'string': a b c +end diff --git a/test/assets/badrule2.y b/test/assets/badrule2.y new file mode 100644 index 00000000..8f79f3e6 --- /dev/null +++ b/test/assets/badrule2.y @@ -0,0 +1,7 @@ +class A +token A B + +rule + A : 'hello' + B : 'goodbye' +end diff --git a/test/assets/badrule3.y b/test/assets/badrule3.y new file mode 100644 index 00000000..e1ef3eb8 --- /dev/null +++ b/test/assets/badrule3.y @@ -0,0 +1,5 @@ +class A +rule + A : a b error + error: a b +end diff --git a/test/assets/badrule4.y b/test/assets/badrule4.y new file mode 100644 index 00000000..41593ef0 --- /dev/null +++ b/test/assets/badrule4.y @@ -0,0 +1,5 @@ +class A +rule + A : a { puts 'hello' } b c + | a b { puts 'hello' } c +end diff --git a/test/assets/badsyntax.y b/test/assets/badsyntax.y new file mode 100644 index 00000000..2541012c --- /dev/null +++ b/test/assets/badsyntax.y @@ -0,0 +1,6 @@ +class A +rule + start : A B C { + }}} + } +end diff --git a/test/bench.y b/test/assets/bench.y similarity index 100% rename from test/bench.y rename to test/assets/bench.y diff --git a/test/assets/cadenza.y b/test/assets/cadenza.y new file mode 100644 index 00000000..1940ead2 --- /dev/null +++ b/test/assets/cadenza.y @@ -0,0 +1,170 @@ +# This grammar is released under an MIT license +# Author: William Howard (http://github.com/whoward) +# Source: https://github.com/whoward/cadenza/blob/master/src/cadenza.y + +class Cadenza::RaccParser + +/* expect this many shift/reduce conflicts */ +expect 37 + +rule + target + : document + | /* none */ { result = nil } + ; + + parameter_list + : logical_expression { result = [val[0]] } + | parameter_list ',' logical_expression { result = val[0].push(val[2]) } + ; + + /* this has a shift/reduce conflict but since Racc will shift in this case it is the correct behavior */ + primary_expression + : IDENTIFIER { result = VariableNode.new(val[0].value) } + | IDENTIFIER parameter_list { result = VariableNode.new(val[0].value, val[1]) } + | INTEGER { result = ConstantNode.new(val[0].value) } + | REAL { result = ConstantNode.new(val[0].value) } + | STRING { result = ConstantNode.new(val[0].value) } + | '(' filtered_expression ')' { result = val[1] } + ; + + multiplicative_expression + : primary_expression + | multiplicative_expression '*' primary_expression { result = OperationNode.new(val[0], "*", val[2]) } + | multiplicative_expression '/' primary_expression { result = OperationNode.new(val[0], "/", val[2]) } + ; + + additive_expression + : multiplicative_expression + | additive_expression '+' multiplicative_expression { result = OperationNode.new(val[0], "+", val[2]) } + | additive_expression '-' multiplicative_expression { result = OperationNode.new(val[0], "-", val[2]) } + ; + + boolean_expression + : additive_expression + | boolean_expression OP_EQ additive_expression { result = OperationNode.new(val[0], "==", val[2]) } + | boolean_expression OP_NEQ additive_expression { result = OperationNode.new(val[0], "!=", val[2]) } + | boolean_expression OP_LEQ additive_expression { result = OperationNode.new(val[0], "<=", val[2]) } + | boolean_expression OP_GEQ additive_expression { result = OperationNode.new(val[0], ">=", val[2]) } + | boolean_expression '>' additive_expression { result = OperationNode.new(val[0], ">", val[2]) } + | boolean_expression '<' additive_expression { result = OperationNode.new(val[0], "<", val[2]) } + ; + + inverse_expression + : boolean_expression + | NOT boolean_expression { result = BooleanInverseNode.new(val[1]) } + ; + + logical_expression + : inverse_expression + | logical_expression AND inverse_expression { result = OperationNode.new(val[0], "and", val[2]) } + | logical_expression OR inverse_expression { result = OperationNode.new(val[0], "or", val[2]) } + ; + + filter + : IDENTIFIER { result = FilterNode.new(val[0].value) } + | IDENTIFIER ':' parameter_list { result = FilterNode.new(val[0].value, val[2]) } + ; + + filter_list + : filter { result = [val[0]] } + | filter_list '|' filter { result = val[0].push(val[2]) } + ; + + filtered_expression + : logical_expression + | logical_expression '|' filter_list { result = FilteredValueNode.new(val[0], val[2]) } + ; + + inject_statement + : VAR_OPEN filtered_expression VAR_CLOSE { result = val[1] } + ; + + if_tag + : STMT_OPEN IF logical_expression STMT_CLOSE { open_scope!; result = val[2] } + | STMT_OPEN UNLESS logical_expression STMT_CLOSE { open_scope!; result = BooleanInverseNode.new(val[2]) } + ; + + else_tag + : STMT_OPEN ELSE STMT_CLOSE { result = close_scope!; open_scope! } + ; + + end_if_tag + : STMT_OPEN ENDIF STMT_CLOSE { result = close_scope! } + | STMT_OPEN ENDUNLESS STMT_CLOSE { result = close_scope! } + ; + + if_block + : if_tag end_if_tag { result = IfNode.new(val[0], val[1]) } + | if_tag document end_if_tag { result = IfNode.new(val[0], val[2]) } + | if_tag else_tag document end_if_tag { result = IfNode.new(val[0], val[1], val[3]) } + | if_tag document else_tag end_if_tag { result = IfNode.new(val[0], val[2], val[3]) } + | if_tag document else_tag document end_if_tag { result = IfNode.new(val[0], val[2], val[4]) } + ; + + for_tag + : STMT_OPEN FOR IDENTIFIER IN filtered_expression STMT_CLOSE { open_scope!; result = [val[2].value, val[4]] } + ; + + end_for_tag + : STMT_OPEN ENDFOR STMT_CLOSE { result = close_scope! } + ; + + /* this has a shift/reduce conflict but since Racc will shift in this case it is the correct behavior */ + for_block + : for_tag end_for_tag { result = ForNode.new(VariableNode.new(val[0].first), val[0].last, val[1]) } + | for_tag document end_for_tag { result = ForNode.new(VariableNode.new(val[0].first), val[0].last, val[2]) } + ; + + block_tag + : STMT_OPEN BLOCK IDENTIFIER STMT_CLOSE { result = open_block_scope!(val[2].value) } + ; + + end_block_tag + : STMT_OPEN ENDBLOCK STMT_CLOSE { result = close_block_scope! } + ; + + /* this has a shift/reduce conflict but since Racc will shift in this case it is the correct behavior */ + block_block + : block_tag end_block_tag { result = BlockNode.new(val[0], val[1]) } + | block_tag document end_block_tag { result = BlockNode.new(val[0], val[2]) } + ; + + generic_block_tag + : STMT_OPEN IDENTIFIER STMT_CLOSE { open_scope!; result = [val[1].value, []] } + | STMT_OPEN IDENTIFIER parameter_list STMT_CLOSE { open_scope!; result = [val[1].value, val[2]] } + ; + + end_generic_block_tag + : STMT_OPEN END STMT_CLOSE { result = close_scope! } + ; + + generic_block + : generic_block_tag document end_generic_block_tag { result = GenericBlockNode.new(val[0].first, val[2], val[0].last) } + ; + + extends_statement + : STMT_OPEN EXTENDS STRING STMT_CLOSE { result = val[2].value } + | STMT_OPEN EXTENDS IDENTIFIER STMT_CLOSE { result = VariableNode.new(val[2].value) } + ; + + document_component + : TEXT_BLOCK { result = TextNode.new(val[0].value) } + | inject_statement + | if_block + | for_block + | generic_block + | block_block + ; + + document + : document_component { push val[0] } + | document document_component { push val[1] } + | extends_statement { document.extends = val[0] } + | document extends_statement { document.extends = val[1] } + ; + +---- header ---- +# racc_parser.rb : generated by racc + +---- inner ---- diff --git a/test/assets/calc-ja.y b/test/assets/calc-ja.y new file mode 100644 index 00000000..a1c11e93 --- /dev/null +++ b/test/assets/calc-ja.y @@ -0,0 +1,64 @@ +# encoding: EUC-JP + +# A simple calculator, version 2. +# This file contains Japanese characters (encoding=EUC-JP). + +class Calculator2 + prechigh + nonassoc UMINUS + left '*' '/' + left '+' '-' + preclow + options no_result_var +rule + target : exp + | /* none */ { 0 } + + exp : exp '+' exp { val[0] + val[2] } + | exp '-' exp { val[0] - val[2] } + | exp '*' exp { val[0] * val[2] } + | exp '/' exp { val[0] / val[2] } + | '(' exp ')' { val[1] } + | '-' NUMBER =UMINUS { -(val[1]) } + | NUMBER +end + +---- inner + + def evaluate(str) + @tokens = [] + until str.empty? + case str + when /\A\s+/ + ; + when /\A\d+/ + @tokens.push [:NUMBER, $&.to_i] + when /\A.|\n/ + s = $& + @tokens.push [s, s] + end + str = $' + end + @tokens.push [false, '$'] + do_parse + end + + def next_token + @tokens.shift + end + +---- footer + +puts 'Ķ 2 浡' +puts 'Q ǽλޤ' +calc = Calculator2.new +while true + print '>>> '; $stdout.flush + str = $stdin.gets.strip + break if /q/i =~ str + begin + p calc.evaluate(str) + rescue ParseError + puts 'parse error' + end +end diff --git a/test/assets/cast.y b/test/assets/cast.y new file mode 100644 index 00000000..d180c09e --- /dev/null +++ b/test/assets/cast.y @@ -0,0 +1,926 @@ +# The MIT License +# +# Copyright (c) George Ogata +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +class C::Parser +# shift/reduce conflict on "if (c) if (c) ; else ; else ;" +expect 1 +rule + +# A.2.4 External definitions + +# Returns TranslationUnit +translation_unit + : external_declaration {result = TranslationUnit.new_at(val[0].pos, NodeChain[val[0]])} + | translation_unit external_declaration {result = val[0]; result.entities << val[1]} + +# Returns Declaration|FunctionDef +external_declaration + : function_definition {result = val[0]} + | declaration {result = val[0]} + +# Returns FunctionDef +function_definition + : declaration_specifiers declarator declaration_list compound_statement {result = make_function_def(val[0][0], val[0][1], val[1], val[2], val[3])} + | declaration_specifiers declarator compound_statement {result = make_function_def(val[0][0], val[0][1], val[1], nil , val[2])} + +# Returns [Declaration] +declaration_list + : declaration {result = [val[0]]} + | declaration_list declaration {result = val[0] << val[1]} + +# A.2.3 Statements + +# Returns Statement +statement + : labeled_statement {result = val[0]} + | compound_statement {result = val[0]} + | expression_statement {result = val[0]} + | selection_statement {result = val[0]} + | iteration_statement {result = val[0]} + | jump_statement {result = val[0]} + +# Returns Statement +labeled_statement + : identifier COLON statement {val[2].labels.unshift(PlainLabel.new_at(val[0].pos, val[0].val)); result = val[2]} + | CASE constant_expression COLON statement {val[3].labels.unshift(Case .new_at(val[0].pos, val[1] )); result = val[3]} + | DEFAULT COLON statement {val[2].labels.unshift(Default .new_at(val[0].pos )); result = val[2]} + # type names can also be used as labels + | typedef_name COLON statement {val[2].labels.unshift(PlainLabel.new_at(val[0].pos, val[0].name)); result = val[2]} + +# Returns Block +compound_statement + : LBRACE block_item_list RBRACE {result = Block.new_at(val[0].pos, val[1])} + | LBRACE RBRACE {result = Block.new_at(val[0].pos )} + +# Returns NodeChain[Declaration|Statement] +block_item_list + : block_item {result = NodeChain[val[0]]} + | block_item_list block_item {result = val[0] << val[1]} + +# Returns Declaration|Statement +block_item + : declaration {result = val[0]} + | statement {result = val[0]} + +# Returns ExpressionStatement +expression_statement + : expression SEMICOLON {result = ExpressionStatement.new_at(val[0].pos, val[0])} + | SEMICOLON {result = ExpressionStatement.new_at(val[0].pos )} + +# Returns Statement +selection_statement + : IF LPAREN expression RPAREN statement {result = If .new_at(val[0].pos, val[2], val[4] )} + | IF LPAREN expression RPAREN statement ELSE statement {result = If .new_at(val[0].pos, val[2], val[4], val[6])} + | SWITCH LPAREN expression RPAREN statement {result = Switch.new_at(val[0].pos, val[2], val[4] )} + +# Returns Statement +iteration_statement + : WHILE LPAREN expression RPAREN statement {result = While.new_at(val[0].pos, val[2], val[4] )} + | DO statement WHILE LPAREN expression RPAREN SEMICOLON {result = While.new_at(val[0].pos, val[4], val[1], :do => true )} + | FOR LPAREN expression SEMICOLON expression SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], val[4], val[6], val[8])} + | FOR LPAREN expression SEMICOLON expression SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], val[4], nil , val[7])} + | FOR LPAREN expression SEMICOLON SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , val[5], val[7])} + | FOR LPAREN expression SEMICOLON SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , nil , val[6])} + | FOR LPAREN SEMICOLON expression SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, nil , val[3], val[5], val[7])} + | FOR LPAREN SEMICOLON expression SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, nil , val[3], nil , val[6])} + | FOR LPAREN SEMICOLON SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, nil , nil , val[4], val[6])} + | FOR LPAREN SEMICOLON SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, nil , nil , nil , val[5])} + | FOR LPAREN declaration expression SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], val[3], val[5], val[7])} + | FOR LPAREN declaration expression SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], val[3], nil , val[6])} + | FOR LPAREN declaration SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , val[4], val[6])} + | FOR LPAREN declaration SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , nil , val[5])} + +# Returns Statement +jump_statement + : GOTO identifier SEMICOLON {result = Goto .new_at(val[0].pos, val[1].val)} + | CONTINUE SEMICOLON {result = Continue.new_at(val[0].pos )} + | BREAK SEMICOLON {result = Break .new_at(val[0].pos )} + | RETURN expression SEMICOLON {result = Return .new_at(val[0].pos, val[1] )} + | RETURN SEMICOLON {result = Return .new_at(val[0].pos )} + # type names can also be used as labels + | GOTO typedef_name SEMICOLON {result = Goto .new_at(val[0].pos, val[1].name)} + +# A.2.2 Declarations + +# Returns Declaration +declaration + : declaration_specifiers init_declarator_list SEMICOLON {result = make_declaration(val[0][0], val[0][1], val[1])} + | declaration_specifiers SEMICOLON {result = make_declaration(val[0][0], val[0][1], NodeArray[])} + +# Returns {Pos, [Symbol]} +declaration_specifiers + : storage_class_specifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]} + | storage_class_specifier {result = [val[0][0], [val[0][1]]]} + | type_specifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]} + | type_specifier {result = [val[0][0], [val[0][1]]]} + | type_qualifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]} + | type_qualifier {result = [val[0][0], [val[0][1]]]} + | function_specifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]} + | function_specifier {result = [val[0][0], [val[0][1]]]} + +# Returns NodeArray[Declarator] +init_declarator_list + : init_declarator {result = NodeArray[val[0]]} + | init_declarator_list COMMA init_declarator {result = val[0] << val[2]} + +# Returns Declarator +init_declarator + : declarator {result = val[0]} + | declarator EQ initializer {val[0].init = val[2]; result = val[0]} + +# Returns [Pos, Symbol] +storage_class_specifier + : TYPEDEF {result = [val[0].pos, :typedef ]} + | EXTERN {result = [val[0].pos, :extern ]} + | STATIC {result = [val[0].pos, :static ]} + | AUTO {result = [val[0].pos, :auto ]} + | REGISTER {result = [val[0].pos, :register]} + +# Returns [Pos, Type|Symbol] +type_specifier + : VOID {result = [val[0].pos, :void ]} + | CHAR {result = [val[0].pos, :char ]} + | SHORT {result = [val[0].pos, :short ]} + | INT {result = [val[0].pos, :int ]} + | LONG {result = [val[0].pos, :long ]} + | FLOAT {result = [val[0].pos, :float ]} + | DOUBLE {result = [val[0].pos, :double ]} + | SIGNED {result = [val[0].pos, :signed ]} + | UNSIGNED {result = [val[0].pos, :unsigned ]} + | BOOL {result = [val[0].pos, :_Bool ]} + | COMPLEX {result = [val[0].pos, :_Complex ]} + | IMAGINARY {result = [val[0].pos, :_Imaginary]} + | struct_or_union_specifier {result = [val[0].pos, val[0] ]} + | enum_specifier {result = [val[0].pos, val[0] ]} + | typedef_name {result = [val[0].pos, val[0] ]} + +# Returns Struct|Union +struct_or_union_specifier + : struct_or_union identifier LBRACE struct_declaration_list RBRACE {result = val[0][1].new_at(val[0][0], val[1].val, val[3])} + | struct_or_union LBRACE struct_declaration_list RBRACE {result = val[0][1].new_at(val[0][0], nil , val[2])} + | struct_or_union identifier {result = val[0][1].new_at(val[0][0], val[1].val, nil )} + # type names can also be used as struct identifiers + | struct_or_union typedef_name LBRACE struct_declaration_list RBRACE {result = val[0][1].new_at(val[0][0], val[1].name, val[3])} + | struct_or_union typedef_name {result = val[0][1].new_at(val[0][0], val[1].name, nil )} + +# Returns [Pos, Class] +struct_or_union + : STRUCT {result = [val[0].pos, Struct]} + | UNION {result = [val[0].pos, Union ]} + +# Returns NodeArray[Declaration] +struct_declaration_list + : struct_declaration {result = NodeArray[val[0]]} + | struct_declaration_list struct_declaration {val[0] << val[1]; result = val[0]} + +# Returns Declaration +struct_declaration + : specifier_qualifier_list struct_declarator_list SEMICOLON {result = make_declaration(val[0][0], val[0][1], val[1])} + +# Returns {Pos, [Symbol]} +specifier_qualifier_list + : type_specifier specifier_qualifier_list {val[1][1] << val[0][1]; result = val[1]} + | type_specifier {result = [val[0][0], [val[0][1]]]} + | type_qualifier specifier_qualifier_list {val[1][1] << val[0][1]; result = val[1]} + | type_qualifier {result = [val[0][0], [val[0][1]]]} + +# Returns NodeArray[Declarator] +struct_declarator_list + : struct_declarator {result = NodeArray[val[0]]} + | struct_declarator_list COMMA struct_declarator {result = val[0] << val[2]} + +# Returns Declarator +struct_declarator + : declarator {result = val[0]} + | declarator COLON constant_expression {result = val[0]; val[0].num_bits = val[2]} + | COLON constant_expression {result = Declarator.new_at(val[0].pos, :num_bits => val[1])} + +# Returns Enum +enum_specifier + : ENUM identifier LBRACE enumerator_list RBRACE {result = Enum.new_at(val[0].pos, val[1].val, val[3])} + | ENUM LBRACE enumerator_list RBRACE {result = Enum.new_at(val[0].pos, nil , val[2])} + | ENUM identifier LBRACE enumerator_list COMMA RBRACE {result = Enum.new_at(val[0].pos, val[1].val, val[3])} + | ENUM LBRACE enumerator_list COMMA RBRACE {result = Enum.new_at(val[0].pos, nil , val[2])} + | ENUM identifier {result = Enum.new_at(val[0].pos, val[1].val, nil )} + # type names can also be used as enum names + | ENUM typedef_name LBRACE enumerator_list RBRACE {result = Enum.new_at(val[0].pos, val[1].name, val[3])} + | ENUM typedef_name LBRACE enumerator_list COMMA RBRACE {result = Enum.new_at(val[0].pos, val[1].name, val[3])} + | ENUM typedef_name {result = Enum.new_at(val[0].pos, val[1].name, nil )} + +# Returns NodeArray[Enumerator] +enumerator_list + : enumerator {result = NodeArray[val[0]]} + | enumerator_list COMMA enumerator {result = val[0] << val[2]} + +# Returns Enumerator +enumerator + : enumeration_constant {result = Enumerator.new_at(val[0].pos, val[0].val, nil )} + | enumeration_constant EQ constant_expression {result = Enumerator.new_at(val[0].pos, val[0].val, val[2])} + +# Returns [Pos, Symbol] +type_qualifier + : CONST {result = [val[0].pos, :const ]} + | RESTRICT {result = [val[0].pos, :restrict]} + | VOLATILE {result = [val[0].pos, :volatile]} + +# Returns [Pos, Symbol] +function_specifier + : INLINE {result = [val[0].pos, :inline]} + +# Returns Declarator +declarator + : pointer direct_declarator {result = add_decl_type(val[1], val[0])} + | direct_declarator {result = val[0]} + +# Returns Declarator +direct_declarator + : identifier {result = Declarator.new_at(val[0].pos, nil, val[0].val)} + | LPAREN declarator RPAREN {result = val[1]} + | direct_declarator LBRACKET type_qualifier_list assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO + | direct_declarator LBRACKET type_qualifier_list RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO + | direct_declarator LBRACKET assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos, nil, val[2]))} + | direct_declarator LBRACKET RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} + | direct_declarator LBRACKET STATIC type_qualifier_list assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO + | direct_declarator LBRACKET STATIC assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO + | direct_declarator LBRACKET type_qualifier_list STATIC assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO + | direct_declarator LBRACKET type_qualifier_list MUL RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO + | direct_declarator LBRACKET MUL RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO + | direct_declarator LPAREN parameter_type_list RPAREN {result = add_decl_type(val[0], Function.new_at(val[0].pos, nil, param_list(*val[2]), :var_args => val[2][1]))} + | direct_declarator LPAREN identifier_list RPAREN {result = add_decl_type(val[0], Function.new_at(val[0].pos, nil, val[2]))} + | direct_declarator LPAREN RPAREN {result = add_decl_type(val[0], Function.new_at(val[0].pos ))} + +# Returns Pointer +pointer + : MUL type_qualifier_list {result = add_type_quals(Pointer.new_at(val[0].pos), val[1][1]) } + | MUL {result = Pointer.new_at(val[0].pos) } + | MUL type_qualifier_list pointer {p = add_type_quals(Pointer.new_at(val[0].pos), val[1][1]); val[2].direct_type = p; result = val[2]} + | MUL pointer {p = Pointer.new_at(val[0].pos) ; val[1].direct_type = p; result = val[1]} + +# Returns {Pos, [Symbol]} +type_qualifier_list + : type_qualifier {result = [val[0][0], [val[0][1]]]} + | type_qualifier_list type_qualifier {val[0][1] << val[1][1]; result = val[0]} + +# Returns [NodeArray[Parameter], var_args?] +parameter_type_list + : parameter_list {result = [val[0], false]} + | parameter_list COMMA ELLIPSIS {result = [val[0], true ]} + +# Returns NodeArray[Parameter] +parameter_list + : parameter_declaration {result = NodeArray[val[0]]} + | parameter_list COMMA parameter_declaration {result = val[0] << val[2]} + +# Returns Parameter +parameter_declaration + : declaration_specifiers declarator {ind_type = val[1].indirect_type and ind_type.detach + result = make_parameter(val[0][0], val[0][1], ind_type, val[1].name)} + | declaration_specifiers abstract_declarator {result = make_parameter(val[0][0], val[0][1], val[1] , nil )} + | declaration_specifiers {result = make_parameter(val[0][0], val[0][1], nil , nil )} + +# Returns NodeArray[Parameter] +identifier_list + : identifier {result = NodeArray[Parameter.new_at(val[0].pos, nil, val[0].val)]} + | identifier_list COMMA identifier {result = val[0] << Parameter.new_at(val[2].pos, nil, val[2].val)} + +# Returns Type +type_name + : specifier_qualifier_list abstract_declarator {val[1].direct_type = make_direct_type(val[0][0], val[0][1]); result = val[1]} + | specifier_qualifier_list {result = make_direct_type(val[0][0], val[0][1]) } + +# Returns Type +abstract_declarator + : pointer {result = val[0]} + | pointer direct_abstract_declarator {val[1].direct_type = val[0]; result = val[1]} + | direct_abstract_declarator {result = val[0]} + +# Returns Type +direct_abstract_declarator + : LPAREN abstract_declarator RPAREN {result = val[1]} + | direct_abstract_declarator LBRACKET assignment_expression RBRACKET {val[0].direct_type = Array.new_at(val[0].pos, nil, val[2]); result = val[0]} + | direct_abstract_declarator LBRACKET RBRACKET {val[0].direct_type = Array.new_at(val[0].pos, nil, nil ); result = val[0]} + | LBRACKET assignment_expression RBRACKET {result = Array.new_at(val[0].pos, nil, val[1])} + | LBRACKET RBRACKET {result = Array.new_at(val[0].pos )} + | direct_abstract_declarator LBRACKET MUL RBRACKET {val[0].direct_type = Array.new_at(val[0].pos); result = val[0]} # TODO + | LBRACKET MUL RBRACKET {result = Array.new_at(val[0].pos)} # TODO + | direct_abstract_declarator LPAREN parameter_type_list RPAREN {val[0].direct_type = Function.new_at(val[0].pos, nil, param_list(*val[2]), val[2][1]); result = val[0]} + | direct_abstract_declarator LPAREN RPAREN {val[0].direct_type = Function.new_at(val[0].pos ); result = val[0]} + | LPAREN parameter_type_list RPAREN {result = Function.new_at(val[0].pos, nil, param_list(*val[1]), val[1][1])} + | LPAREN RPAREN {result = Function.new_at(val[0].pos )} + +# Returns CustomType +typedef_name + #: identifier -- insufficient since we must distinguish between type + # names and var names (otherwise we have a conflict) + : TYPENAME {result = CustomType.new_at(val[0].pos, val[0].val)} + +# Returns Expression +initializer + : assignment_expression {result = val[0]} + | LBRACE initializer_list RBRACE {result = CompoundLiteral.new_at(val[0].pos, nil, val[1])} + | LBRACE initializer_list COMMA RBRACE {result = CompoundLiteral.new_at(val[0].pos, nil, val[1])} + +# Returns NodeArray[MemberInit] +initializer_list + : designation initializer {result = NodeArray[MemberInit.new_at(val[0][0] , val[0][1], val[1])]} + | initializer {result = NodeArray[MemberInit.new_at(val[0].pos, nil , val[0])]} + | initializer_list COMMA designation initializer {result = val[0] << MemberInit.new_at(val[2][0] , val[2][1], val[3])} + | initializer_list COMMA initializer {result = val[0] << MemberInit.new_at(val[2].pos, nil , val[2])} + +# Returns {Pos, NodeArray[Expression|Token]} +designation + : designator_list EQ {result = val[0]} + +# Returns {Pos, NodeArray[Expression|Token]} +designator_list + : designator {result = val[0]; val[0][1] = NodeArray[val[0][1]]} + | designator_list designator {result = val[0]; val[0][1] << val[1][1]} + +# Returns {Pos, Expression|Member} +designator + : LBRACKET constant_expression RBRACKET {result = [val[1].pos, val[1] ]} + | DOT identifier {result = [val[1].pos, Member.new_at(val[1].pos, val[1].val)]} + +# A.2.1 Expressions + +# Returns Expression +primary_expression + : identifier {result = Variable.new_at(val[0].pos, val[0].val)} + | constant {result = val[0]} + | string_literal {result = val[0]} + # GCC EXTENSION: allow a compound statement in parentheses as an expression + | LPAREN expression RPAREN {result = val[1]} + | LPAREN compound_statement RPAREN {block_expressions_enabled? or parse_error val[0].pos, "compound statement found where expression expected" + result = BlockExpression.new(val[1]); result.pos = val[0].pos} + +# Returns Expression +postfix_expression + : primary_expression {result = val[0]} + | postfix_expression LBRACKET expression RBRACKET {result = Index .new_at(val[0].pos, val[0], val[2])} + | postfix_expression LPAREN argument_expression_list RPAREN {result = Call .new_at(val[0].pos, val[0], val[2] )} + | postfix_expression LPAREN RPAREN {result = Call .new_at(val[0].pos, val[0], NodeArray[])} + | postfix_expression DOT identifier {result = Dot .new_at(val[0].pos, val[0], Member.new(val[2].val))} + | postfix_expression ARROW identifier {result = Arrow .new_at(val[0].pos, val[0], Member.new(val[2].val))} + | postfix_expression INC {result = PostInc .new_at(val[0].pos, val[0] )} + | postfix_expression DEC {result = PostDec .new_at(val[0].pos, val[0] )} + | LPAREN type_name RPAREN LBRACE initializer_list RBRACE {result = CompoundLiteral.new_at(val[0].pos, val[1], val[4])} + | LPAREN type_name RPAREN LBRACE initializer_list COMMA RBRACE {result = CompoundLiteral.new_at(val[0].pos, val[1], val[4])} + +# Returns [Expression|Type] +argument_expression_list + : argument_expression {result = NodeArray[val[0]]} + | argument_expression_list COMMA argument_expression {result = val[0] << val[2]} + +# Returns Expression|Type -- EXTENSION: allow type names here too, to support some standard library macros (e.g., va_arg [7.15.1.1]) +argument_expression + : assignment_expression {result = val[0]} + | type_name {result = val[0]} + +# Returns Expression +unary_expression + : postfix_expression {result = val[0]} + | INC unary_expression {result = PreInc.new_at(val[0].pos, val[1])} + | DEC unary_expression {result = PreDec.new_at(val[0].pos, val[1])} + | unary_operator cast_expression {result = val[0][0].new_at(val[0][1], val[1])} + | SIZEOF unary_expression {result = Sizeof.new_at(val[0].pos, val[1])} + | SIZEOF LPAREN type_name RPAREN {result = Sizeof.new_at(val[0].pos, val[2])} + +# Returns [Class, Pos] +unary_operator + : AND {result = [Address , val[0].pos]} + | MUL {result = [Dereference, val[0].pos]} + | ADD {result = [Positive , val[0].pos]} + | SUB {result = [Negative , val[0].pos]} + | NOT {result = [BitNot , val[0].pos]} + | BANG {result = [Not , val[0].pos]} + +# Returns Expression +cast_expression + : unary_expression {result = val[0]} + | LPAREN type_name RPAREN cast_expression {result = Cast.new_at(val[0].pos, val[1], val[3])} + +# Returns Expression +multiplicative_expression + : cast_expression {result = val[0]} + | multiplicative_expression MUL cast_expression {result = Multiply.new_at(val[0].pos, val[0], val[2])} + | multiplicative_expression DIV cast_expression {result = Divide .new_at(val[0].pos, val[0], val[2])} + | multiplicative_expression MOD cast_expression {result = Mod .new_at(val[0].pos, val[0], val[2])} + +# Returns Expression +additive_expression + : multiplicative_expression {result = val[0]} + | additive_expression ADD multiplicative_expression {result = Add .new_at(val[0].pos, val[0], val[2])} + | additive_expression SUB multiplicative_expression {result = Subtract.new_at(val[0].pos, val[0], val[2])} + +# Returns Expression +shift_expression + : additive_expression {result = val[0]} + | shift_expression LSHIFT additive_expression {result = ShiftLeft .new_at(val[0].pos, val[0], val[2])} + | shift_expression RSHIFT additive_expression {result = ShiftRight.new_at(val[0].pos, val[0], val[2])} + +# Returns Expression +relational_expression + : shift_expression {result = val[0]} + | relational_expression LT shift_expression {result = Less.new_at(val[0].pos, val[0], val[2])} + | relational_expression GT shift_expression {result = More.new_at(val[0].pos, val[0], val[2])} + | relational_expression LEQ shift_expression {result = LessOrEqual.new_at(val[0].pos, val[0], val[2])} + | relational_expression GEQ shift_expression {result = MoreOrEqual.new_at(val[0].pos, val[0], val[2])} + +# Returns Expression +equality_expression + : relational_expression {result = val[0]} + | equality_expression EQEQ relational_expression {result = Equal .new_at(val[0].pos, val[0], val[2])} + | equality_expression NEQ relational_expression {result = NotEqual.new_at(val[0].pos, val[0], val[2])} + +# Returns Expression +and_expression + : equality_expression {result = val[0]} + | and_expression AND equality_expression {result = BitAnd.new_at(val[0].pos, val[0], val[2])} + +# Returns Expression +exclusive_or_expression + : and_expression {result = val[0]} + | exclusive_or_expression XOR and_expression {result = BitXor.new_at(val[0].pos, val[0], val[2])} + +# Returns Expression +inclusive_or_expression + : exclusive_or_expression {result = val[0]} + | inclusive_or_expression OR exclusive_or_expression {result = BitOr.new_at(val[0].pos, val[0], val[2])} + +# Returns Expression +logical_and_expression + : inclusive_or_expression {result = val[0]} + | logical_and_expression ANDAND inclusive_or_expression {result = And.new_at(val[0].pos, val[0], val[2])} + +# Returns Expression +logical_or_expression + : logical_and_expression {result = val[0]} + | logical_or_expression OROR logical_and_expression {result = Or.new_at(val[0].pos, val[0], val[2])} + +# Returns Expression +conditional_expression + : logical_or_expression {result = val[0]} + | logical_or_expression QUESTION expression COLON conditional_expression {result = Conditional.new_at(val[0].pos, val[0], val[2], val[4])} + +# Returns Expression +assignment_expression + : conditional_expression {result = val[0]} + | unary_expression assignment_operator assignment_expression {result = val[1].new_at(val[0].pos, val[0], val[2])} + +# Returns Class +assignment_operator + : EQ {result = Assign} + | MULEQ {result = MultiplyAssign} + | DIVEQ {result = DivideAssign} + | MODEQ {result = ModAssign} + | ADDEQ {result = AddAssign} + | SUBEQ {result = SubtractAssign} + | LSHIFTEQ {result = ShiftLeftAssign} + | RSHIFTEQ {result = ShiftRightAssign} + | ANDEQ {result = BitAndAssign} + | XOREQ {result = BitXorAssign} + | OREQ {result = BitOrAssign} + +# Returns Expression +expression + : assignment_expression {result = val[0]} + | expression COMMA assignment_expression { + if val[0].is_a? Comma + if val[2].is_a? Comma + val[0].exprs.push(*val[2].exprs) + else + val[0].exprs << val[2] + end + result = val[0] + else + if val[2].is_a? Comma + val[2].exprs.unshift(val[0]) + val[2].pos = val[0].pos + result = val[2] + else + result = Comma.new_at(val[0].pos, NodeArray[val[0], val[2]]) + end + end + } + +# Returns Expression +constant_expression + : conditional_expression {result = val[0]} + +# A.1.1 -- Lexical elements +# +# token +# : keyword (raw string) +# | identifier expanded below +# | constant expanded below +# | string_literal expanded below +# | punctuator (raw string) +# +# preprocessing-token (skip) + +# Returns Token +identifier + : ID {result = val[0]} + +# Returns Literal +constant + : ICON {result = val[0].val; result.pos = val[0].pos} + | FCON {result = val[0].val; result.pos = val[0].pos} + #| enumeration_constant -- these are parsed as identifiers at all + # places the `constant' nonterminal appears + | CCON {result = val[0].val; result.pos = val[0].pos} + +# Returns Token +enumeration_constant + : ID {result = val[0]} + +# Returns StringLiteral +# Also handles string literal concatenation (6.4.5.4) +string_literal + : string_literal SCON {val[0].val << val[1].val.val; result = val[0]} + | SCON { result = val[0].val; result.pos = val[0].pos } + +---- inner + # A.1.9 -- Preprocessing numbers -- skip + # A.1.8 -- Header names -- skip + + # A.1.7 -- Puncuators -- we don't bother with {##,#,%:,%:%:} since + # we don't do preprocessing + @@punctuators = %r'\+\+|-[->]|&&|\|\||\.\.\.|(?:<<|>>|[<>=!*/%+\-&^|])=?|[\[\](){}.~?:;,]' + @@digraphs = %r'<[:%]|[:%]>' + + # A.1.6 -- String Literals -- simple for us because we don't decode + # the string (and indeed accept some illegal strings) + @@string_literal = %r'L?"(?:[^\\]|\\.)*?"'m + + # A.1.5 -- Constants + @@decimal_floating_constant = %r'(?:(?:\d*\.\d+|\d+\.)(?:e[-+]?\d+)?|\d+e[-+]?\d+)[fl]?'i + @@hexadecimal_floating_constant = %r'0x(?:(?:[0-9a-f]*\.[0-9a-f]+|[0-9a-f]+\.)|[0-9a-f]+)p[-+]?\d+[fl]?'i + + @@integer_constant = %r'(?:[1-9][0-9]*|0x[0-9a-f]+|0[0-7]*)(?:ul?l?|ll?u?)?'i + @@floating_constant = %r'#{@@decimal_floating_constant}|#{@@hexadecimal_floating_constant}' + @@enumeration_constant = %r'[a-zA-Z_\\][a-zA-Z_\\0-9]*' + @@character_constant = %r"L?'(?:[^\\]|\\.)+?'" + # (note that as with string-literals, we accept some illegal + # character-constants) + + # A.1.4 -- Universal character names -- skip + + # A.1.3 -- Identifiers -- skip, since an identifier is lexically + # identical to an enumeration constant + + # A.1.2 Keywords + keywords = %w'auto break case char const continue default do +double else enum extern float for goto if inline int long register +restrict return short signed sizeof static struct switch typedef union + unsigned void volatile while _Bool _Complex _Imaginary' + @@keywords = %r"#{keywords.join('|')}" + + def initialize + @type_names = ::Set.new + + @warning_proc = lambda{} + @pos = C::Node::Pos.new(nil, 1, 0) + end + def initialize_copy(x) + @pos = x.pos.dup + @type_names = x.type_names.dup + end + attr_accessor :pos, :type_names + + def parse(str) + if str.respond_to? :read + str = str.read + end + @str = str + begin + prepare_lexer(str) + return do_parse + rescue ParseError => e + e.set_backtrace(caller) + raise + end + end + + # + # Error handler, as used by racc. + # + def on_error(error_token_id, error_value, value_stack) + if error_value == '$' + parse_error @pos, "unexpected EOF" + else + parse_error(error_value.pos, + "parse error on #{token_to_str(error_token_id)} (#{error_value.val})") + end + end + + def self.feature(name) + attr_writer "#{name}_enabled" + class_eval <<-EOS + def enable_#{name} + @#{name}_enabled = true + end + def #{name}_enabled? + @#{name}_enabled + end + EOS + end + private_class_method :feature + + # + # Allow blocks in parentheses as expressions, as per the gcc + # extension. [http://rubyurl.com/iB7] + # + feature :block_expressions + + private # --------------------------------------------------------- + + class Token + attr_accessor :pos, :val + def initialize(pos, val) + @pos = pos + @val = val + end + end + def eat(str) + lines = str.split(/\r\n|[\r\n]/, -1) + if lines.length == 1 + @pos.col_num += lines[0].length + else + @pos.line_num += lines.length - 1 + @pos.col_num = lines[-1].length + end + end + + # + # Make a Declaration from the given specs and declarators. + # + def make_declaration(pos, specs, declarators) + specs.all?{|x| x.is_a?(Symbol) || x.is_a?(Type)} or raise specs.map{|x| x.class}.inspect + decl = Declaration.new_at(pos, nil, declarators) + + # set storage class + storage_classes = specs.find_all do |x| + [:typedef, :extern, :static, :auto, :register].include? x + end + # 6.7.1p2: at most, one storage-class specifier may be given in + # the declaration specifiers in a declaration + storage_classes.length <= 1 or + begin + if declarators.length == 0 + for_name = '' + else + for_name = "for `#{declarators[0].name}'" + end + parse_error pos, "multiple or duplicate storage classes given #{for_name}'" + end + decl.storage = storage_classes[0] + + # set type (specifiers, qualifiers) + decl.type = make_direct_type(pos, specs) + + # set function specifiers + decl.inline = specs.include?(:inline) + + # look for new type names + if decl.typedef? + decl.declarators.each do |d| + if d.name + @type_names << d.name + end + end + end + + return decl + end + + def make_function_def(pos, specs, func_declarator, decl_list, defn) + add_decl_type(func_declarator, make_direct_type(pos, specs)) + + # get types from decl_list if necessary + function = func_declarator.indirect_type + function.is_a? Function or + parse_error pos, "non function type for function `#{func_declarator.name}'" + params = function.params + if decl_list + params.all?{|p| p.type.nil?} or + parse_error pos, "both prototype and declaration list given for `#{func_declarator.name}'" + decl_list.each do |declaration| + declaration.declarators.each do |declarator| + param = params.find{|p| p.name == declarator.name} or + parse_error pos, "no parameter named #{declarator.name}" + if declarator.indirect_type + param.type = declarator.indirect_type + param.type.direct_type = declaration.type.dup + else + param.type = declaration.type.dup + end + end + end + params.all?{|p| p.type} or + begin + s = params.find_all{|p| p.type.nil?}.map{|p| "`#{p.name}'"}.join(' and ') + parse_error pos, "types missing for parameters #{s}" + end + end + + fd = FunctionDef.new_at(pos, + function.detach, + func_declarator.name, + defn, + :no_prototype => !decl_list.nil?) + + # set storage class + # 6.9.1p4: only extern or static allowed + specs.each do |s| + [:typedef, :auto, :register].include?(s) and + "`#{s}' illegal for function" + end + storage_classes = specs.find_all do |s| + s == :extern || s == :static + end + # 6.7.1p2: at most, one storage-class specifier may be given in + # the declaration specifiers in a declaration + storage_classes.length <= 1 or + "multiple or duplicate storage classes given for `#{func_declarator.name}'" + fd.storage = storage_classes[0] if storage_classes[0] + + # set function specifiers + # 6.7.4p5 'inline' can be repeated + fd.inline = specs.include?(:inline) + + return fd + end + + # + # Make a direct type from the list of type specifiers and type + # qualifiers. + # + def make_direct_type(pos, specs) + specs_order = [:signed, :unsigned, :short, :long, :double, :void, + :char, :int, :float, :_Bool, :_Complex, :_Imaginary] + + type_specs = specs.find_all do |x| + specs_order.include?(x) || !x.is_a?(Symbol) + end + type_specs.sort! do |a, b| + (specs_order.index(a)||100) <=> (specs_order.index(b)||100) + end + + # set type specifiers + # 6.7.2p2: the specifier list should be one of these + type = + case type_specs + when [:void] + Void.new + when [:char] + Char.new + when [:signed, :char] + Char.new :signed => true + when [:unsigned, :char] + Char.new :signed => false + when [:short], [:signed, :short], [:short, :int], + [:signed, :short, :int] + Int.new :longness => -1 + when [:unsigned, :short], [:unsigned, :short, :int] + Int.new :unsigned => true, :longness => -1 + when [:int], [:signed], [:signed, :int] + Int.new + when [:unsigned], [:unsigned, :int] + Int.new :unsigned => true + when [:long], [:signed, :long], [:long, :int], + [:signed, :long, :int] + Int.new :longness => 1 + when [:unsigned, :long], [:unsigned, :long, :int] + Int.new :longness => 1, :unsigned => true + when [:long, :long], [:signed, :long, :long], + [:long, :long, :int], [:signed, :long, :long, :int] + Int.new :longness => 2 + when [:unsigned, :long, :long], [:unsigned, :long, :long, :int] + Int.new :longness => 2, :unsigned => true + when [:float] + Float.new + when [:double] + Float.new :longness => 1 + when [:long, :double] + Float.new :longness => 2 + when [:_Bool] + Bool.new + when [:float, :_Complex] + Complex.new + when [:double, :_Complex] + Complex.new :longness => 1 + when [:long, :double, :_Complex] + Complex.new :longness => 2 + when [:float, :_Imaginary] + Imaginary.new + when [:double, :_Imaginary] + Imaginary.new :longness => 1 + when [:long, :double, :_Imaginary] + Imaginary.new :longness => 2 + else + if type_specs.length == 1 && + [CustomType, Struct, Union, Enum].any?{|c| type_specs[0].is_a? c} + type_specs[0] + else + if type_specs == [] + parse_error pos, "no type specifiers given" + else + parse_error pos, "invalid type specifier combination: #{type_specs.join(' ')}" + end + end + end + type.pos ||= pos + + # set type qualifiers + # 6.7.3p4: type qualifiers can be repeated + type.const = specs.any?{|x| x.equal? :const } + type.restrict = specs.any?{|x| x.equal? :restrict} + type.volatile = specs.any?{|x| x.equal? :volatile} + + return type + end + + def make_parameter(pos, specs, indirect_type, name) + type = indirect_type + if type + type.direct_type = make_direct_type(pos, specs) + else + type = make_direct_type(pos, specs) + end + [:typedef, :extern, :static, :auto, :inline].each do |sym| + specs.include? sym and + parse_error pos, "parameter `#{declarator.name}' declared `#{sym}'" + end + return Parameter.new_at(pos, type, name, + :register => specs.include?(:register)) + end + + def add_type_quals(type, quals) + type.const = quals.include?(:const ) + type.restrict = quals.include?(:restrict) + type.volatile = quals.include?(:volatile) + return type + end + + # + # Add te given type as the "most direct" type to the given + # declarator. Return the declarator. + # + def add_decl_type(declarator, type) + if declarator.indirect_type + declarator.indirect_type.direct_type = type + else + declarator.indirect_type = type + end + return declarator + end + + def param_list(params, var_args) + if params.length == 1 && + params[0].type.is_a?(Void) && + params[0].name.nil? + return NodeArray[] + elsif params.empty? + return nil + else + return params + end + end + + def parse_error(pos, str) + raise ParseError, "#{pos}: #{str}" + end + +---- header + +require 'set' + +# Error classes +module C + class ParseError < StandardError; end +end + +# Local variables: +# mode: ruby +# end: diff --git a/test/assets/conf.y b/test/assets/conf.y index de9de71d..8e7b4392 100644 --- a/test/assets/conf.y +++ b/test/assets/conf.y @@ -6,7 +6,6 @@ a: A c C expr; b: A B; # useless -c: A; c: A; expr: expr '+' expr diff --git a/test/assets/csspool.y b/test/assets/csspool.y new file mode 100644 index 00000000..3d6af25d --- /dev/null +++ b/test/assets/csspool.y @@ -0,0 +1,729 @@ +class CSSPool::CSS::Parser + +token CHARSET_SYM IMPORT_SYM STRING SEMI IDENT S COMMA LBRACE RBRACE STAR HASH +token LSQUARE RSQUARE EQUAL INCLUDES DASHMATCH LPAREN RPAREN FUNCTION GREATER PLUS +token SLASH NUMBER MINUS LENGTH PERCENTAGE ANGLE TIME FREQ URI +token IMPORTANT_SYM MEDIA_SYM NOT ONLY AND NTH_PSEUDO_CLASS +token DOCUMENT_QUERY_SYM FUNCTION_NO_QUOTE +token TILDE +token PREFIXMATCH SUFFIXMATCH SUBSTRINGMATCH +token NOT_PSEUDO_CLASS +token KEYFRAMES_SYM +token MATCHES_PSEUDO_CLASS +token NAMESPACE_SYM +token MOZ_PSEUDO_ELEMENT +token RESOLUTION +token COLON +token SUPPORTS_SYM +token OR +token VARIABLE_NAME +token CALC_SYM +token FONTFACE_SYM +token UNICODE_RANGE +token RATIO + +rule + document + : { @handler.start_document } + stylesheet + { @handler.end_document } + ; + stylesheet + : charset stylesheet + | import stylesheet + | namespace stylesheet + | charset + | import + | namespace + | body + | + ; + charset + : CHARSET_SYM STRING SEMI { @handler.charset interpret_string(val[1]), {} } + ; + import + : IMPORT_SYM import_location medium SEMI { + @handler.import_style val[2], val[1] + } + | IMPORT_SYM import_location SEMI { + @handler.import_style [], val[1] + } + ; + import_location + : import_location S + | STRING { result = Terms::String.new interpret_string val.first } + | URI { result = Terms::URI.new interpret_uri val.first } + ; + namespace + : NAMESPACE_SYM ident import_location SEMI { + @handler.namespace val[1], val[2] + } + | NAMESPACE_SYM import_location SEMI { + @handler.namespace nil, val[1] + } + ; + medium + : medium COMMA IDENT { + result = val[0] << MediaType.new(val[2]) + } + | IDENT { + result = [MediaType.new(val[0])] + } + ; + media_query_list + : media_query { result = MediaQueryList.new([ val[0] ]) } + | media_query_list COMMA media_query { result = val[0] << val[2] } + | { result = MediaQueryList.new } + ; + media_query + : optional_only_or_not media_type optional_and_exprs { result = MediaQuery.new(val[0], val[1], val[2]) } + | media_expr optional_and_exprs { result = MediaQuery.new(nil, val[0], val[1]) } + ; + optional_only_or_not + : ONLY { result = :only } + | NOT { result = :not } + | { result = nil } + ; + media_type + : IDENT { result = MediaType.new(val[0]) } + ; + media_expr + : LPAREN optional_space IDENT optional_space RPAREN { result = MediaType.new(val[2]) } + | LPAREN optional_space IDENT optional_space COLON optional_space expr RPAREN { result = MediaFeature.new(val[2], val[6][0]) } + ; + optional_space + : S { result = val[0] } + | { result = nil } + ; + optional_and_exprs + : optional_and_exprs AND media_expr { result = val[0] << val[2] } + | { result = [] } + ; + resolution + : RESOLUTION { + unit = val.first.gsub(/[\s\d.]/, '') + number = numeric(val.first) + result = Terms::Resolution.new(number, unit) + } + ; + body + : ruleset body + | conditional_rule body + | keyframes_rule body + | fontface_rule body + | ruleset + | conditional_rule + | keyframes_rule + | fontface_rule + ; + conditional_rule + : media + | document_query + | supports + ; + body_in_media + : body + | empty_ruleset + ; + media + : start_media body_in_media RBRACE { @handler.end_media val.first } + ; + start_media + : MEDIA_SYM media_query_list LBRACE { + result = val[1] + @handler.start_media result + } + ; + document_query + : start_document_query body RBRACE { @handler.end_document_query(before_pos(val), after_pos(val)) } + | start_document_query RBRACE { @handler.end_document_query(before_pos(val), after_pos(val)) } + ; + start_document_query + : start_document_query_pos url_match_fns LBRACE { + @handler.start_document_query(val[1], after_pos(val)) + } + ; + start_document_query_pos + : DOCUMENT_QUERY_SYM { + @handler.node_start_pos = before_pos(val) + } + ; + url_match_fns + : url_match_fn COMMA url_match_fns { + result = [val[0], val[2]].flatten + } + | url_match_fn { + result = val + } + ; + url_match_fn + : function_no_quote + | function + | uri + ; + supports + : start_supports body RBRACE { @handler.end_supports } + | start_supports RBRACE { @handler.end_supports } + ; + start_supports + : SUPPORTS_SYM supports_condition_root LBRACE { + @handler.start_supports val[1] + } + ; + supports_condition_root + : supports_negation { result = val.join('') } + | supports_conjunction_or_disjunction { result = val.join('') } + | supports_condition_in_parens { result = val.join('') } + ; + supports_condition + : supports_negation { result = val.join('') } + | supports_conjunction_or_disjunction { result = val.join('') } + | supports_condition_in_parens { result = val.join('') } + ; + supports_condition_in_parens + : LPAREN supports_condition RPAREN { result = val.join('') } + | supports_declaration_condition { result = val.join('') } + ; + supports_negation + : NOT supports_condition_in_parens { result = val.join('') } + ; + supports_conjunction_or_disjunction + : supports_conjunction + | supports_disjunction + ; + supports_conjunction + : supports_condition_in_parens AND supports_condition_in_parens { result = val.join('') } + | supports_conjunction_or_disjunction AND supports_condition_in_parens { result = val.join('') } + ; + supports_disjunction + : supports_condition_in_parens OR supports_condition_in_parens { result = val.join('') } + | supports_conjunction_or_disjunction OR supports_condition_in_parens { result = val.join('') } + ; + supports_declaration_condition + : LPAREN declaration_internal RPAREN { result = val.join('') } + | LPAREN S declaration_internal RPAREN { result = val.join('') } + ; + keyframes_rule + : start_keyframes_rule keyframes_blocks RBRACE + | start_keyframes_rule RBRACE + ; + start_keyframes_rule + : KEYFRAMES_SYM IDENT LBRACE { + @handler.start_keyframes_rule val[1] + } + ; + keyframes_blocks + : keyframes_block keyframes_blocks + | keyframes_block + ; + keyframes_block + : start_keyframes_block declarations RBRACE { @handler.end_keyframes_block } + | start_keyframes_block RBRACE { @handler.end_keyframes_block } + ; + start_keyframes_block + : keyframes_selectors LBRACE { + @handler.start_keyframes_block val[0] + } + ; + keyframes_selectors + | keyframes_selector COMMA keyframes_selectors { + result = val[0] + ', ' + val[2] + } + | keyframes_selector + ; + keyframes_selector + : IDENT + | PERCENTAGE { result = val[0].strip } + ; + fontface_rule + : start_fontface_rule declarations RBRACE { @handler.end_fontface_rule } + | start_fontface_rule RBRACE { @handler.end_fontface_rule } + ; + start_fontface_rule + : FONTFACE_SYM LBRACE { + @handler.start_fontface_rule + } + ; + ruleset + : start_selector declarations RBRACE { + @handler.end_selector val.first + } + | start_selector RBRACE { + @handler.end_selector val.first + } + ; + empty_ruleset + : optional_space { + start = @handler.start_selector([]) + @handler.end_selector(start) + } + ; + start_selector + : S start_selector { result = val.last } + | selectors LBRACE { + @handler.start_selector val.first + } + ; + selectors + : selector COMMA selectors + { + sel = Selector.new(val.first, {}) + result = [sel].concat(val[2]) + } + | selector + { + result = [Selector.new(val.first, {})] + } + ; + selector + : simple_selector combinator selector + { + val.flatten! + val[2].combinator = val.delete_at 1 + result = val + } + | simple_selector + ; + combinator + : S { result = :s } + | GREATER { result = :> } + | PLUS { result = :+ } + | TILDE { result = :~ } + ; + simple_selector + : element_name hcap { + selector = val.first + selector.additional_selectors = val.last + result = [selector] + } + | element_name { result = val } + | hcap + { + ss = Selectors::Simple.new nil, nil + ss.additional_selectors = val.flatten + result = [ss] + } + ; + simple_selectors + : simple_selector COMMA simple_selectors { result = [val[0], val[2]].flatten } + | simple_selector + ; + ident_with_namespace + : IDENT { result = [interpret_identifier(val[0]), nil] } + | IDENT '|' IDENT { result = [interpret_identifier(val[2]), interpret_identifier(val[0])] } + | '|' IDENT { result = [interpret_identifier(val[1]), nil] } + | STAR '|' IDENT { result = [interpret_identifier(val[2]), '*'] } + ; + element_name + : ident_with_namespace { result = Selectors::Type.new val.first[0], nil, val.first[1] } + | STAR { result = Selectors::Universal.new val.first } + | '|' STAR { result = Selectors::Universal.new val[1] } + | STAR '|' STAR { result = Selectors::Universal.new val[2], nil, val[0] } + | IDENT '|' STAR { result = Selectors::Universal.new val[2], nil, interpret_identifier(val[0]) } + ; + hcap + : hash { result = val } + | class { result = val } + | attrib { result = val } + | pseudo { result = val } + | hash hcap { result = val.flatten } + | class hcap { result = val.flatten } + | attrib hcap { result = val.flatten } + | pseudo hcap { result = val.flatten } + ; + hash + : HASH { + result = Selectors::Id.new interpret_identifier val.first.sub(/^#/, '') + } + class + : '.' IDENT { + result = Selectors::Class.new interpret_identifier val.last + } + ; + attrib + : LSQUARE ident_with_namespace EQUAL IDENT RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::EQUALS, + val[1][1] + ) + } + | LSQUARE ident_with_namespace EQUAL STRING RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::EQUALS, + val[1][1] + ) + } + | LSQUARE ident_with_namespace INCLUDES STRING RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::INCLUDES, + val[1][1] + ) + } + | LSQUARE ident_with_namespace INCLUDES IDENT RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::INCLUDES, + val[1][1] + ) + } + | LSQUARE ident_with_namespace DASHMATCH IDENT RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::DASHMATCH, + val[1][1] + ) + } + | LSQUARE ident_with_namespace DASHMATCH STRING RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::DASHMATCH, + val[1][1] + ) + } + | LSQUARE ident_with_namespace PREFIXMATCH IDENT RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::PREFIXMATCH, + val[1][1] + ) + } + | LSQUARE ident_with_namespace PREFIXMATCH STRING RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::PREFIXMATCH, + val[1][1] + ) + } + | LSQUARE ident_with_namespace SUFFIXMATCH IDENT RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::SUFFIXMATCH, + val[1][1] + ) + } + | LSQUARE ident_with_namespace SUFFIXMATCH STRING RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::SUFFIXMATCH, + val[1][1] + ) + } + | LSQUARE ident_with_namespace SUBSTRINGMATCH IDENT RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::SUBSTRINGMATCH, + val[1][1] + ) + } + | LSQUARE ident_with_namespace SUBSTRINGMATCH STRING RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::SUBSTRINGMATCH, + val[1][1] + ) + } + | LSQUARE ident_with_namespace RSQUARE { + result = Selectors::Attribute.new( + val[1][0], + nil, + Selectors::Attribute::SET, + val[1][1] + ) + } + ; + pseudo + : COLON IDENT { + result = Selectors::pseudo interpret_identifier(val[1]) + } + | COLON COLON IDENT { + result = Selectors::PseudoElement.new( + interpret_identifier(val[2]) + ) + } + | COLON FUNCTION RPAREN { + result = Selectors::PseudoClass.new( + interpret_identifier(val[1].sub(/\($/, '')), + '' + ) + } + | COLON FUNCTION IDENT RPAREN { + result = Selectors::PseudoClass.new( + interpret_identifier(val[1].sub(/\($/, '')), + interpret_identifier(val[2]) + ) + } + | COLON NOT_PSEUDO_CLASS simple_selector RPAREN { + result = Selectors::PseudoClass.new( + 'not', + val[2].first.to_s + ) + } + | COLON NTH_PSEUDO_CLASS { + result = Selectors::PseudoClass.new( + interpret_identifier(val[1].sub(/\(.*/, '')), + interpret_identifier(val[1].sub(/.*\(/, '').sub(/\).*/, '')) + ) + } + | COLON MATCHES_PSEUDO_CLASS simple_selectors RPAREN { + result = Selectors::PseudoClass.new( + val[1].split('(').first.strip, + val[2].join(', ') + ) + } + | COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN { + result = Selectors::PseudoElement.new( + interpret_identifier(val[1].sub(/\($/, '')) + ) + } + | COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN { + result = Selectors::PseudoElement.new( + interpret_identifier(val[2].sub(/\($/, '')) + ) + } + ; + any_number_of_idents + : + | multiple_idents + ; + multiple_idents + : IDENT + | IDENT COMMA multiple_idents + ; + # declarations can be separated by one *or more* semicolons. semi-colons at the start or end of a ruleset are also allowed + one_or_more_semis + : SEMI + | SEMI one_or_more_semis + ; + declarations + : declaration one_or_more_semis declarations + | one_or_more_semis declarations + | declaration one_or_more_semis + | declaration + | one_or_more_semis + ; + declaration + : declaration_internal { @handler.property val.first } + ; + declaration_internal + : property COLON expr prio + { result = Declaration.new(val.first, val[2], val[3]) } + | property COLON S expr prio + { result = Declaration.new(val.first, val[3], val[4]) } + | property S COLON expr prio + { result = Declaration.new(val.first, val[3], val[4]) } + | property S COLON S expr prio + { result = Declaration.new(val.first, val[4], val[5]) } + ; + prio + : IMPORTANT_SYM { result = true } + | { result = false } + ; + property + : IDENT { result = interpret_identifier val[0] } + | STAR IDENT { result = interpret_identifier val.join } + | VARIABLE_NAME { result = interpret_identifier val[0] } + ; + operator + : COMMA + | SLASH + | EQUAL + ; + expr + : term operator expr { + result = [val.first, val.last].flatten + val.last.first.operator = val[1] + } + | term expr { result = val.flatten } + | term { result = val } + ; + term + : ident + | ratio + | numeric + | string + | uri + | hexcolor + | calc + | function + | resolution + | VARIABLE_NAME + | uranges + ; + function + : function S { result = val.first } + | FUNCTION expr RPAREN { + name = interpret_identifier val.first.sub(/\($/, '') + if name == 'rgb' + result = Terms::Rgb.new(*val[1]) + else + result = Terms::Function.new name, val[1] + end + } + | FUNCTION RPAREN { + name = interpret_identifier val.first.sub(/\($/, '') + result = Terms::Function.new name + } + ; + function_no_quote + : function_no_quote S { result = val.first } + | FUNCTION_NO_QUOTE { + parts = val.first.split('(') + name = interpret_identifier parts.first + result = Terms::Function.new(name, [Terms::String.new(interpret_string_no_quote(parts.last))]) + } + ; + uranges + : UNICODE_RANGE COMMA uranges + | UNICODE_RANGE + ; + calc + : CALC_SYM calc_sum RPAREN optional_space { + result = Terms::Math.new(val.first.split('(').first, val[1]) + } + ; + # plus and minus are supposed to have whitespace around them, per http://dev.w3.org/csswg/css-values/#calc-syntax, but the numbers are eating trailing whitespace, so we inject it back in + calc_sum + : calc_product + | calc_product PLUS calc_sum { val.insert(1, ' '); result = val.join('') } + | calc_product MINUS calc_sum { val.insert(1, ' '); result = val.join('') } + ; + calc_product + : calc_value + | calc_value optional_space STAR calc_value { result = val.join('') } + | calc_value optional_space SLASH calc_value { result = val.join('') } + ; + calc_value + : numeric { result = val.join('') } + | function { result = val.join('') } # for var() variable references + | LPAREN calc_sum RPAREN { result = val.join('') } + ; + hexcolor + : hexcolor S { result = val.first } + | HASH { result = Terms::Hash.new val.first.sub(/^#/, '') } + ; + uri + : uri S { result = val.first } + | URI { result = Terms::URI.new interpret_uri val.first } + ; + string + : string S { result = val.first } + | STRING { result = Terms::String.new interpret_string val.first } + ; + numeric + : unary_operator numeric { + result = val[1] + val[1].unary_operator = val.first + } + | NUMBER { + result = Terms::Number.new numeric val.first + } + | PERCENTAGE { + result = Terms::Number.new numeric(val.first), nil, '%' + } + | LENGTH { + unit = val.first.gsub(/[\s\d.]/, '') + result = Terms::Number.new numeric(val.first), nil, unit + } + | ANGLE { + unit = val.first.gsub(/[\s\d.]/, '') + result = Terms::Number.new numeric(val.first), nil, unit + } + | TIME { + unit = val.first.gsub(/[\s\d.]/, '') + result = Terms::Number.new numeric(val.first), nil, unit + } + | FREQ { + unit = val.first.gsub(/[\s\d.]/, '') + result = Terms::Number.new numeric(val.first), nil, unit + } + ; + ratio + : RATIO { + result = Terms::Ratio.new(val[0], val[1]) + } + ; + unary_operator + : MINUS { result = :minus } + | PLUS { result = :plus } + ; + ident + : ident S { result = val.first } + | IDENT { result = Terms::Ident.new interpret_identifier val.first } + ; + +---- inner + +def numeric thing + thing = thing.gsub(/[^\d.]/, '') + Integer(thing) rescue Float(thing) +end + +def interpret_identifier s + interpret_escapes s +end + +def interpret_uri s + interpret_escapes s.match(/^url\((.*)\)$/mui)[1].strip.match(/^(['"]?)((?:\\.|.)*)\1$/mu)[2] +end + +def interpret_string_no_quote s + interpret_escapes s.match(/^(.*)\)$/mu)[1].strip.match(/^(['"]?)((?:\\.|.)*)\1$/mu)[2] +end + +def interpret_string s + interpret_escapes s.match(/^(['"])((?:\\.|.)*)\1$/mu)[2] +end + +def interpret_escapes s + token_exp = /\\(?:([0-9a-fA-F]{1,6}(?:\r\n|\s)?)|(.))/mu + return s.gsub(token_exp) do |escape_sequence| + if !$1.nil? + code = $1.chomp.to_i 16 + code = 0xFFFD if code > 0x10FFFF + next [code].pack('U') + end + next '' if $2 == "\n" + next $2 + end +end + +# override racc's on_error so we can have context in our error messages +def on_error(t, val, vstack) + errcontext = (@ss.pre_match[-10..-1] || @ss.pre_match) + + @ss.matched + @ss.post_match[0..9] + line_number = @ss.pre_match.lines.count + raise ParseError, sprintf("parse error on value %s (%s) " + + "on line %s around \"%s\"", + val.inspect, token_to_str(t) || '?', + line_number, errcontext) +end + +def before_pos(val) + # don't include leading whitespace + return current_pos - val.last.length + val.last[/\A\s*/].size +end + +def after_pos(val) + # don't include trailing whitespace + return current_pos - val.last[/\s*\z/].size +end + +# charpos will work with multibyte strings but is not available until ruby 2 +def current_pos + @ss.respond_to?('charpos') ? @ss.charpos : @ss.pos +end diff --git a/test/assets/duplicate.y b/test/assets/duplicate.y new file mode 100644 index 00000000..9ea880d4 --- /dev/null +++ b/test/assets/duplicate.y @@ -0,0 +1,9 @@ +class A +rule + +a: A c C expr; + +c: A; +c: A; + +end diff --git a/test/assets/edtf.y b/test/assets/edtf.y new file mode 100644 index 00000000..4f5f6bb4 --- /dev/null +++ b/test/assets/edtf.y @@ -0,0 +1,583 @@ +# -*- racc -*- + +# Copyright 2011 Sylvester Keil. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are +# those of the authors and should not be interpreted as representing official +# policies, either expressed or implied, of the copyright holder. + +class EDTF::Parser + +token T Z E X U UNKNOWN OPEN LONGYEAR UNMATCHED DOTS UA PUA + +expect 0 + +rule + + edtf : level_0_expression + | level_1_expression + | level_2_expression + ; + + # ---- Level 0 / ISO 8601 Rules ---- + + # NB: level 0 intervals are covered by the level 1 interval rules + level_0_expression : date + | date_time + ; + + date : positive_date + | negative_date + ; + + positive_date : + year { result = Date.new(val[0]).year_precision! } + | year_month { result = Date.new(*val.flatten).month_precision! } + | year_month_day { result = Date.new(*val.flatten).day_precision! } + ; + + negative_date : '-' positive_date { result = -val[1] } + + + date_time : date T time { + result = DateTime.new(val[0].year, val[0].month, val[0].day, *val[2]) + result.skip_timezone = (val[2].length == 3) + } + + time : base_time + | base_time zone_offset { result = val.flatten } + + base_time : hour ':' minute ':' second { result = val.values_at(0, 2, 4) } + | midnight + + midnight : '2' '4' ':' '0' '0' ':' '0' '0' { result = [24, 0, 0] } + + zone_offset : Z { result = 0 } + | '-' zone_offset_hour { result = -1 * val[1] } + | '+' positive_zone_offset { result = val[1] } + ; + + positive_zone_offset : zone_offset_hour + | '0' '0' ':' '0' '0' { result = 0 } + ; + + + zone_offset_hour : d01_13 ':' minute { result = Rational(val[0] * 60 + val[2], 1440) } + | '1' '4' ':' '0' '0' { result = Rational(840, 1440) } + | '0' '0' ':' d01_59 { result = Rational(val[3], 1440) } + ; + + year : digit digit digit digit { + result = val.zip([1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b } + } + + month : d01_12 + day : d01_31 + + year_month : year '-' month { result = [val[0], val[2]] } + + # We raise an exception if there are two many days for the month, but + # do not consider leap years, as the EDTF BNF did not either. + # NB: an exception will be raised regardless, because the Ruby Date + # implementation calculates leap years. + year_month_day : year_month '-' day { + result = val[0] << val[2] + if result[2] > 31 || (result[2] > 30 && [2,4,6,9,11].include?(result[1])) || (result[2] > 29 && result[1] == 2) + raise ArgumentError, "invalid date (invalid days #{result[2]} for month #{result[1]})" + end + } + + hour : d00_23 + minute : d00_59 + second : d00_59 + + # Completely covered by level_1_interval + # level_0_interval : date '/' date { result = Interval.new(val[0], val[1]) } + + + # ---- Level 1 Extension Rules ---- + + # NB: Uncertain/approximate Dates are covered by the Level 2 rules + level_1_expression : unspecified | level_1_interval | long_year_simple | season + + # uncertain_or_approximate_date : date UA { result = uoa(val[0], val[1]) } + + unspecified : unspecified_year + { + result = Date.new(val[0][0]).year_precision! + result.unspecified.year[2,2] = val[0][1] + } + | unspecified_month + | unspecified_day + | unspecified_day_and_month + ; + + unspecified_year : + digit digit digit U + { + result = [val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }, [false,true]] + } + | digit digit U U + { + result = [val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }, [true, true]] + } + + unspecified_month : year '-' U U { + result = Date.new(val[0]).unspecified!(:month) + result.precision = :month + } + + unspecified_day : year_month '-' U U { + result = Date.new(*val[0]).unspecified!(:day) + } + + unspecified_day_and_month : year '-' U U '-' U U { + result = Date.new(val[0]).unspecified!([:day,:month]) + } + + + level_1_interval : level_1_start '/' level_1_end { + result = Interval.new(val[0], val[2]) + } + + level_1_start : date | partial_uncertain_or_approximate | unspecified | partial_unspecified | UNKNOWN + + level_1_end : level_1_start | OPEN + + + long_year_simple : + LONGYEAR long_year + { + result = Date.new(val[1]) + result.precision = :year + } + | LONGYEAR '-' long_year + { + result = Date.new(-1 * val[2]) + result.precision = :year + } + ; + + long_year : + positive_digit digit digit digit digit { + result = val.zip([10000,1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b } + } + | long_year digit { result = 10 * val[0] + val[1] } + ; + + + season : year '-' season_number ua { + result = Season.new(val[0], val[2]) + val[3].each { |ua| result.send(ua) } + } + + season_number : '2' '1' { result = 21 } + | '2' '2' { result = 22 } + | '2' '3' { result = 23 } + | '2' '4' { result = 24 } + ; + + + # ---- Level 2 Extension Rules ---- + + # NB: Level 2 Intervals are covered by the Level 1 Interval rules. + level_2_expression : season_qualified + | partial_uncertain_or_approximate + | partial_unspecified + | choice_list + | inclusive_list + | masked_precision + | date_and_calendar + | long_year_scientific + ; + + + season_qualified : season '^' { result = val[0]; result.qualifier = val[1] } + + + long_year_scientific : + long_year_simple E integer + { + result = Date.new(val[0].year * 10 ** val[2]).year_precision! + } + | LONGYEAR int1_4 E integer + { + result = Date.new(val[1] * 10 ** val[3]).year_precision! + } + | LONGYEAR '-' int1_4 E integer + { + result = Date.new(-1 * val[2] * 10 ** val[4]).year_precision! + } + ; + + + date_and_calendar : date '^' { result = val[0]; result.calendar = val[1] } + + + masked_precision : + digit digit digit X + { + d = val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b } + result = EDTF::Decade.new(d) + } + | digit digit X X + { + d = val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b } + result = EDTF::Century.new(d) + } + ; + + + choice_list : '[' list ']' { result = val[1].choice! } + + inclusive_list : '{' list '}' { result = val[1] } + + list : earlier { result = EDTF::Set.new(val[0]).earlier! } + | earlier ',' list_elements ',' later { result = EDTF::Set.new([val[0]] + val[2] + [val[4]]).earlier!.later! } + | earlier ',' list_elements { result = EDTF::Set.new([val[0]] + val[2]).earlier! } + | earlier ',' later { result = EDTF::Set.new([val[0]] + [val[2]]).earlier!.later! } + | list_elements ',' later { result = EDTF::Set.new(val[0] + [val[2]]).later! } + | list_elements { result = EDTF::Set.new(*val[0]) } + | later { result = EDTF::Set.new(val[0]).later! } + ; + + list_elements : list_element { result = [val[0]].flatten } + | list_elements ',' list_element { result = val[0] + [val[2]].flatten } + ; + + list_element : atomic + | consecutives + ; + + atomic : date + | partial_uncertain_or_approximate + | unspecified + ; + + earlier : DOTS date { result = val[1] } + + later : year_month_day DOTS { result = Date.new(*val[0]).year_precision! } + | year_month DOTS { result = Date.new(*val[0]).month_precision! } + | year DOTS { result = Date.new(val[0]).year_precision! } + ; + + consecutives : year_month_day DOTS year_month_day { result = (Date.new(val[0]).day_precision! .. Date.new(val[2]).day_precision!) } + | year_month DOTS year_month { result = (Date.new(val[0]).month_precision! .. Date.new(val[2]).month_precision!) } + | year DOTS year { result = (Date.new(val[0]).year_precision! .. Date.new(val[2]).year_precision!) } + ; + + partial_unspecified : + unspecified_year '-' month '-' day + { + result = Date.new(val[0][0], val[2], val[4]) + result.unspecified.year[2,2] = val[0][1] + } + | unspecified_year '-' U U '-' day + { + result = Date.new(val[0][0], 1, val[5]) + result.unspecified.year[2,2] = val[0][1] + result.unspecified!(:month) + } + | unspecified_year '-' U U '-' U U + { + result = Date.new(val[0][0], 1, 1) + result.unspecified.year[2,2] = val[0][1] + result.unspecified!([:month, :day]) + } + | unspecified_year '-' month '-' U U + { + result = Date.new(val[0][0], val[2], 1) + result.unspecified.year[2,2] = val[0][1] + result.unspecified!(:day) + } + | year '-' U U '-' day + { + result = Date.new(val[0], 1, val[5]) + result.unspecified!(:month) + } + ; + + + partial_uncertain_or_approximate : pua_base + | '(' pua_base ')' UA { result = uoa(val[1], val[3]) } + + pua_base : + pua_year { result = val[0].year_precision! } + | pua_year_month { result = val[0][0].month_precision! } + | pua_year_month_day { result = val[0].day_precision! } + + pua_year : year UA { result = uoa(Date.new(val[0]), val[1], :year) } + + pua_year_month : + pua_year '-' month ua { + result = [uoa(val[0].change(:month => val[2]), val[3], [:month, :year])] + } + | year '-' month UA { + result = [uoa(Date.new(val[0], val[2]), val[3], [:year, :month])] + } + | year '-(' month ')' UA { + result = [uoa(Date.new(val[0], val[2]), val[4], [:month]), true] + } + | pua_year '-(' month ')' UA { + result = [uoa(val[0].change(:month => val[2]), val[4], [:month]), true] + } + ; + + pua_year_month_day : + pua_year_month '-' day ua { + result = uoa(val[0][0].change(:day => val[2]), val[3], val[0][1] ? [:day] : nil) + } + | pua_year_month '-(' day ')' UA { + result = uoa(val[0][0].change(:day => val[2]), val[4], [:day]) + } + | year '-(' month ')' UA day ua { + result = uoa(uoa(Date.new(val[0], val[2], val[5]), val[4], :month), val[6], :day) + } + | year_month '-' day UA { + result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[3]) + } + | year_month '-(' day ')' UA { + result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[4], [:day]) + } + | year '-(' month '-' day ')' UA { + result = uoa(Date.new(val[0], val[2], val[4]), val[6], [:month, :day]) + } + | year '-(' month '-(' day ')' UA ')' UA { + result = Date.new(val[0], val[2], val[4]) + result = uoa(result, val[6], [:day]) + result = uoa(result, val[8], [:month, :day]) + } + | pua_year '-(' month '-' day ')' UA { + result = val[0].change(:month => val[2], :day => val[4]) + result = uoa(result, val[6], [:month, :day]) + } + | pua_year '-(' month '-(' day ')' UA ')' UA { + result = val[0].change(:month => val[2], :day => val[4]) + result = uoa(result, val[6], [:day]) + result = uoa(result, val[8], [:month, :day]) + } + # | '(' pua_year '-(' month ')' UA ')' UA '-' day ua { + # result = val[1].change(:month => val[3], :day => val[9]) + # result = uoa(result, val[5], [:month]) + # result = [uoa(result, val[7], [:year]), true] + # } + ; + + ua : { result = [] } | UA + + # ---- Auxiliary Rules ---- + + digit : '0' { result = 0 } + | positive_digit + ; + + positive_digit : '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + + d01_12 : '0' positive_digit { result = val[1] } + | '1' '0' { result = 10 } + | '1' '1' { result = 11 } + | '1' '2' { result = 12 } + ; + + d01_13 : d01_12 + | '1' '3' { result = 13 } + ; + + d01_23 : '0' positive_digit { result = val[1] } + | '1' digit { result = 10 + val[1] } + | '2' '0' { result = 20 } + | '2' '1' { result = 21 } + | '2' '2' { result = 22 } + | '2' '3' { result = 23 } + ; + + d00_23 : '0' '0' + | d01_23 + ; + + d01_29 : d01_23 + | '2' '4' { result = 24 } + | '2' '5' { result = 25 } + | '2' '6' { result = 26 } + | '2' '7' { result = 27 } + | '2' '8' { result = 28 } + | '2' '9' { result = 29 } + ; + + d01_30 : d01_29 + | '3' '0' { result = 30 } + ; + + d01_31 : d01_30 + | '3' '1' { result = 31 } + ; + + d01_59 : d01_29 + | '3' digit { result = 30 + val[1] } + | '4' digit { result = 40 + val[1] } + | '5' digit { result = 50 + val[1] } + ; + + d00_59 : '0' '0' + | d01_59 + ; + + int1_4 : positive_digit { result = val[0] } + | positive_digit digit { result = 10 * val[0] + val[1] } + | positive_digit digit digit + { + result = val.zip([100,10,1]).reduce(0) { |s,(a,b)| s += a * b } + } + | positive_digit digit digit digit + { + result = val.zip([1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b } + } + ; + + integer : positive_digit { result = val[0] } + | integer digit { result = 10 * val[0] + val[1] } + ; + + + +---- header +require 'strscan' + +---- inner + + @defaults = { + :level => 2, + :debug => false + }.freeze + + class << self; attr_reader :defaults; end + + attr_reader :options + + def initialize(options = {}) + @options = Parser.defaults.merge(options) + end + + def debug? + !!(options[:debug] || ENV['DEBUG']) + end + + def parse(input) + parse!(input) + rescue => e + warn e.message if debug? + nil + end + + def parse!(input) + @yydebug = debug? + @src = StringScanner.new(input) + do_parse + end + + def on_error(tid, value, stack) + raise ArgumentError, + "failed to parse date: unexpected '#{value}' at #{stack.inspect}" + end + + def apply_uncertainty(date, uncertainty, scope = nil) + uncertainty.each do |u| + scope.nil? ? date.send(u) : date.send(u, scope) + end + date + end + + alias uoa apply_uncertainty + + def next_token + case + when @src.eos? + nil + # when @src.scan(/\s+/) + # ignore whitespace + when @src.scan(/\(/) + ['(', @src.matched] + # when @src.scan(/\)\?~-/) + # [:PUA, [:uncertain!, :approximate!]] + # when @src.scan(/\)\?-/) + # [:PUA, [:uncertain!]] + # when @src.scan(/\)~-/) + # [:PUA, [:approximate!]] + when @src.scan(/\)/) + [')', @src.matched] + when @src.scan(/\[/) + ['[', @src.matched] + when @src.scan(/\]/) + [']', @src.matched] + when @src.scan(/\{/) + ['{', @src.matched] + when @src.scan(/\}/) + ['}', @src.matched] + when @src.scan(/T/) + [:T, @src.matched] + when @src.scan(/Z/) + [:Z, @src.matched] + when @src.scan(/\?~/) + [:UA, [:uncertain!, :approximate!]] + when @src.scan(/\?/) + [:UA, [:uncertain!]] + when @src.scan(/~/) + [:UA, [:approximate!]] + when @src.scan(/open/i) + [:OPEN, :open] + when @src.scan(/unkn?own/i) # matches 'unkown' typo too + [:UNKNOWN, :unknown] + when @src.scan(/u/) + [:U, @src.matched] + when @src.scan(/x/i) + [:X, @src.matched] + when @src.scan(/y/) + [:LONGYEAR, @src.matched] + when @src.scan(/e/) + [:E, @src.matched] + when @src.scan(/\+/) + ['+', @src.matched] + when @src.scan(/-\(/) + ['-(', @src.matched] + when @src.scan(/-/) + ['-', @src.matched] + when @src.scan(/:/) + [':', @src.matched] + when @src.scan(/\//) + ['/', @src.matched] + when @src.scan(/\s*\.\.\s*/) + [:DOTS, '..'] + when @src.scan(/\s*,\s*/) + [',', ','] + when @src.scan(/\^\w+/) + ['^', @src.matched[1..-1]] + when @src.scan(/\d/) + [@src.matched, @src.matched.to_i] + else @src.scan(/./) + [:UNMATCHED, @src.rest] + end + end + + +# -*- racc -*- diff --git a/test/assets/empty.y b/test/assets/empty.y new file mode 100644 index 00000000..16422a9e --- /dev/null +++ b/test/assets/empty.y @@ -0,0 +1,5 @@ +class Empty + +token A B C + +end \ No newline at end of file diff --git a/test/assets/empty_user_code.y b/test/assets/empty_user_code.y new file mode 100644 index 00000000..983c5388 --- /dev/null +++ b/test/assets/empty_user_code.y @@ -0,0 +1,9 @@ +class Test1 +rule +main : A; +end + +# empty line at last + + + diff --git a/test/assets/error_recovery.y b/test/assets/error_recovery.y new file mode 100644 index 00000000..1fd21ac7 --- /dev/null +++ b/test/assets/error_recovery.y @@ -0,0 +1,35 @@ +# Regression test case for the bug discussed here: +# https://github.com/whitequark/parser/issues/93 +# In short, a Racc-generated parser could go into an infinite loop when +# attempting error recovery at EOF + +class InfiniteLoop + +rule + + stmts: stmt + | error stmt + + stmt: '%' stmt + +end + +---- inner + + def parse + @errors = [] + do_parse + end + + def next_token + nil + end + + def on_error(error_token, error_value, value_stack) + # oh my, an error + @errors << [error_token, error_value] + end + +---- footer + +InfiniteLoop.new.parse \ No newline at end of file diff --git a/test/assets/eye-of-newt.y b/test/assets/eye-of-newt.y new file mode 100644 index 00000000..dff329f0 --- /dev/null +++ b/test/assets/eye-of-newt.y @@ -0,0 +1,99 @@ +class EyeOfNewt::Parser +token WORD NUMBER UNIT TEXT OF OR A TO_TASTE UNIT_MODIFIER +rule + ingredient + : quantity ingredient_names style note + | quantity ingredient_names note + | ingredient_names to_taste style note + | ingredient_names to_taste note + | ingredient_names style note + | ingredient_names note + | quantity ingredient_names style + | quantity ingredient_names + | ingredient_names to_taste style + | ingredient_names to_taste + | ingredient_names style + | ingredient_names + ; + ingredient_names + : ingredient_name OR ingredient_names + | ingredient_name + ; + ingredient_name + : ingredient_words { @ingredient.names << result } + ; + quantity + : amount unit_modifier unit OF + | amount unit_modifier unit + | amount unit OF + | amount unit + | amount unit_modifier OF + | amount unit_modifier + | amount OF + | amount + | unit_modifier unit OF + | unit_modifier unit + | unit OF + | unit + ; + amount + : numerical_amount { @ingredient.amount = result } + | numerical_range { @ingredient.amount = result } + | A { @ingredient.amount = 1 } + ; + unit : UNIT { @ingredient.unit = to_unit(result) } ; + to_taste : TO_TASTE { @ingredient.unit = to_unit(result) } ; + style : ',' text { @ingredient.style = val[1] } ; + note : '(' text ')' { @ingredient.note = val[1] } ; + unit_modifier + : UNIT_MODIFIER { @ingredient.unit_modifier = val[0] } + | '(' text ')' { @ingredient.unit_modifier = val[1] } + ; + numerical_range + : numerical_amount '-' numerical_amount { result = [val[0], val[2]] } + | numerical_amount '–' numerical_amount { result = [val[0], val[2]] } + ; + numerical_amount + : number + | number fraction { result = val[0] + val[1] } + | fraction + | decimal + ; + ingredient_words + : ingredient_word ingredient_words { result = val.join(' ') } + | ingredient_word + ; + text : TEXT ; + ingredient_word : WORD | A | OF | UNIT_MODIFIER ; + number : NUMBER { result = val[0].to_i } ; + fraction : NUMBER '/' NUMBER { result = val[0].to_f / val[2].to_f } ; + decimal : NUMBER '.' NUMBER { result = val.join.to_f } ; +end + +---- inner + + def initialize(tokenizer, units:, ingredient: nil) + @tokenizer = tokenizer + @units = units + @ingredient = ingredient || default_ingredient + super() + end + + def next_token + @tokenizer.next_token + end + + def parse + do_parse + @ingredient + rescue Racc::ParseError + raise InvalidIngredient, @tokenizer.string + end + + def to_unit(u) + @units[u] + end + + def default_ingredient + EyeOfNewt::Ingredient.new(amount: 1, unit: @units.default) + end diff --git a/test/assets/huia.y b/test/assets/huia.y new file mode 100644 index 00000000..a26a26f2 --- /dev/null +++ b/test/assets/huia.y @@ -0,0 +1,318 @@ +# Copyright (c) 2014 James Harton +# +# MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +class Huia::Parser + + token + IDENTIFIER EQUAL PLUS MINUS ASTERISK FWD_SLASH COLON FLOAT INTEGER STRING + EXPO INDENT OUTDENT OPAREN CPAREN DOT SIGNATURE NL EOF PIPE COMMA NIL TRUE + FALSE EQUALITY CALL SELF CONSTANT CHAR DOUBLE_TICK_STRING + DOUBLE_TICK_STRING_END INTERPOLATE_START INTERPOLATE_END BOX LSQUARE + RSQUARE FACES LFACE RFACE BANG TILDE RETURN NOT_EQUALITY OR AND GT LT + GTE LTE AT PERCENT + + prechigh + left EXPO + left BANG TILDE + left ASTERISK FWD_SLASH PERCENT + left PLUS MINUS + + right EQUAL + preclow + + rule + statements: statement + | statements statement { return scope } + + statement: expr eol { return scope.append val[0] } + | expr { return scope.append val[0] } + | eol { return scope } + + eol: NL | EOF + nlq: NL | + + expr: literal + | grouped_expr + | binary_op + | unary_op + | method_call + | constant + | variable + | array + | hash + | return + + return: return_expr + | return_nil + return_expr: RETURN expr { return n(:Return, val[1]) } + return_nil: RETURN { return n(:Return, n(:Nil)) } + + array: empty_array + | array_list + + empty_array: BOX { return n :Array } + + array_list: LSQUARE array_items RSQUARE { return val[1] } + array_items: expr { return n :Array, [val[0]] } + | array_items COMMA expr { val[0].append(val[2]); return val[0] } + + hash: empty_hash + | hash_list + empty_hash: FACES { return n :Hash } + hash_list: LFACE hash_items RFACE { return val[1] } + hash_items: hash_item { return n :Hash, val[0] } + | hash_items COMMA hash_item { val[0].append(val[2]); return val[0] } + hash_item: expr COLON expr { return n :HashItem, val[0], val[2] } + + constant: CONSTANT { return constant val[0] } + + indented: indented_w_stmts + | indented_w_expr + | indented_wo_stmts + indented_w_stmts: indent statements outdent { return val[0] } + indented_w_expr: indent expr outdent { return val[0].append(val[1]) } + indented_wo_stmts: indent outdent { return val[0] } + outdent: OUTDENT { return pop_scope } + + + indent_w_args: indent_pipe indent_args PIPE nlq INDENT { return val[0] } + indent_pipe: PIPE { return push_scope } + indent_wo_args: INDENT { return push_scope } + indent: indent_w_args + | indent_wo_args + + indent_args: indent_arg + | indent_args COMMA indent_arg + indent_arg: arg_var { return scope.add_argument val[0] } + | arg_var EQUAL expr { return n :Assignment, val[0], val[2] } + arg_var: IDENTIFIER { return n :Variable, val[0] } + + method_call: method_call_on_object + | method_call_on_self + | method_call_on_closure + method_call_on_object: expr DOT call_signature { return n :MethodCall, val[0], val[2] } + | expr DOT IDENTIFIER { return n :MethodCall, val[0], n(:CallSignature, val[2]) } + method_call_on_self: call_signature { return n :MethodCall, scope_instance, val[0] } + + method_call_on_closure: AT call_signature { return n :MethodCall, this_closure, val[1] } + | AT IDENTIFIER { return n :MethodCall, this_closure, n(:CallSignature, val[1]) } + + call_signature: call_arguments + | call_simple_name + call_simple_name: CALL { return n :CallSignature, val[0] } + call_argument: SIGNATURE call_passed_arg { return n :CallSignature, val[0], [val[1]] } + call_passed_arg: call_passed_simple + | call_passed_indented + call_passed_simple: expr + | expr NL + call_passed_indented: indented + | indented NL + call_arguments: call_argument { return val[0] } + | call_arguments call_argument { return val[0].concat_signature val[1] } + + grouped_expr: OPAREN expr CPAREN { return n :Expression, val[1] } + + variable: IDENTIFIER { return allocate_local val[0] } + + binary_op: assignment + | addition + | subtraction + | multiplication + | division + | exponentiation + | modulo + | equality + | not_equality + | logical_or + | logical_and + | greater_than + | less_than + | greater_or_eq + | less_or_eq + + assignment: IDENTIFIER EQUAL expr { return allocate_local_assignment val[0], val[2] } + addition: expr PLUS expr { return binary val[0], val[2], 'plus:' } + subtraction: expr MINUS expr { return binary val[0], val[2], 'minus:' } + multiplication: expr ASTERISK expr { return binary val[0], val[2], 'multiplyBy:' } + division: expr FWD_SLASH expr { return binary val[0], val[2], 'divideBy:' } + exponentiation: expr EXPO expr { return binary val[0], val[2], 'toThePowerOf:' } + modulo: expr PERCENT expr { return binary val[0], val[2], 'moduloOf:' } + equality: expr EQUALITY expr { return binary val[0], val[2], 'isEqualTo:' } + not_equality: expr NOT_EQUALITY expr { return binary val[0], val[2], 'isNotEqualTo:' } + logical_or: expr OR expr { return binary val[0], val[2], 'logicalOr:' } + logical_and: expr AND expr { return binary val[0], val[2], 'logicalAnd:' } + greater_than: expr GT expr { return binary val[0], val[2], 'isGreaterThan:' } + less_than: expr LT expr { return binary val[0], val[2], 'isLessThan:' } + greater_or_eq: expr GTE expr { return binary val[0], val[2], 'isGreaterOrEqualTo:' } + less_or_eq: expr LTE expr { return binary val[0], val[2], 'isLessOrEqualTo:' } + + unary_op: unary_not + | unary_plus + | unary_minus + | unary_complement + + unary_not: BANG expr { return unary val[1], 'unaryNot' } + unary_plus: PLUS expr { return unary val[1], 'unaryPlus' } + unary_minus: MINUS expr { return unary val[1], 'unaryMinus' } + unary_complement: TILDE expr { return unary val[1], 'unaryComplement' } + + literal: integer + | float + | string + | nil + | true + | false + | self + + float: FLOAT { return n :Float, val[0] } + integer: INTEGER { return n :Integer, val[0] } + nil: NIL { return n :Nil } + true: TRUE { return n :True } + false: FALSE { return n :False } + self: SELF { return n :Self } + + string: STRING { return n :String, val[0] } + | interpolated_string + | empty_string + + interpolated_string: DOUBLE_TICK_STRING interpolated_string_contents DOUBLE_TICK_STRING_END { return val[1] } + interpolation: INTERPOLATE_START expr INTERPOLATE_END { return val[1] } + interpolated_string_contents: interpolated_string_chunk { return n :InterpolatedString, val[0] } + | interpolated_string_contents interpolated_string_chunk { val[0].append(val[1]); return val[0] } + interpolated_string_chunk: chars { return val[0] } + | interpolation { return to_string(val[0]) } + empty_string: DOUBLE_TICK_STRING DOUBLE_TICK_STRING_END { return n :String, '' } + + chars: CHAR { return n :String, val[0] } + | chars CHAR { val[0].append(val[1]); return val[0] } +end + +---- inner + +attr_accessor :lexer, :scopes, :state + +def initialize lexer + @lexer = lexer + @state = [] + @scopes = [] + push_scope +end + +def ast + @ast ||= do_parse + @scopes.first +end + +def on_error t, val, vstack + line = lexer.line + col = lexer.column + message = "Unexpected #{token_to_str t} at #{lexer.filename} line #{line}:#{col}:\n\n" + + start = line - 5 > 0 ? line - 5 : 0 + i_size = line.to_s.size + (start..(start + 5)).each do |i| + message << sprintf("\t%#{i_size}d: %s\n", i, lexer.get_line(i)) + message << "\t#{' ' * i_size} #{'-' * (col - 1)}^\n" if i == line + end + + raise SyntaxError, message +end + +def next_token + nt = lexer.next_computed_token + # just use a state stack for now, we'll have to do something + # more sophisticated soon. + if nt && nt.first == :state + if nt.last + state.push << nt.last + else + state.pop + end + next_token + else + nt + end +end + +def push_scope + new_scope = Huia::AST::Scope.new scope + new_scope.file = lexer.filename + new_scope.line = lexer.line + new_scope.column = lexer.column + scopes.push new_scope + new_scope +end + +def pop_scope + scopes.pop +end + +def scope + scopes.last +end + +def binary left, right, method + node(:MethodCall, left, node(:CallSignature, method, [right])) +end + +def unary left, method + node(:MethodCall, left, node(:CallSignature, method)) +end + +def node type, *args + Huia::AST.const_get(type).new(*args).tap do |n| + n.file = lexer.filename + n.line = lexer.line + n.column = lexer.column + end +end +alias n node + +def allocate_local name + node(:Variable, name).tap do |n| + scope.allocate_local n + end +end + +def allocate_local_assignment name, value + node(:Assignment, name, value).tap do |n| + scope.allocate_local n + end +end + +def this_closure + allocate_local('@') +end + +def scope_instance + node(:ScopeInstance, scope) +end + +def constant name + return scope_instance if name == 'self' + node(:Constant, name) +end + +def to_string expr + node(:MethodCall, expr, node(:CallSignature, 'toString')) +end diff --git a/test/infini.y b/test/assets/infini.y similarity index 100% rename from test/infini.y rename to test/assets/infini.y diff --git a/test/assets/intp.y b/test/assets/intp.y index 24e547da..d1e72fdc 100644 --- a/test/assets/intp.y +++ b/test/assets/intp.y @@ -27,7 +27,7 @@ rule result.push val[1] } | stmt_list EOL - + stmt : expr | assign | IDENT realprim @@ -38,7 +38,7 @@ rule | if_stmt | while_stmt | defun - + if_stmt : IF stmt THEN EOL stmt_list else_stmt END { result = IfNode.new( @fname, val[0][0], @@ -261,7 +261,7 @@ module Intp class Core - def initialize + def initialize @ftab = {} @obj = Object.new @stack = [] @@ -318,7 +318,7 @@ module Intp def lvar?(name) @lvars.key? name end - + def [](key) @lvars[key] end @@ -534,7 +534,7 @@ end # module Intp begin tree = nil - fname = 'src.intp' + fname = 'test/assets/src.intp' File.open(fname) {|f| tree = Intp::Parser.new.parse(f, fname) } diff --git a/test/assets/journey.y b/test/assets/journey.y new file mode 100644 index 00000000..c2640f33 --- /dev/null +++ b/test/assets/journey.y @@ -0,0 +1,47 @@ +class Journey::Parser + +token SLASH LITERAL SYMBOL LPAREN RPAREN DOT STAR OR + +rule + expressions + : expressions expression { result = Cat.new(val.first, val.last) } + | expression { result = val.first } + | or + ; + expression + : terminal + | group + | star + ; + group + : LPAREN expressions RPAREN { result = Group.new(val[1]) } + ; + or + : expressions OR expression { result = Or.new([val.first, val.last]) } + ; + star + : STAR { result = Star.new(Symbol.new(val.last)) } + ; + terminal + : symbol + | literal + | slash + | dot + ; + slash + : SLASH { result = Slash.new('/') } + ; + symbol + : SYMBOL { result = Symbol.new(val.first) } + ; + literal + : LITERAL { result = Literal.new(val.first) } + dot + : DOT { result = Dot.new(val.first) } + ; + +end + +---- header + +require 'journey/parser_extras' diff --git a/test/assets/liquor.y b/test/assets/liquor.y new file mode 100644 index 00000000..c9622f6b --- /dev/null +++ b/test/assets/liquor.y @@ -0,0 +1,313 @@ +# Copyright (c) 2012-2013 Peter Zotov +# 2012 Yaroslav Markin +# 2012 Nate Gadgibalaev +# +# MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +class Liquor::Parser + token comma dot endtag ident integer keyword lblock lblock2 lbracket + linterp lparen op_div op_eq op_gt op_geq op_lt op_leq op_minus + op_mod op_mul op_neq op_not op_plus op_and op_or pipe plaintext + rblock rbracket rinterp rparen string tag_ident + + prechigh + left dot + nonassoc op_uminus op_not + left op_mul op_div op_mod + left op_plus op_minus + left op_eq op_neq op_lt op_leq op_gt op_geq + left op_and + left op_or + preclow + + expect 15 + + start block + +rule + block: /* empty */ + { result = [] } + | plaintext block + { result = [ val[0], *val[1] ] } + | interp block + { result = [ val[0], *val[1] ] } + | tag block + { result = [ val[0], *val[1] ] } + + interp: + linterp expr rinterp + { result = [ :interp, retag(val), val[1] ] } + | linterp filter_chain rinterp + { result = [ :interp, retag(val), val[1] ] } + + primary_expr: + ident + | lparen expr rparen + { result = [ val[1][0], retag(val), *val[1][2..-1] ] } + + expr: + integer + | string + | tuple + | ident function_args + { result = [ :call, retag(val), val[0], val[1] ] } + | expr lbracket expr rbracket + { result = [ :index, retag(val), val[0], val[2] ] } + | expr dot ident function_args + { result = [ :external, retag(val), val[0], val[2], val[3] ] } + | expr dot ident + { result = [ :external, retag(val), val[0], val[2], nil ] } + | op_minus expr =op_uminus + { result = [ :uminus, retag(val), val[1] ] } + | op_not expr + { result = [ :not, retag(val), val[1] ] } + | expr op_mul expr + { result = [ :mul, retag(val), val[0], val[2] ] } + | expr op_div expr + { result = [ :div, retag(val), val[0], val[2] ] } + | expr op_mod expr + { result = [ :mod, retag(val), val[0], val[2] ] } + | expr op_plus expr + { result = [ :plus, retag(val), val[0], val[2] ] } + | expr op_minus expr + { result = [ :minus, retag(val), val[0], val[2] ] } + | expr op_eq expr + { result = [ :eq, retag(val), val[0], val[2] ] } + | expr op_neq expr + { result = [ :neq, retag(val), val[0], val[2] ] } + | expr op_lt expr + { result = [ :lt, retag(val), val[0], val[2] ] } + | expr op_leq expr + { result = [ :leq, retag(val), val[0], val[2] ] } + | expr op_gt expr + { result = [ :gt, retag(val), val[0], val[2] ] } + | expr op_geq expr + { result = [ :geq, retag(val), val[0], val[2] ] } + | expr op_and expr + { result = [ :and, retag(val), val[0], val[2] ] } + | expr op_or expr + { result = [ :or, retag(val), val[0], val[2] ] } + | primary_expr + + tuple: + lbracket tuple_content rbracket + { result = [ :tuple, retag(val), val[1].compact ] } + + tuple_content: + expr comma tuple_content + { result = [ val[0], *val[2] ] } + | expr + { result = [ val[0] ] } + | /* empty */ + { result = [ ] } + + function_args: + lparen function_args_inside rparen + { result = [ :args, retag(val), *val[1] ] } + + function_args_inside: + expr function_keywords + { result = [ val[0], val[1][2] ] } + | function_keywords + { result = [ nil, val[0][2] ] } + + function_keywords: + keyword expr function_keywords + { name = val[0][2].to_sym + tail = val[2][2] + loc = retag([ val[0], val[1] ]) + + if tail.include? name + @errors << SyntaxError.new("duplicate keyword argument `#{val[0][2]}'", + tail[name][1]) + end + + hash = { + name => [ val[1][0], loc, *val[1][2..-1] ] + }.merge(tail) + + result = [ :keywords, retag([ loc, val[2] ]), hash ] + } + | /* empty */ + { result = [ :keywords, nil, {} ] } + + filter_chain: + expr pipe filter_chain_cont + { result = [ val[0], *val[2] ]. + reduce { |tree, node| node[3][2] = tree; node } + } + + filter_chain_cont: + filter_call pipe filter_chain_cont + { result = [ val[0], *val[2] ] } + | filter_call + { result = [ val[0] ] } + + filter_call: + ident function_keywords + { ident_loc = val[0][1] + empty_args_loc = { line: ident_loc[:line], + start: ident_loc[:end] + 1, + end: ident_loc[:end] + 1, } + result = [ :call, val[0][1], val[0], + [ :args, val[1][1] || empty_args_loc, nil, val[1][2] ] ] + } + + tag: + lblock ident expr tag_first_cont + { result = [ :tag, retag(val), val[1], val[2], *reduce_tag_args(val[3][2]) ] } + | lblock ident tag_first_cont + { result = [ :tag, retag(val), val[1], nil, *reduce_tag_args(val[2][2]) ] } + + # Racc cannot do lookahead across rules. I had to add states + # explicitly to avoid S/R conflicts. You are not expected to + # understand this. + + tag_first_cont: + rblock + { result = [ :cont, retag(val), [] ] } + | keyword tag_first_cont2 + { result = [ :cont, retag(val), [ val[0], *val[1][2] ] ] } + + tag_first_cont2: + rblock block lblock2 tag_next_cont + { result = [ :cont2, val[0][1], [ [:block, val[0][1], val[1] ], *val[3] ] ] } + | expr tag_first_cont + { result = [ :cont2, retag(val), [ val[0], *val[1][2] ] ] } + + tag_next_cont: + endtag rblock + { result = [] } + | keyword tag_next_cont2 + { result = [ val[0], *val[1] ] } + + tag_next_cont2: + rblock block lblock2 tag_next_cont + { result = [ [:block, val[0][1], val[1] ], *val[3] ] } + | expr keyword tag_next_cont3 + { result = [ val[0], val[1], *val[2] ] } + + tag_next_cont3: + rblock block lblock2 tag_next_cont + { result = [ [:block, val[0][1], val[1] ], *val[3] ] } + | expr tag_next_cont + { result = [ val[0], *val[1] ] } + +---- inner + attr_reader :errors, :ast + + def initialize(tags={}) + super() + + @errors = [] + @ast = nil + @tags = tags + end + + def success? + @errors.empty? + end + + def parse(string, name='(code)') + @errors.clear + @name = name + @ast = nil + + begin + @stream = Lexer.lex(string, @name, @tags) + @ast = do_parse + rescue Liquor::SyntaxError => e + @errors << e + end + + success? + end + + def next_token + tok = @stream.shift + [ tok[0], tok ] if tok + end + + TOKEN_NAME_MAP = { + :comma => ',', + :dot => '.', + :lblock => '{%', + :rblock => '%}', + :linterp => '{{', + :rinterp => '}}', + :lbracket => '[', + :rbracket => ']', + :lparen => '(', + :rparen => ')', + :pipe => '|', + :op_not => '!', + :op_mul => '*', + :op_div => '/', + :op_mod => '%', + :op_plus => '+', + :op_minus => '-', + :op_eq => '==', + :op_neq => '!=', + :op_lt => '<', + :op_leq => '<=', + :op_gt => '>', + :op_geq => '>=', + :keyword => 'keyword argument name', + :kwarg => 'keyword argument', + :ident => 'identifier', + } + + def on_error(error_token_id, error_token, value_stack) + if token_to_str(error_token_id) == "$end" + raise Liquor::SyntaxError.new("unexpected end of program", { + file: @name + }) + else + type, (loc, value) = error_token + type = TOKEN_NAME_MAP[type] || type + + raise Liquor::SyntaxError.new("unexpected token `#{type}'", loc) + end + end + + def retag(nodes) + loc = nodes.map { |node| node[1] }.compact + first, *, last = loc + return first if last.nil? + + { + file: first[:file], + line: first[:line], + start: first[:start], + end: last[:end], + } + end + + def reduce_tag_args(list) + list.each_slice(2).reduce([]) { |args, (k, v)| + if v[0] == :block + args << [ :blockarg, retag([ k, v ]), k, v[2] || [] ] + else + args << [ :kwarg, retag([ k, v ]), k, v ] + end + } + end \ No newline at end of file diff --git a/test/assets/lr_not_lalr.y b/test/assets/lr_not_lalr.y new file mode 100644 index 00000000..0aa1225a --- /dev/null +++ b/test/assets/lr_not_lalr.y @@ -0,0 +1,12 @@ +# This grammar is LR(1), but not LALR(1) + +class LrNotLalr + +rule + S: a E a + | b E b + | a F b + | b F a + + E: e + F: e \ No newline at end of file diff --git a/test/assets/lr_not_lalr2.y b/test/assets/lr_not_lalr2.y new file mode 100644 index 00000000..458dcbda --- /dev/null +++ b/test/assets/lr_not_lalr2.y @@ -0,0 +1,15 @@ + +class LrNotLalr2 + +rule + S: '(' X + | E ']' + | F ')' + + X: E ')' + | F ']' + + E: A + F: A + + A: # null \ No newline at end of file diff --git a/test/assets/machete.y b/test/assets/machete.y new file mode 100644 index 00000000..ea92d47a --- /dev/null +++ b/test/assets/machete.y @@ -0,0 +1,423 @@ +# Copyright (c) 2011 SUSE +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +class Machete::Parser + +token NIL +token TRUE +token FALSE +token INTEGER +token SYMBOL +token STRING +token REGEXP +token ANY +token EVEN +token ODD +token METHOD_NAME +token CLASS_NAME + +start expression + +rule + +expression : primary + | expression "|" primary { + result = if val[0].is_a?(ChoiceMatcher) + ChoiceMatcher.new(val[0].alternatives << val[2]) + else + ChoiceMatcher.new([val[0], val[2]]) + end + } + +primary : node + | array + | literal + | any + +node : CLASS_NAME { + result = NodeMatcher.new(val[0].to_sym) + } + | CLASS_NAME "<" attrs ">" { + result = NodeMatcher.new(val[0].to_sym, val[2]) + } + +attrs : attr + | attrs "," attr { result = val[0].merge(val[2]) } + +attr : method_name "=" expression { result = { val[0].to_sym => val[2] } } + | method_name "^=" SYMBOL { + result = { + val[0].to_sym => SymbolRegexpMatcher.new( + Regexp.new("^" + Regexp.escape(symbol_value(val[2]).to_s)) + ) + } + } + | method_name "$=" SYMBOL { + result = { + val[0].to_sym => SymbolRegexpMatcher.new( + Regexp.new(Regexp.escape(symbol_value(val[2]).to_s) + "$") + ) + } + } + | method_name "*=" SYMBOL { + result = { + val[0].to_sym => SymbolRegexpMatcher.new( + Regexp.new(Regexp.escape(symbol_value(val[2]).to_s)) + ) + } + } + | method_name "^=" STRING { + result = { + val[0].to_sym => StringRegexpMatcher.new( + Regexp.new("^" + Regexp.escape(string_value(val[2]))) + ) + } + } + | method_name "$=" STRING { + result = { + val[0].to_sym => StringRegexpMatcher.new( + Regexp.new(Regexp.escape(string_value(val[2])) + "$") + ) + } + } + | method_name "*=" STRING { + result = { + val[0].to_sym => StringRegexpMatcher.new( + Regexp.new(Regexp.escape(string_value(val[2]))) + ) + } + } + | method_name "*=" REGEXP { + result = { + val[0].to_sym => IndifferentRegexpMatcher.new( + Regexp.new(regexp_value(val[2])) + ) + } + } + +# Hack to overcome the fact that some tokens will lex as simple tokens, not +# METHOD_NAME tokens, and that "reserved words" will lex as separate kinds of +# tokens. +method_name : METHOD_NAME + | NIL + | TRUE + | FALSE + | ANY + | EVEN + | ODD + | "*" + | "+" + | "<" + | ">" + | "^" + | "|" + +array : "[" items_opt "]" { result = ArrayMatcher.new(val[1]) } + +items_opt : /* empty */ { result = [] } + | items + +items : item { result = [val[0]] } + | items "," item { result = val[0] << val[2] } + +item : expression + | expression quantifier { result = Quantifier.new(val[0], *val[1]) } + +quantifier : "*" { result = [0, nil, 1] } + | "+" { result = [1, nil, 1] } + | "?" { result = [0, 1, 1] } + | "{" INTEGER "}" { + result = [integer_value(val[1]), integer_value(val[1]), 1] + } + | "{" INTEGER "," "}" { + result = [integer_value(val[1]), nil, 1] + } + | "{" "," INTEGER "}" { + result = [0, integer_value(val[2]), 1] + } + | "{" INTEGER "," INTEGER "}" { + result = [integer_value(val[1]), integer_value(val[3]), 1] + } + | "{" EVEN "}" { result = [0, nil, 2] } + | "{" ODD "}" { result = [1, nil, 2] } + +literal : NIL { result = LiteralMatcher.new(nil) } + | TRUE { result = LiteralMatcher.new(true) } + | FALSE { result = LiteralMatcher.new(false) } + | INTEGER { result = LiteralMatcher.new(integer_value(val[0])) } + | SYMBOL { result = LiteralMatcher.new(symbol_value(val[0])) } + | STRING { result = LiteralMatcher.new(string_value(val[0])) } + | REGEXP { result = LiteralMatcher.new(regexp_value(val[0])) } + +any : ANY { result = AnyMatcher.new } + +---- inner + +include Matchers + +class SyntaxError < StandardError; end + +def parse(input) + @input = input + @pos = 0 + + do_parse +end + +private + +def integer_value(value) + if value =~ /^0[bB]/ + value[2..-1].to_i(2) + elsif value =~ /^0[oO]/ + value[2..-1].to_i(8) + elsif value =~ /^0[dD]/ + value[2..-1].to_i(10) + elsif value =~ /^0[xX]/ + value[2..-1].to_i(16) + elsif value =~ /^0/ + value.to_i(8) + else + value.to_i + end +end + +def symbol_value(value) + value[1..-1].to_sym +end + +def string_value(value) + quote = value[0..0] + if quote == "'" + value[1..-2].gsub("\\\\", "\\").gsub("\\'", "'") + elsif quote == '"' + value[1..-2]. + gsub("\\\\", "\\"). + gsub('\\"', '"'). + gsub("\\n", "\n"). + gsub("\\t", "\t"). + gsub("\\r", "\r"). + gsub("\\f", "\f"). + gsub("\\v", "\v"). + gsub("\\a", "\a"). + gsub("\\e", "\e"). + gsub("\\b", "\b"). + gsub("\\s", "\s"). + gsub(/\\([0-7]{1,3})/) { $1.to_i(8).chr }. + gsub(/\\x([0-9a-fA-F]{1,2})/) { $1.to_i(16).chr } + else + raise "Unknown quote: #{quote.inspect}." + end +end + +REGEXP_OPTIONS = { + 'i' => Regexp::IGNORECASE, + 'm' => Regexp::MULTILINE, + 'x' => Regexp::EXTENDED +} + +def regexp_value(value) + /\A\/(.*)\/([imx]*)\z/ =~ value + pattern, options = $1, $2 + + Regexp.new(pattern, options.chars.map { |ch| REGEXP_OPTIONS[ch] }.inject(:|)) +end + +# "^" needs to be here because if it were among operators recognized by +# METHOD_NAME, "^=" would be recognized as two tokens. +SIMPLE_TOKENS = [ + "|", + "<", + ">", + ",", + "=", + "^=", + "^", + "$=", + "[", + "]", + "*=", + "*", + "+", + "?", + "{", + "}" +] + +COMPLEX_TOKENS = [ + [:NIL, /^nil/], + [:TRUE, /^true/], + [:FALSE, /^false/], + # INTEGER needs to be before METHOD_NAME, otherwise e.g. "+1" would be + # recognized as two tokens. + [ + :INTEGER, + /^ + [+-]? # sign + ( + 0[bB][01]+(_[01]+)* # binary (prefixed) + | + 0[oO][0-7]+(_[0-7]+)* # octal (prefixed) + | + 0[dD]\d+(_\d+)* # decimal (prefixed) + | + 0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)* # hexadecimal (prefixed) + | + 0[0-7]*(_[0-7]+)* # octal (unprefixed) + | + [1-9]\d*(_\d+)* # decimal (unprefixed) + ) + /x + ], + [ + :SYMBOL, + /^ + : + ( + # class name + [A-Z][a-zA-Z0-9_]* + | + # regular method name + [a-z_][a-zA-Z0-9_]*[?!=]? + | + # instance variable name + @[a-zA-Z_][a-zA-Z0-9_]* + | + # class variable name + @@[a-zA-Z_][a-zA-Z0-9_]* + | + # operator (sorted by length, then alphabetically) + (<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[%&*+\-\/<>^`|~]) + ) + /x + ], + [ + :STRING, + /^ + ( + ' # sinqle-quoted string + ( + \\[\\'] # escape + | + [^'] # regular character + )* + ' + | + " # double-quoted string + ( + \\ # escape + ( + [\\"ntrfvaebs] # one-character escape + | + [0-7]{1,3} # octal number escape + | + x[0-9a-fA-F]{1,2} # hexadecimal number escape + ) + | + [^"] # regular character + )* + " + ) + /x + ], + [ + :REGEXP, + /^ + \/ + ( + \\ # escape + ( + [\\\/ntrfvaebs\(\)\[\]\{\}\-\.\?\*\+\|\^\$] # one-character escape + | + [0-7]{2,3} # octal number escape + | + x[0-9a-fA-F]{1,2} # hexadecimal number escape + ) + | + [^\/] # regular character + )* + \/ + [imx]* + /x + ], + # ANY, EVEN and ODD need to be before METHOD_NAME, otherwise they would be + # recognized as method names. + [:ANY, /^any/], + [:EVEN, /^even/], + [:ODD, /^odd/], + # We exclude "*", "+", "<", ">", "^" and "|" from method names since they are + # lexed as simple tokens. This is because they have also other meanings in + # Machette patterns beside Ruby method names. + [ + :METHOD_NAME, + /^ + ( + # regular name + [a-z_][a-zA-Z0-9_]*[?!=]? + | + # operator (sorted by length, then alphabetically) + (<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[%&\-\/`~]) + ) + /x + ], + [:CLASS_NAME, /^[A-Z][a-zA-Z0-9_]*/] +] + +def next_token + skip_whitespace + + return false if remaining_input.empty? + + # Complex tokens need to be before simple tokens, otherwise e.g. "<<" would be + # recognized as two tokens. + + COMPLEX_TOKENS.each do |type, regexp| + if remaining_input =~ regexp + @pos += $&.length + return [type, $&] + end + end + + SIMPLE_TOKENS.each do |token| + if remaining_input[0...token.length] == token + @pos += token.length + return [token, token] + end + end + + raise SyntaxError, "Unexpected character: #{remaining_input[0..0].inspect}." +end + +def skip_whitespace + if remaining_input =~ /\A^[ \t\r\n]+/ + @pos += $&.length + end +end + +def remaining_input + @input[@pos..-1] +end + +def on_error(error_token_id, error_value, value_stack) + raise SyntaxError, "Unexpected token: #{error_value.inspect}." +end diff --git a/test/assets/macruby.y b/test/assets/macruby.y new file mode 100644 index 00000000..5ede0083 --- /dev/null +++ b/test/assets/macruby.y @@ -0,0 +1,2197 @@ +# Copyright (c) 2013 Peter Zotov +# +# Parts of the source are derived from ruby_parser: +# Copyright (c) Ryan Davis, seattle.rb +# +# MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +class Parser::MacRuby + +token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS + kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT + kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kDO_LAMBDA kRETURN kYIELD kSUPER + kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD + kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__ + k__FILE__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT + tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT + tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ + tGEQ tLEQ tANDOP tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF + tASET tLSHFT tRSHFT tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN + tLPAREN2 tRPAREN tLPAREN_ARG tLBRACK tLBRACK2 tRBRACK tLBRACE + tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2 tTILDE tPERCENT tDIVIDE + tPLUS tMINUS tLT tGT tPIPE tBANG tCARET tLCURLY tRCURLY + tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tREGEXP_OPT + tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END + tSTRING tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA tLAMBEG + tCHARACTER + +prechigh + right tBANG tTILDE tUPLUS + right tPOW + right tUMINUS_NUM tUMINUS + left tSTAR2 tDIVIDE tPERCENT + left tPLUS tMINUS + left tLSHFT tRSHFT + left tAMPER2 + left tPIPE tCARET + left tGT tGEQ tLT tLEQ + nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH + left tANDOP + left tOROP + nonassoc tDOT2 tDOT3 + right tEH tCOLON + left kRESCUE_MOD + right tEQL tOP_ASGN + nonassoc kDEFINED + right kNOT + left kOR kAND + nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD + nonassoc tLBRACE_ARG + nonassoc tLOWEST +preclow + +rule + + program: top_compstmt + + top_compstmt: top_stmts opt_terms + { + result = @builder.compstmt(val[0]) + } + + top_stmts: # nothing + { + result = [] + } + | top_stmt + { + result = [ val[0] ] + } + | top_stmts terms top_stmt + { + result = val[0] << val[2] + } + | error top_stmt + { + result = [ val[1] ] + } + + top_stmt: stmt + | klBEGIN tLCURLY top_compstmt tRCURLY + { + result = @builder.preexe(val[0], val[1], val[2], val[3]) + } + + bodystmt: compstmt opt_rescue opt_else opt_ensure + { + rescue_bodies = val[1] + else_t, else_ = val[2] + ensure_t, ensure_ = val[3] + + if rescue_bodies.empty? && !else_.nil? + diagnostic :warning, :useless_else, nil, else_t + end + + result = @builder.begin_body(val[0], + rescue_bodies, + else_t, else_, + ensure_t, ensure_) + } + + compstmt: stmts opt_terms + { + result = @builder.compstmt(val[0]) + } + + stmts: # nothing + { + result = [] + } + | stmt + { + result = [ val[0] ] + } + | stmts terms stmt + { + result = val[0] << val[2] + } + | error stmt + { + result = [ val[1] ] + } + + stmt: kALIAS fitem + { + @lexer.state = :expr_fname + } + fitem + { + result = @builder.alias(val[0], val[1], val[3]) + } + | kALIAS tGVAR tGVAR + { + result = @builder.alias(val[0], + @builder.gvar(val[1]), + @builder.gvar(val[2])) + } + | kALIAS tGVAR tBACK_REF + { + result = @builder.alias(val[0], + @builder.gvar(val[1]), + @builder.back_ref(val[2])) + } + | kALIAS tGVAR tNTH_REF + { + diagnostic :error, :nth_ref_alias, nil, val[2] + } + | kUNDEF undef_list + { + result = @builder.undef_method(val[0], val[1]) + } + | stmt kIF_MOD expr_value + { + result = @builder.condition_mod(val[0], nil, + val[1], val[2]) + } + | stmt kUNLESS_MOD expr_value + { + result = @builder.condition_mod(nil, val[0], + val[1], val[2]) + } + | stmt kWHILE_MOD expr_value + { + result = @builder.loop_mod(:while, val[0], val[1], val[2]) + } + | stmt kUNTIL_MOD expr_value + { + result = @builder.loop_mod(:until, val[0], val[1], val[2]) + } + | stmt kRESCUE_MOD stmt + { + rescue_body = @builder.rescue_body(val[1], + nil, nil, nil, + nil, val[2]) + + result = @builder.begin_body(val[0], [ rescue_body ]) + } + | klEND tLCURLY compstmt tRCURLY + { + result = @builder.postexe(val[0], val[1], val[2], val[3]) + } + | lhs tEQL command_call + { + result = @builder.assign(val[0], val[1], val[2]) + } + | mlhs tEQL command_call + { + result = @builder.multi_assign(val[0], val[1], val[2]) + } + | var_lhs tOP_ASGN command_call + { + result = @builder.op_assign(val[0], val[1], val[2]) + } + | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_call + { + result = @builder.op_assign( + @builder.index( + val[0], val[1], val[2], val[3]), + val[4], val[5]) + } + | primary_value tDOT tIDENTIFIER tOP_ASGN command_call + { + result = @builder.op_assign( + @builder.call_method( + val[0], val[1], val[2]), + val[3], val[4]) + } + | primary_value tDOT tCONSTANT tOP_ASGN command_call + { + result = @builder.op_assign( + @builder.call_method( + val[0], val[1], val[2]), + val[3], val[4]) + } + | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call + { + result = @builder.op_assign( + @builder.call_method( + val[0], val[1], val[2]), + val[3], val[4]) + } + | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call + { + result = @builder.op_assign( + @builder.call_method( + val[0], val[1], val[2]), + val[3], val[4]) + } + | backref tOP_ASGN command_call + { + @builder.op_assign(val[0], val[1], val[2]) + } + | lhs tEQL mrhs + { + result = @builder.assign(val[0], val[1], + @builder.array(nil, val[2], nil)) + } + | mlhs tEQL arg_value + { + result = @builder.multi_assign(val[0], val[1], val[2]) + } + | mlhs tEQL mrhs + { + result = @builder.multi_assign(val[0], val[1], + @builder.array(nil, val[2], nil)) + } + | expr + + expr: command_call + | expr kAND expr + { + result = @builder.logical_op(:and, val[0], val[1], val[2]) + } + | expr kOR expr + { + result = @builder.logical_op(:or, val[0], val[1], val[2]) + } + | kNOT opt_nl expr + { + result = @builder.not_op(val[0], nil, val[2], nil) + } + | tBANG command_call + { + result = @builder.not_op(val[0], nil, val[1], nil) + } + | arg + + expr_value: expr + + command_call: command + | block_command + + block_command: block_call + | block_call tDOT operation2 command_args + { + result = @builder.call_method(val[0], val[1], val[2], + *val[3]) + } + | block_call tCOLON2 operation2 command_args + { + result = @builder.call_method(val[0], val[1], val[2], + *val[3]) + } + + cmd_brace_block: tLBRACE_ARG + { + @static_env.extend_dynamic + } + opt_block_param compstmt tRCURLY + { + result = [ val[0], val[2], val[3], val[4] ] + + @static_env.unextend + } + + command: operation command_args =tLOWEST + { + result = @builder.call_method(nil, nil, val[0], + *val[1]) + } + | operation command_args cmd_brace_block + { + method_call = @builder.call_method(nil, nil, val[0], + *val[1]) + + begin_t, args, body, end_t = val[2] + result = @builder.block(method_call, + begin_t, args, body, end_t) + } + | primary_value tDOT operation2 command_args =tLOWEST + { + result = @builder.call_method(val[0], val[1], val[2], + *val[3]) + } + | primary_value tDOT operation2 command_args cmd_brace_block + { + method_call = @builder.call_method(val[0], val[1], val[2], + *val[3]) + + begin_t, args, body, end_t = val[4] + result = @builder.block(method_call, + begin_t, args, body, end_t) + } + | primary_value tCOLON2 operation2 command_args =tLOWEST + { + result = @builder.call_method(val[0], val[1], val[2], + *val[3]) + } + | primary_value tCOLON2 operation2 command_args cmd_brace_block + { + method_call = @builder.call_method(val[0], val[1], val[2], + *val[3]) + + begin_t, args, body, end_t = val[4] + result = @builder.block(method_call, + begin_t, args, body, end_t) + } + | kSUPER command_args + { + result = @builder.keyword_cmd(:super, val[0], + *val[1]) + } + | kYIELD command_args + { + result = @builder.keyword_cmd(:yield, val[0], + *val[1]) + } + | kRETURN call_args + { + result = @builder.keyword_cmd(:return, val[0], + nil, val[1], nil) + } + | kBREAK call_args + { + result = @builder.keyword_cmd(:break, val[0], + nil, val[1], nil) + } + | kNEXT call_args + { + result = @builder.keyword_cmd(:next, val[0], + nil, val[1], nil) + } + + mlhs: mlhs_basic + { + result = @builder.multi_lhs(nil, val[0], nil) + } + | tLPAREN mlhs_inner rparen + { + result = @builder.begin(val[0], val[1], val[2]) + } + + mlhs_inner: mlhs_basic + { + result = @builder.multi_lhs(nil, val[0], nil) + } + | tLPAREN mlhs_inner rparen + { + result = @builder.multi_lhs(val[0], val[1], val[2]) + } + + mlhs_basic: mlhs_head + | mlhs_head mlhs_item + { + result = val[0]. + push(val[1]) + } + | mlhs_head tSTAR mlhs_node + { + result = val[0]. + push(@builder.splat(val[1], val[2])) + } + | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post + { + result = val[0]. + push(@builder.splat(val[1], val[2])). + concat(val[4]) + } + | mlhs_head tSTAR + { + result = val[0]. + push(@builder.splat(val[1])) + } + | mlhs_head tSTAR tCOMMA mlhs_post + { + result = val[0]. + push(@builder.splat(val[1])). + concat(val[3]) + } + | tSTAR mlhs_node + { + result = [ @builder.splat(val[0], val[1]) ] + } + | tSTAR mlhs_node tCOMMA mlhs_post + { + result = [ @builder.splat(val[0], val[1]), + *val[3] ] + } + | tSTAR + { + result = [ @builder.splat(val[0]) ] + } + | tSTAR tCOMMA mlhs_post + { + result = [ @builder.splat(val[0]), + *val[2] ] + } + + mlhs_item: mlhs_node + | tLPAREN mlhs_inner rparen + { + result = @builder.begin(val[0], val[1], val[2]) + } + + mlhs_head: mlhs_item tCOMMA + { + result = [ val[0] ] + } + | mlhs_head mlhs_item tCOMMA + { + result = val[0] << val[1] + } + + mlhs_post: mlhs_item + { + result = [ val[0] ] + } + | mlhs_post tCOMMA mlhs_item + { + result = val[0] << val[2] + } + + mlhs_node: variable + { + result = @builder.assignable(val[0]) + } + | primary_value tLBRACK2 opt_call_args rbracket + { + result = @builder.index_asgn(val[0], val[1], val[2], val[3]) + } + | primary_value tDOT tIDENTIFIER + { + result = @builder.attr_asgn(val[0], val[1], val[2]) + } + | primary_value tCOLON2 tIDENTIFIER + { + result = @builder.attr_asgn(val[0], val[1], val[2]) + } + | primary_value tDOT tCONSTANT + { + result = @builder.attr_asgn(val[0], val[1], val[2]) + } + | primary_value tCOLON2 tCONSTANT + { + result = @builder.assignable( + @builder.const_fetch(val[0], val[1], val[2])) + } + | tCOLON3 tCONSTANT + { + result = @builder.assignable( + @builder.const_global(val[0], val[1])) + } + | backref + { + result = @builder.assignable(val[0]) + } + + lhs: variable + { + result = @builder.assignable(val[0]) + } + | primary_value tLBRACK2 opt_call_args rbracket + { + result = @builder.index_asgn(val[0], val[1], val[2], val[3]) + } + | primary_value tDOT tIDENTIFIER + { + result = @builder.attr_asgn(val[0], val[1], val[2]) + } + | primary_value tCOLON2 tIDENTIFIER + { + result = @builder.attr_asgn(val[0], val[1], val[2]) + } + | primary_value tDOT tCONSTANT + { + result = @builder.attr_asgn(val[0], val[1], val[2]) + } + | primary_value tCOLON2 tCONSTANT + { + result = @builder.assignable( + @builder.const_fetch(val[0], val[1], val[2])) + } + | tCOLON3 tCONSTANT + { + result = @builder.assignable( + @builder.const_global(val[0], val[1])) + } + | backref + { + result = @builder.assignable(val[0]) + } + + cname: tIDENTIFIER + { + diagnostic :error, :module_name_const, nil, val[0] + } + | tCONSTANT + + cpath: tCOLON3 cname + { + result = @builder.const_global(val[0], val[1]) + } + | cname + { + result = @builder.const(val[0]) + } + | primary_value tCOLON2 cname + { + result = @builder.const_fetch(val[0], val[1], val[2]) + } + + fname: tIDENTIFIER | tCONSTANT | tFID + | op + | reswords + + fsym: fname + { + result = @builder.symbol(val[0]) + } + | symbol + + fitem: fsym + | dsym + + undef_list: fitem + { + result = [ val[0] ] + } + | undef_list tCOMMA + { + @lexer.state = :expr_fname + } + fitem + { + result = val[0] << val[3] + } + + op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ + | tMATCH | tNMATCH | tGT | tGEQ | tLT | tLEQ + | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2 + | tSTAR | tDIVIDE | tPERCENT | tPOW | tBANG | tTILDE + | tUPLUS | tUMINUS | tAREF | tASET | tBACK_REF2 + + reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND + | kALIAS | kAND | kBEGIN | kBREAK | kCASE + | kCLASS | kDEF | kDEFINED | kDO | kELSE + | kELSIF | kEND | kENSURE | kFALSE | kFOR + | kIN | kMODULE | kNEXT | kNIL | kNOT + | kOR | kREDO | kRESCUE | kRETRY | kRETURN + | kSELF | kSUPER | kTHEN | kTRUE | kUNDEF + | kWHEN | kYIELD | kIF | kUNLESS | kWHILE + | kUNTIL + + arg: lhs tEQL arg + { + result = @builder.assign(val[0], val[1], val[2]) + } + | lhs tEQL arg kRESCUE_MOD arg + { + rescue_body = @builder.rescue_body(val[3], + nil, nil, nil, + nil, val[4]) + + rescue_ = @builder.begin_body(val[2], [ rescue_body ]) + + result = @builder.assign(val[0], val[1], rescue_) + } + | var_lhs tOP_ASGN arg + { + result = @builder.op_assign(val[0], val[1], val[2]) + } + | var_lhs tOP_ASGN arg kRESCUE_MOD arg + { + rescue_body = @builder.rescue_body(val[3], + nil, nil, nil, + nil, val[4]) + + rescue_ = @builder.begin_body(val[2], [ rescue_body ]) + + result = @builder.op_assign(val[0], val[1], rescue_) + } + | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg + { + result = @builder.op_assign( + @builder.index( + val[0], val[1], val[2], val[3]), + val[4], val[5]) + } + | primary_value tDOT tIDENTIFIER tOP_ASGN arg + { + result = @builder.op_assign( + @builder.call_method( + val[0], val[1], val[2]), + val[3], val[4]) + } + | primary_value tDOT tCONSTANT tOP_ASGN arg + { + result = @builder.op_assign( + @builder.call_method( + val[0], val[1], val[2]), + val[3], val[4]) + } + | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg + { + result = @builder.op_assign( + @builder.call_method( + val[0], val[1], val[2]), + val[3], val[4]) + } + | primary_value tCOLON2 tCONSTANT tOP_ASGN arg + { + diagnostic :error, :dynamic_const, nil, val[2], [ val[3] ] + } + | tCOLON3 tCONSTANT tOP_ASGN arg + { + diagnostic :error, :dynamic_const, nil, val[1], [ val[2] ] + } + | backref tOP_ASGN arg + { + result = @builder.op_assign(val[0], val[1], val[2]) + } + | arg tDOT2 arg + { + result = @builder.range_inclusive(val[0], val[1], val[2]) + } + | arg tDOT3 arg + { + result = @builder.range_exclusive(val[0], val[1], val[2]) + } + | arg tPLUS arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tMINUS arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tSTAR2 arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tDIVIDE arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tPERCENT arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tPOW arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | tUMINUS_NUM tINTEGER tPOW arg + { + result = @builder.unary_op(val[0], + @builder.binary_op( + @builder.integer(val[1]), + val[2], val[3])) + } + | tUMINUS_NUM tFLOAT tPOW arg + { + result = @builder.unary_op(val[0], + @builder.binary_op( + @builder.float(val[1]), + val[2], val[3])) + } + | tUPLUS arg + { + result = @builder.unary_op(val[0], val[1]) + } + | tUMINUS arg + { + result = @builder.unary_op(val[0], val[1]) + } + | arg tPIPE arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tCARET arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tAMPER2 arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tCMP arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tGT arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tGEQ arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tLT arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tLEQ arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tEQ arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tEQQ arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tNEQ arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tMATCH arg + { + result = @builder.match_op(val[0], val[1], val[2]) + } + | arg tNMATCH arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | tBANG arg + { + result = @builder.not_op(val[0], nil, val[1], nil) + } + | tTILDE arg + { + result = @builder.unary_op(val[0], val[1]) + } + | arg tLSHFT arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tRSHFT arg + { + result = @builder.binary_op(val[0], val[1], val[2]) + } + | arg tANDOP arg + { + result = @builder.logical_op(:and, val[0], val[1], val[2]) + } + | arg tOROP arg + { + result = @builder.logical_op(:or, val[0], val[1], val[2]) + } + | kDEFINED opt_nl arg + { + result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil) + } + + | arg tEH arg opt_nl tCOLON arg + { + result = @builder.ternary(val[0], val[1], + val[2], val[4], val[5]) + } + | primary + + arg_value: arg + + aref_args: none + | args trailer + | args tCOMMA assocs trailer + { + result = val[0] << @builder.associate(nil, val[2], nil) + } + | assocs trailer + { + result = [ @builder.associate(nil, val[0], nil) ] + } + + paren_args: tLPAREN2 opt_call_args rparen + { + result = val + } + + opt_paren_args: # nothing + { + result = [ nil, [], nil ] + } + | paren_args + + opt_call_args: # nothing + { + result = [] + } + | call_args + + call_args: command + { + result = [ val[0] ] + } + | args opt_block_arg + { + result = val[0].concat(val[1]) + } + | assocs opt_block_arg + { + result = [ @builder.associate(nil, val[0], nil) ] + result.concat(val[1]) + } + | args tCOMMA assocs opt_block_arg + { + assocs = @builder.associate(nil, val[2], nil) + result = val[0] << assocs + result.concat(val[3]) + } + | args tCOMMA assocs tCOMMA args opt_block_arg + { + val[2][-1] = @builder.objc_varargs(val[2][-1], val[4]) + assocs = @builder.associate(nil, val[2], nil) + result = val[0] << assocs + result.concat(val[5]) + } + | block_arg + { + result = [ val[0] ] + } + + call_args2: arg_value tCOMMA args opt_block_arg + { + result = [ val[0], *val[2].concat(val[3]) ] + } + | arg_value tCOMMA block_arg + { + result = [ val[0], val[2] ] + } + | assocs opt_block_arg + { + result = [ @builder.associate(nil, val[0], nil), + *val[1] ] + } + | arg_value tCOMMA assocs opt_block_arg + { + result = [ val[0], + @builder.associate(nil, val[2], nil), + *val[3] ] + } + | arg_value tCOMMA args tCOMMA assocs opt_block_arg + { + result = [ val[0], + *val[2]. + push(@builder.associate(nil, val[4], nil)). + concat(val[5]) ] + } + | block_arg + { + result = [ val[0] ] + } + + command_args: { + result = @lexer.cmdarg.dup + @lexer.cmdarg.push(true) + } + open_args + { + @lexer.cmdarg = val[0] + + result = val[1] + } + + open_args: call_args + { + result = [ nil, val[0], nil ] + } + | tLPAREN_ARG + { + @lexer.state = :expr_endarg + } + rparen + { + result = [ val[0], [], val[2] ] + } + | tLPAREN_ARG call_args2 + { + @lexer.state = :expr_endarg + } + rparen + { + result = [ val[0], val[1], val[3] ] + } + + block_arg: tAMPER arg_value + { + result = @builder.block_pass(val[0], val[1]) + } + + opt_block_arg: tCOMMA block_arg + { + result = [ val[1] ] + } + | tCOMMA + { + result = [] + } + | # nothing + { + result = [] + } + + args: arg_value + { + result = [ val[0] ] + } + | tSTAR arg_value + { + result = [ @builder.splat(val[0], val[1]) ] + } + | args tCOMMA arg_value + { + result = val[0] << val[2] + } + | args tCOMMA tSTAR arg_value + { + result = val[0] << @builder.splat(val[2], val[3]) + } + + mrhs: args tCOMMA arg_value + { + result = val[0] << val[2] + } + | args tCOMMA tSTAR arg_value + { + result = val[0] << @builder.splat(val[2], val[3]) + } + | tSTAR arg_value + { + result = [ @builder.splat(val[0], val[1]) ] + } + + primary: literal + | strings + | xstring + | regexp + | words + | qwords + | var_ref + | backref + | tFID + { + result = @builder.call_method(nil, nil, val[0]) + } + | kBEGIN bodystmt kEND + { + result = @builder.begin_keyword(val[0], val[1], val[2]) + } + | tLPAREN_ARG expr + { + @lexer.state = :expr_endarg + } + rparen + { + result = @builder.begin(val[0], val[1], val[3]) + } + | tLPAREN compstmt tRPAREN + { + result = @builder.begin(val[0], val[1], val[2]) + } + | primary_value tCOLON2 tCONSTANT + { + result = @builder.const_fetch(val[0], val[1], val[2]) + } + | tCOLON3 tCONSTANT + { + result = @builder.const_global(val[0], val[1]) + } + | tLBRACK aref_args tRBRACK + { + result = @builder.array(val[0], val[1], val[2]) + } + | tLBRACE assoc_list tRCURLY + { + result = @builder.associate(val[0], val[1], val[2]) + } + | kRETURN + { + result = @builder.keyword_cmd(:return, val[0]) + } + | kYIELD tLPAREN2 call_args rparen + { + result = @builder.keyword_cmd(:yield, val[0], val[1], val[2], val[3]) + } + | kYIELD tLPAREN2 rparen + { + result = @builder.keyword_cmd(:yield, val[0], val[1], [], val[2]) + } + | kYIELD + { + result = @builder.keyword_cmd(:yield, val[0]) + } + | kDEFINED opt_nl tLPAREN2 expr rparen + { + result = @builder.keyword_cmd(:defined?, val[0], + val[2], [ val[3] ], val[4]) + } + | kNOT tLPAREN2 expr rparen + { + result = @builder.not_op(val[0], val[1], val[2], val[3]) + } + | kNOT tLPAREN2 rparen + { + result = @builder.not_op(val[0], val[1], nil, val[2]) + } + | operation brace_block + { + method_call = @builder.call_method(nil, nil, val[0]) + + begin_t, args, body, end_t = val[1] + result = @builder.block(method_call, + begin_t, args, body, end_t) + } + | method_call + | method_call brace_block + { + begin_t, args, body, end_t = val[1] + result = @builder.block(val[0], + begin_t, args, body, end_t) + } + | tLAMBDA lambda + { + lambda_call = @builder.call_lambda(val[0]) + + args, (begin_t, body, end_t) = val[1] + result = @builder.block(lambda_call, + begin_t, args, body, end_t) + } + | kIF expr_value then compstmt if_tail kEND + { + else_t, else_ = val[4] + result = @builder.condition(val[0], val[1], val[2], + val[3], else_t, + else_, val[5]) + } + | kUNLESS expr_value then compstmt opt_else kEND + { + else_t, else_ = val[4] + result = @builder.condition(val[0], val[1], val[2], + else_, else_t, + val[3], val[5]) + } + | kWHILE + { + @lexer.cond.push(true) + } + expr_value do + { + @lexer.cond.pop + } + compstmt kEND + { + result = @builder.loop(:while, val[0], val[2], val[3], + val[5], val[6]) + } + | kUNTIL + { + @lexer.cond.push(true) + } + expr_value do + { + @lexer.cond.pop + } + compstmt kEND + { + result = @builder.loop(:until, val[0], val[2], val[3], + val[5], val[6]) + } + | kCASE expr_value opt_terms case_body kEND + { + *when_bodies, (else_t, else_body) = *val[3] + + result = @builder.case(val[0], val[1], + when_bodies, else_t, else_body, + val[4]) + } + | kCASE opt_terms case_body kEND + { + *when_bodies, (else_t, else_body) = *val[2] + + result = @builder.case(val[0], nil, + when_bodies, else_t, else_body, + val[3]) + } + | kFOR for_var kIN + { + @lexer.cond.push(true) + } + expr_value do + { + @lexer.cond.pop + } + compstmt kEND + { + result = @builder.for(val[0], val[1], + val[2], val[4], + val[5], val[7], val[8]) + } + | kCLASS cpath superclass + { + @static_env.extend_static + @lexer.push_cmdarg + } + bodystmt kEND + { + if in_def? + diagnostic :error, :class_in_def, nil, val[0] + end + + lt_t, superclass = val[2] + result = @builder.def_class(val[0], val[1], + lt_t, superclass, + val[4], val[5]) + + @lexer.pop_cmdarg + @static_env.unextend + } + | kCLASS tLSHFT expr term + { + result = @def_level + @def_level = 0 + + @static_env.extend_static + @lexer.push_cmdarg + } + bodystmt kEND + { + result = @builder.def_sclass(val[0], val[1], val[2], + val[5], val[6]) + + @lexer.pop_cmdarg + @static_env.unextend + + @def_level = val[4] + } + | kMODULE cpath + { + @static_env.extend_static + @lexer.push_cmdarg + } + bodystmt kEND + { + if in_def? + diagnostic :error, :module_in_def, nil, val[0] + end + + result = @builder.def_module(val[0], val[1], + val[3], val[4]) + + @lexer.pop_cmdarg + @static_env.unextend + } + | kDEF fname + { + @def_level += 1 + @static_env.extend_static + @lexer.push_cmdarg + } + f_arglist bodystmt kEND + { + result = @builder.def_method(val[0], val[1], + val[3], val[4], val[5]) + + @lexer.pop_cmdarg + @static_env.unextend + @def_level -= 1 + } + | kDEF singleton dot_or_colon + { + @lexer.state = :expr_fname + } + fname + { + @def_level += 1 + @static_env.extend_static + @lexer.push_cmdarg + } + f_arglist bodystmt kEND + { + result = @builder.def_singleton(val[0], val[1], val[2], + val[4], val[6], val[7], val[8]) + + @lexer.pop_cmdarg + @static_env.unextend + @def_level -= 1 + } + | kBREAK + { + result = @builder.keyword_cmd(:break, val[0]) + } + | kNEXT + { + result = @builder.keyword_cmd(:next, val[0]) + } + | kREDO + { + result = @builder.keyword_cmd(:redo, val[0]) + } + | kRETRY + { + result = @builder.keyword_cmd(:retry, val[0]) + } + + primary_value: primary + + then: term + | kTHEN + | term kTHEN + { + result = val[1] + } + + do: term + | kDO_COND + + if_tail: opt_else + | kELSIF expr_value then compstmt if_tail + { + else_t, else_ = val[4] + result = [ val[0], + @builder.condition(val[0], val[1], val[2], + val[3], else_t, + else_, nil), + ] + } + + opt_else: none + | kELSE compstmt + { + result = val + } + + for_var: lhs + | mlhs + + f_marg: f_norm_arg + | tLPAREN f_margs rparen + { + result = @builder.multi_lhs(val[0], val[1], val[2]) + } + + f_marg_list: f_marg + { + result = [ val[0] ] + } + | f_marg_list tCOMMA f_marg + { + result = val[0] << val[2] + } + + f_margs: f_marg_list + | f_marg_list tCOMMA tSTAR f_norm_arg + { + result = val[0]. + push(@builder.objc_restarg(val[2], val[3])) + } + | f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list + { + result = val[0]. + push(@builder.objc_restarg(val[2], val[3])). + concat(val[5]) + } + | f_marg_list tCOMMA tSTAR + { + result = val[0]. + push(@builder.objc_restarg(val[2])) + } + | f_marg_list tCOMMA tSTAR tCOMMA f_marg_list + { + result = val[0]. + push(@builder.objc_restarg(val[2])). + concat(val[4]) + } + | tSTAR f_norm_arg + { + result = [ @builder.objc_restarg(val[0], val[1]) ] + } + | tSTAR f_norm_arg tCOMMA f_marg_list + { + result = [ @builder.objc_restarg(val[0], val[1]), + *val[3] ] + } + | tSTAR + { + result = [ @builder.objc_restarg(val[0]) ] + } + | tSTAR tCOMMA f_marg_list + { + result = [ @builder.objc_restarg(val[0]), + *val[2] ] + } + + block_param: f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[4]). + concat(val[5]) + } + | f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[4]). + concat(val[6]). + concat(val[7]) + } + | f_arg tCOMMA f_block_optarg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[3]) + } + | f_arg tCOMMA f_block_optarg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[4]). + concat(val[5]) + } + | f_arg tCOMMA f_rest_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[3]) + } + | f_arg tCOMMA + | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[4]). + concat(val[5]) + } + | f_arg opt_f_block_arg + { + result = val[0].concat(val[1]) + } + | f_block_optarg tCOMMA f_rest_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[3]) + } + | f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[4]). + concat(val[5]) + } + | f_block_optarg opt_f_block_arg + { + result = val[0]. + concat(val[1]) + } + | f_block_optarg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[3]) + } + | f_rest_arg opt_f_block_arg + { + result = val[0]. + concat(val[1]) + } + | f_rest_arg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[3]) + } + | f_block_arg + { + result = [ val[0] ] + } + + opt_block_param: # nothing + { + result = @builder.args(nil, [], nil) + } + | block_param_def + { + @lexer.state = :expr_value + } + + block_param_def: tPIPE opt_bv_decl tPIPE + { + result = @builder.args(val[0], val[1], val[2]) + } + | tOROP + { + result = @builder.args(val[0], [], val[0]) + } + | tPIPE block_param opt_bv_decl tPIPE + { + result = @builder.args(val[0], val[1].concat(val[2]), val[3]) + } + + opt_bv_decl: # nothing + { + result = [] + } + | tSEMI bv_decls + { + result = val[1] + } + + bv_decls: bvar + { + result = [ val[0] ] + } + | bv_decls tCOMMA bvar + { + result = val[0] << val[2] + } + + bvar: tIDENTIFIER + { + result = @builder.shadowarg(val[0]) + } + | f_bad_arg + + lambda: { + @static_env.extend_dynamic + } + f_larglist lambda_body + { + result = [ val[1], val[2] ] + + @static_env.unextend + } + + f_larglist: tLPAREN2 f_args opt_bv_decl rparen + { + result = @builder.args(val[0], val[1].concat(val[2]), val[3]) + } + | f_args + { + result = @builder.args(nil, val[0], nil) + } + + lambda_body: tLAMBEG compstmt tRCURLY + { + result = [ val[0], val[1], val[2] ] + } + | kDO_LAMBDA compstmt kEND + { + result = [ val[0], val[1], val[2] ] + } + + do_block: kDO_BLOCK + { + @static_env.extend_dynamic + } + opt_block_param compstmt kEND + { + result = [ val[0], val[2], val[3], val[4] ] + + @static_env.unextend + } + + block_call: command do_block + { + begin_t, block_args, body, end_t = val[1] + result = @builder.block(val[0], + begin_t, block_args, body, end_t) + } + | block_call tDOT operation2 opt_paren_args + { + lparen_t, args, rparen_t = val[3] + result = @builder.call_method(val[0], val[1], val[2], + lparen_t, args, rparen_t) + } + | block_call tCOLON2 operation2 opt_paren_args + { + lparen_t, args, rparen_t = val[3] + result = @builder.call_method(val[0], val[1], val[2], + lparen_t, args, rparen_t) + } + + method_call: operation paren_args + { + lparen_t, args, rparen_t = val[1] + result = @builder.call_method(nil, nil, val[0], + lparen_t, args, rparen_t) + } + | primary_value tDOT operation2 opt_paren_args + { + lparen_t, args, rparen_t = val[3] + result = @builder.call_method(val[0], val[1], val[2], + lparen_t, args, rparen_t) + } + | primary_value tCOLON2 operation2 paren_args + { + lparen_t, args, rparen_t = val[3] + result = @builder.call_method(val[0], val[1], val[2], + lparen_t, args, rparen_t) + } + | primary_value tCOLON2 operation3 + { + result = @builder.call_method(val[0], val[1], val[2]) + } + | primary_value tDOT paren_args + { + lparen_t, args, rparen_t = val[2] + result = @builder.call_method(val[0], val[1], nil, + lparen_t, args, rparen_t) + } + | primary_value tCOLON2 paren_args + { + lparen_t, args, rparen_t = val[2] + result = @builder.call_method(val[0], val[1], nil, + lparen_t, args, rparen_t) + } + | kSUPER paren_args + { + lparen_t, args, rparen_t = val[1] + result = @builder.keyword_cmd(:super, val[0], + lparen_t, args, rparen_t) + } + | kSUPER + { + result = @builder.keyword_cmd(:zsuper, val[0]) + } + | primary_value tLBRACK2 opt_call_args rbracket + { + result = @builder.index(val[0], val[1], val[2], val[3]) + } + + brace_block: tLCURLY + { + @static_env.extend_dynamic + } + opt_block_param compstmt tRCURLY + { + result = [ val[0], val[2], val[3], val[4] ] + + @static_env.unextend + } + | kDO + { + @static_env.extend_dynamic + } + opt_block_param compstmt kEND + { + result = [ val[0], val[2], val[3], val[4] ] + + @static_env.unextend + } + + case_body: kWHEN args then compstmt cases + { + result = [ @builder.when(val[0], val[1], val[2], val[3]), + *val[4] ] + } + + cases: opt_else + { + result = [ val[0] ] + } + | case_body + + opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue + { + assoc_t, exc_var = val[2] + + if val[1] + exc_list = @builder.array(nil, val[1], nil) + end + + result = [ @builder.rescue_body(val[0], + exc_list, assoc_t, exc_var, + val[3], val[4]), + *val[5] ] + } + | + { + result = [] + } + + exc_list: arg_value + { + result = [ val[0] ] + } + | mrhs + | none + + exc_var: tASSOC lhs + { + result = [ val[0], val[1] ] + } + | none + + opt_ensure: kENSURE compstmt + { + result = [ val[0], val[1] ] + } + | none + + literal: numeric + | symbol + | dsym + + strings: string + { + result = @builder.string_compose(nil, val[0], nil) + } + + string: string1 + { + result = [ val[0] ] + } + | string string1 + { + result = val[0] << val[1] + } + + string1: tSTRING_BEG string_contents tSTRING_END + { + result = @builder.string_compose(val[0], val[1], val[2]) + } + | tSTRING + { + result = @builder.string(val[0]) + } + | tCHARACTER + { + result = @builder.character(val[0]) + } + + xstring: tXSTRING_BEG xstring_contents tSTRING_END + { + result = @builder.xstring_compose(val[0], val[1], val[2]) + } + + regexp: tREGEXP_BEG regexp_contents tSTRING_END tREGEXP_OPT + { + opts = @builder.regexp_options(val[3]) + result = @builder.regexp_compose(val[0], val[1], val[2], opts) + } + + words: tWORDS_BEG word_list tSTRING_END + { + result = @builder.words_compose(val[0], val[1], val[2]) + } + + word_list: # nothing + { + result = [] + } + | word_list word tSPACE + { + result = val[0] << @builder.word(val[1]) + } + + word: string_content + { + result = [ val[0] ] + } + | word string_content + { + result = val[0] << val[1] + } + + qwords: tQWORDS_BEG qword_list tSTRING_END + { + result = @builder.words_compose(val[0], val[1], val[2]) + } + + qword_list: # nothing + { + result = [] + } + | qword_list tSTRING_CONTENT tSPACE + { + result = val[0] << @builder.string_internal(val[1]) + } + + string_contents: # nothing + { + result = [] + } + | string_contents string_content + { + result = val[0] << val[1] + } + +xstring_contents: # nothing + { + result = [] + } + | xstring_contents string_content + { + result = val[0] << val[1] + } + +regexp_contents: # nothing + { + result = [] + } + | regexp_contents string_content + { + result = val[0] << val[1] + } + + string_content: tSTRING_CONTENT + { + result = @builder.string_internal(val[0]) + } + | tSTRING_DVAR string_dvar + { + result = val[1] + } + | tSTRING_DBEG + { + @lexer.cond.push(false) + @lexer.cmdarg.push(false) + } + compstmt tRCURLY + { + @lexer.cond.lexpop + @lexer.cmdarg.lexpop + + result = @builder.begin(val[0], val[2], val[3]) + } + + string_dvar: tGVAR + { + result = @builder.gvar(val[0]) + } + | tIVAR + { + result = @builder.ivar(val[0]) + } + | tCVAR + { + result = @builder.cvar(val[0]) + } + | backref + + + symbol: tSYMBOL + { + result = @builder.symbol(val[0]) + } + + dsym: tSYMBEG xstring_contents tSTRING_END + { + result = @builder.symbol_compose(val[0], val[1], val[2]) + } + + numeric: tINTEGER + { + result = @builder.integer(val[0]) + } + | tFLOAT + { + result = @builder.float(val[0]) + } + | tUMINUS_NUM tINTEGER =tLOWEST + { + result = @builder.negate(val[0], + @builder.integer(val[1])) + } + | tUMINUS_NUM tFLOAT =tLOWEST + { + result = @builder.negate(val[0], + @builder.float(val[1])) + } + + variable: tIDENTIFIER + { + result = @builder.ident(val[0]) + } + | tIVAR + { + result = @builder.ivar(val[0]) + } + | tGVAR + { + result = @builder.gvar(val[0]) + } + | tCONSTANT + { + result = @builder.const(val[0]) + } + | tCVAR + { + result = @builder.cvar(val[0]) + } + | kNIL + { + result = @builder.nil(val[0]) + } + | kSELF + { + result = @builder.self(val[0]) + } + | kTRUE + { + result = @builder.true(val[0]) + } + | kFALSE + { + result = @builder.false(val[0]) + } + | k__FILE__ + { + result = @builder.__FILE__(val[0]) + } + | k__LINE__ + { + result = @builder.__LINE__(val[0]) + } + | k__ENCODING__ + { + result = @builder.__ENCODING__(val[0]) + } + + var_ref: variable + { + result = @builder.accessible(val[0]) + } + + var_lhs: variable + { + result = @builder.assignable(val[0]) + } + + backref: tNTH_REF + { + result = @builder.nth_ref(val[0]) + } + | tBACK_REF + { + result = @builder.back_ref(val[0]) + } + + superclass: term + { + result = nil + } + | tLT expr_value term + { + result = [ val[0], val[1] ] + } + | error term + { + yyerrok + result = nil + } + + f_arglist: tLPAREN2 f_args rparen + { + result = @builder.args(val[0], val[1], val[2]) + + @lexer.state = :expr_value + } + | f_args term + { + result = @builder.args(nil, val[0], nil) + } + + f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[4]). + concat(val[5]) + } + | f_arg tCOMMA f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[4]). + concat(val[6]). + concat(val[7]) + } + | f_arg tCOMMA f_optarg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[3]) + } + | f_arg tCOMMA f_optarg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[4]). + concat(val[5]) + } + | f_arg tCOMMA f_rest_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[3]) + } + | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[4]). + concat(val[5]) + } + | f_arg opt_f_block_arg + { + result = val[0]. + concat(val[1]) + } + | f_optarg tCOMMA f_rest_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[3]) + } + | f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[4]). + concat(val[5]) + } + | f_optarg opt_f_block_arg + { + result = val[0]. + concat(val[1]) + } + | f_optarg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[3]) + } + | f_rest_arg opt_f_block_arg + { + result = val[0]. + concat(val[1]) + } + | f_rest_arg tCOMMA f_arg opt_f_block_arg + { + result = val[0]. + concat(val[2]). + concat(val[3]) + } + | f_block_arg + { + result = [ val[0] ] + } + | # nothing + { + result = [] + } + + f_bad_arg: tCONSTANT + { + diagnostic :error, :argument_const, nil, val[0] + } + | tIVAR + { + diagnostic :error, :argument_ivar, nil, val[0] + } + | tGVAR + { + diagnostic :error, :argument_gvar, nil, val[0] + } + | tCVAR + { + diagnostic :error, :argument_cvar, nil, val[0] + } + + f_norm_arg: f_bad_arg + | tIDENTIFIER + { + @static_env.declare val[0][0] + + result = @builder.arg(val[0]) + } + | tIDENTIFIER tASSOC tIDENTIFIER + { + @static_env.declare val[2][0] + + result = @builder.objc_kwarg(val[0], val[1], val[2]) + } + | tLABEL tIDENTIFIER + { + @static_env.declare val[1][0] + + result = @builder.objc_kwarg(val[0], nil, val[1]) + } + + f_arg_item: f_norm_arg + | tLPAREN f_margs rparen + { + result = @builder.multi_lhs(val[0], val[1], val[2]) + } + + f_arg: f_arg_item + { + result = [ val[0] ] + } + | f_arg tCOMMA f_arg_item + { + result = val[0] << val[2] + } + + f_opt: tIDENTIFIER tEQL arg_value + { + @static_env.declare val[0][0] + + result = @builder.optarg(val[0], val[1], val[2]) + } + + f_block_opt: tIDENTIFIER tEQL primary_value + { + @static_env.declare val[0][0] + + result = @builder.optarg(val[0], val[1], val[2]) + } + + f_block_optarg: f_block_opt + { + result = [ val[0] ] + } + | f_block_optarg tCOMMA f_block_opt + { + result = val[0] << val[2] + } + + f_optarg: f_opt + { + result = [ val[0] ] + } + | f_optarg tCOMMA f_opt + { + result = val[0] << val[2] + } + + restarg_mark: tSTAR2 | tSTAR + + f_rest_arg: restarg_mark tIDENTIFIER + { + @static_env.declare val[1][0] + + result = [ @builder.restarg(val[0], val[1]) ] + } + | restarg_mark + { + result = [ @builder.restarg(val[0]) ] + } + + blkarg_mark: tAMPER2 | tAMPER + + f_block_arg: blkarg_mark tIDENTIFIER + { + @static_env.declare val[1][0] + + result = @builder.blockarg(val[0], val[1]) + } + + opt_f_block_arg: tCOMMA f_block_arg + { + result = [ val[1] ] + } + | # nothing + { + result = [] + } + + singleton: var_ref + | tLPAREN2 expr rparen + { + result = val[1] + } + + assoc_list: # nothing + { + result = [] + } + | assocs trailer + + assocs: assoc + { + result = [ val[0] ] + } + | assocs tCOMMA assoc + { + result = val[0] << val[2] + } + + assoc: arg_value tASSOC arg_value + { + result = @builder.pair(val[0], val[1], val[2]) + } + | tLABEL arg_value + { + result = @builder.pair_keyword(val[0], val[1]) + } + + operation: tIDENTIFIER | tCONSTANT | tFID + operation2: tIDENTIFIER | tCONSTANT | tFID | op + operation3: tIDENTIFIER | tFID | op + dot_or_colon: tDOT | tCOLON2 + opt_terms: | terms + opt_nl: | tNL + rparen: opt_nl tRPAREN + { + result = val[1] + } + rbracket: opt_nl tRBRACK + { + result = val[1] + } + trailer: | tNL | tCOMMA + + term: tSEMI + { + yyerrok + } + | tNL + + terms: term + | terms tSEMI + + none: # nothing + { + result = nil + } +end + +---- header + +require 'parser' + +Parser.check_for_encoding_support + +---- inner + + def version + 19 # closest released match: v1_9_0_2 + end + + def default_encoding + Encoding::BINARY + end diff --git a/test/assets/mailp.y b/test/assets/mailp.y index da332a33..eb7d4d52 100644 --- a/test/assets/mailp.y +++ b/test/assets/mailp.y @@ -35,7 +35,7 @@ rule @field.domain = mb.domain } ; - + datetime : day DIGIT ATOM DIGIT hour zone # 0 1 2 3 4 5 # day month year @@ -44,11 +44,11 @@ rule result = (t + val[4] - val[5]).localtime } ; - + day : /* none */ | ATOM ',' ; - + hour : DIGIT ':' DIGIT { result = (result.to_i * 60 * 60) + (val[2].to_i * 60) @@ -60,16 +60,16 @@ rule + val[4].to_i } ; - + zone : ATOM { result = ::TMail.zonestr2i( val[0] ) * 60 } ; - + received : from by via with id for recvdatetime ; - + from : /* none */ | FROM domain { @@ -84,28 +84,28 @@ rule @field.from = Address.join( val[1] ) } ; - + by : /* none */ | BY domain { @field.by = Address.join( val[1] ) } ; - + via : /* none */ | VIA ATOM { @field.via = val[1] } ; - + with : /* none */ | WITH ATOM { @field.with.push val[1] } ; - + id : /* none */ | ID msgid { @@ -116,14 +116,14 @@ rule @field.msgid = val[1] } ; - + for : /* none */ | FOR addr { @field.for_ = val[1].address } ; - + recvdatetime : /* none */ | ';' datetime @@ -131,7 +131,7 @@ rule @field.date = val[1] } ; - + returnpath: '<' '>' | routeaddr { @@ -173,7 +173,7 @@ rule } # | phrase ':' ';' { result = AddressGroup.new( result ) } ; - + routeaddr : '<' route spec '>' { result = val[2] @@ -184,22 +184,22 @@ rule result = val[1] } ; - + route : at_domains ':' ; - + at_domains: '@' domain { result = [ val[1] ] } | at_domains ',' '@' domain { result.push val[3] } ; - + spec : local '@' domain { result = Address.new( val[0], val[2] ) } | local { result = Address.new( result, nil ) } ; - + local : word { result = val } | local '.' word { result.push val[2] } ; - + domain : domword { result = val } | domain '.' domword { result.push val[2] } ; @@ -215,11 +215,11 @@ rule result = val.join('') } ; - + phrase : word | phrase word { result << ' ' << val[1] } ; - + word : atom | QUOTED | DIGIT @@ -228,7 +228,7 @@ rule keys : phrase | keys ',' phrase ; - + enc : word { @field.encrypter = val[0] @@ -258,7 +258,7 @@ rule @field.sub = '' } ; - + params : /* none */ | params ';' TOKEN '=' value { @@ -281,7 +281,7 @@ rule @field.disposition = val[0] } ; - + disp_params : /* none */ | disp_params ';' disp_param @@ -293,7 +293,7 @@ rule @field.params[ val[0].downcase ] = val[2] } ; - + atom : ATOM | FROM | BY @@ -302,7 +302,7 @@ rule | ID | FOR ; - + end @@ -382,7 +382,7 @@ module TMail @scanner.scan @pass_array end end - + def on_error( tok, val, vstack ) raise ParseError, "\nparse error in '#{@field.name}' header, on token #{val.inspect}" diff --git a/test/assets/mediacloth.y b/test/assets/mediacloth.y new file mode 100644 index 00000000..94cc411e --- /dev/null +++ b/test/assets/mediacloth.y @@ -0,0 +1,599 @@ +# Copyright (c) 2006 Pluron Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# The parser for the MediaWiki language. +# +# Usage together with a lexer: +# inputFile = File.new("data/input1", "r") +# input = inputFile.read +# parser = MediaWikiParser.new +# parser.lexer = MediaWikiLexer.new +# parser.parse(input) + +class MediaWikiParser + +token TEXT BOLD_START BOLD_END ITALIC_START ITALIC_END LINK_START LINK_END LINKSEP + INTLINK_START INTLINK_END INTLINKSEP RESOURCESEP CHAR_ENT + PRE_START PRE_END PREINDENT_START PREINDENT_END + SECTION_START SECTION_END HLINE SIGNATURE_NAME SIGNATURE_DATE SIGNATURE_FULL + PARA_START PARA_END UL_START UL_END OL_START OL_END LI_START LI_END + DL_START DL_END DT_START DT_END DD_START DD_END TAG_START TAG_END ATTR_NAME ATTR_VALUE + TABLE_START TABLE_END ROW_START ROW_END HEAD_START HEAD_END CELL_START CELL_END + KEYWORD TEMPLATE_START TEMPLATE_END CATEGORY PASTE_START PASTE_END + + +rule + +wiki: + repeated_contents + { + @nodes.push WikiAST.new(0, @wiki_ast_length) + #@nodes.last.children.insert(0, val[0]) + #puts val[0] + @nodes.last.children += val[0] + } + ; + +contents: + text + { + result = val[0] + } + | bulleted_list + { + result = val[0] + } + | numbered_list + { + result = val[0] + } + | dictionary_list + { + list = ListAST.new(@ast_index, @ast_length) + list.list_type = :Dictionary + list.children = val[0] + result = list + } + | preformatted + { + result = val[0] + } + | section + { + result = val[0] + } + | tag + { + result = val[0] + } + | template + { + result = val[0] + } + | KEYWORD + { + k = KeywordAST.new(@ast_index, @ast_length) + k.text = val[0] + result = k + } + | PARA_START para_contents PARA_END + { + p = ParagraphAST.new(@ast_index, @ast_length) + p.children = val[1] + result = p + } + | LINK_START link_contents LINK_END + { + l = LinkAST.new(@ast_index, @ast_length) + l.link_type = val[0] + l.url = val[1][0] + l.children += val[1][1..-1] if val[1].length > 1 + result = l + } + | PASTE_START para_contents PASTE_END + { + p = PasteAST.new(@ast_index, @ast_length) + p.children = val[1] + result = p + } + | INTLINK_START TEXT RESOURCESEP TEXT reslink_repeated_contents INTLINK_END + { + l = ResourceLinkAST.new(@ast_index, @ast_length) + l.prefix = val[1] + l.locator = val[3] + l.children = val[4] unless val[4].nil? or val[4].empty? + result = l + } + | INTLINK_START TEXT intlink_repeated_contents INTLINK_END + { + l = InternalLinkAST.new(@ast_index, @ast_length) + l.locator = val[1] + l.children = val[2] unless val[2].nil? or val[2].empty? + result = l + } + | INTLINK_START CATEGORY TEXT cat_sort_contents INTLINK_END + { + l = CategoryAST.new(@ast_index, @ast_length) + l.locator = val[2] + l.sort_as = val[3] + result = l + } + | INTLINK_START RESOURCESEP CATEGORY TEXT intlink_repeated_contents INTLINK_END + { + l = CategoryLinkAST.new(@ast_index, @ast_length) + l.locator = val[3] + l.children = val[4] unless val[4].nil? or val[4].empty? + result = l + } + | table + ; + +para_contents: + { + result = nil + } + | repeated_contents + { + result = val[0] + } + ; + +tag: + TAG_START tag_attributes TAG_END + { + if val[0] != val[2] + raise Racc::ParseError.new("XHTML end tag #{val[2]} does not match start tag #{val[0]}") + end + elem = ElementAST.new(@ast_index, @ast_length) + elem.name = val[0] + elem.attributes = val[1] + result = elem + } + | TAG_START tag_attributes repeated_contents TAG_END + { + if val[0] != val[3] + raise Racc::ParseError.new("XHTML end tag #{val[3]} does not match start tag #{val[0]}") + end + elem = ElementAST.new(@ast_index, @ast_length) + elem.name = val[0] + elem.attributes = val[1] + elem.children += val[2] + result = elem + } + ; + +tag_attributes: + { + result = nil + } + | ATTR_NAME tag_attributes + { + attr_map = val[2] ? val[2] : {} + attr_map[val[0]] = true + result = attr_map + } + | ATTR_NAME ATTR_VALUE tag_attributes + { + attr_map = val[2] ? val[2] : {} + attr_map[val[0]] = val[1] + result = attr_map + } + ; + + +link_contents: + TEXT + { + result = val + } + | TEXT LINKSEP link_repeated_contents + { + result = [val[0]] + result += val[2] + } + ; + + +link_repeated_contents: + repeated_contents + { + result = val[0] + } + | repeated_contents LINKSEP link_repeated_contents + { + result = val[0] + result += val[2] if val[2] + } + ; + + +intlink_repeated_contents: + { + result = nil + } + | INTLINKSEP repeated_contents + { + result = val[1] + } + ; + +cat_sort_contents: + { + result = nil + } + | INTLINKSEP TEXT + { + result = val[1] + } + ; + +reslink_repeated_contents: + { + result = nil + } + | INTLINKSEP reslink_repeated_contents + { + result = val[1] + } + | INTLINKSEP repeated_contents reslink_repeated_contents + { + i = InternalLinkItemAST.new(@ast_index, @ast_length) + i.children = val[1] + result = [i] + result += val[2] if val[2] + } + ; + +repeated_contents: contents + { + result = [] + result << val[0] + } + | repeated_contents contents + { + result = [] + result += val[0] + result << val[1] + } + ; + +text: element + { + p = TextAST.new(@ast_index, @ast_length) + p.formatting = val[0][0] + p.contents = val[0][1] + result = p + } + | formatted_element + { + result = val[0] + } + ; + +table: + TABLE_START table_contents TABLE_END + { + table = TableAST.new(@ast_index, @ast_length) + table.children = val[1] unless val[1].nil? or val[1].empty? + result = table + } + | TABLE_START TEXT table_contents TABLE_END + { + table = TableAST.new(@ast_index, @ast_length) + table.options = val[1] + table.children = val[2] unless val[2].nil? or val[2].empty? + result = table + } + +table_contents: + { + result = nil + } + | ROW_START row_contents ROW_END table_contents + { + row = TableRowAST.new(@ast_index, @ast_length) + row.children = val[1] unless val[1].nil? or val[1].empty? + result = [row] + result += val[3] unless val[3].nil? or val[3].empty? + } + | ROW_START TEXT row_contents ROW_END table_contents + { + row = TableRowAST.new(@ast_index, @ast_length) + row.children = val[2] unless val[2].nil? or val[2].empty? + row.options = val[1] + result = [row] + result += val[4] unless val[4].nil? or val[4].empty? + } + +row_contents: + { + result = nil + } + | HEAD_START HEAD_END row_contents + { + cell = TableCellAST.new(@ast_index, @ast_length) + cell.type = :head + result = [cell] + result += val[2] unless val[2].nil? or val[2].empty? + } + | HEAD_START repeated_contents HEAD_END row_contents + { + cell = TableCellAST.new(@ast_index, @ast_length) + cell.children = val[1] unless val[1].nil? or val[1].empty? + cell.type = :head + result = [cell] + result += val[3] unless val[3].nil? or val[3].empty? + } + | CELL_START CELL_END row_contents + { + cell = TableCellAST.new(@ast_index, @ast_length) + cell.type = :body + result = [cell] + result += val[2] unless val[2].nil? or val[2].empty? + } + | CELL_START repeated_contents CELL_END row_contents + { + if val[2] == 'attributes' + result = [] + else + cell = TableCellAST.new(@ast_index, @ast_length) + cell.children = val[1] unless val[1].nil? or val[1].empty? + cell.type = :body + result = [cell] + end + result += val[3] unless val[3].nil? or val[3].empty? + if val[2] == 'attributes' and val[3] and val[3].first.class == TableCellAST + val[3].first.attributes = val[1] + end + result + } + + +element: + TEXT + { return [:None, val[0]] } + | HLINE + { return [:HLine, val[0]] } + | CHAR_ENT + { return [:CharacterEntity, val[0]] } + | SIGNATURE_DATE + { return [:SignatureDate, val[0]] } + | SIGNATURE_NAME + { return [:SignatureName, val[0]] } + | SIGNATURE_FULL + { return [:SignatureFull, val[0]] } + ; + +formatted_element: + BOLD_START BOLD_END + { + result = FormattedAST.new(@ast_index, @ast_length) + result.formatting = :Bold + result + } + | ITALIC_START ITALIC_END + { + result = FormattedAST.new(@ast_index, @ast_length) + result.formatting = :Italic + result + } + | BOLD_START repeated_contents BOLD_END + { + p = FormattedAST.new(@ast_index, @ast_length) + p.formatting = :Bold + p.children += val[1] + result = p + } + | ITALIC_START repeated_contents ITALIC_END + { + p = FormattedAST.new(@ast_index, @ast_length) + p.formatting = :Italic + p.children += val[1] + result = p + } + ; + +bulleted_list: UL_START list_item list_contents UL_END + { + list = ListAST.new(@ast_index, @ast_length) + list.list_type = :Bulleted + list.children << val[1] + list.children += val[2] + result = list + } + ; + +numbered_list: OL_START list_item list_contents OL_END + { + list = ListAST.new(@ast_index, @ast_length) + list.list_type = :Numbered + list.children << val[1] + list.children += val[2] + result = list + } + ; + +list_contents: + { result = [] } + list_item list_contents + { + result << val[1] + result += val[2] + } + | + { result = [] } + ; + +list_item: + LI_START LI_END + { + result = ListItemAST.new(@ast_index, @ast_length) + } + | LI_START repeated_contents LI_END + { + li = ListItemAST.new(@ast_index, @ast_length) + li.children += val[1] + result = li + } + ; + +dictionary_list: + DL_START dictionary_term dictionary_contents DL_END + { + result = [val[1]] + result += val[2] + } + | DL_START dictionary_contents DL_END + { + result = val[1] + } + ; + +dictionary_term: + DT_START DT_END + { + result = ListTermAST.new(@ast_index, @ast_length) + } + | DT_START repeated_contents DT_END + { + term = ListTermAST.new(@ast_index, @ast_length) + term.children += val[1] + result = term + } + +dictionary_contents: + dictionary_definition dictionary_contents + { + result = [val[0]] + result += val[1] if val[1] + } + | + { + result = [] + } + +dictionary_definition: + DD_START DD_END + { + result = ListDefinitionAST.new(@ast_index, @ast_length) + } + | DD_START repeated_contents DD_END + { + term = ListDefinitionAST.new(@ast_index, @ast_length) + term.children += val[1] + result = term + } + +preformatted: PRE_START repeated_contents PRE_END + { + p = PreformattedAST.new(@ast_index, @ast_length) + p.children += val[1] + result = p + } + | PREINDENT_START repeated_contents PREINDENT_END + { + p = PreformattedAST.new(@ast_index, @ast_length) + p.indented = true + p.children += val[1] + result = p + } + ; + +section: SECTION_START repeated_contents SECTION_END + { result = [val[1], val[0].length] + s = SectionAST.new(@ast_index, @ast_length) + s.children = val[1] + s.level = val[0].length + result = s + } + ; + +template: TEMPLATE_START TEXT template_parameters TEMPLATE_END + { + t = TemplateAST.new(@ast_index, @ast_length) + t.template_name = val[1] + t.children = val[2] unless val[2].nil? or val[2].empty? + result = t + } + ; + +template_parameters: + { + result = nil + } + | INTLINKSEP TEXT template_parameters + { + p = TemplateParameterAST.new(@ast_index, @ast_length) + p.parameter_value = val[1] + result = [p] + result += val[2] if val[2] + } + | INTLINKSEP template template_parameters + { + p = TemplateParameterAST.new(@ast_index, @ast_length) + p.children << val[1] + result = [p] + result += val[2] if val[2] + } + ; + +end + +---- header ---- +require 'mediacloth/mediawikiast' + +---- inner ---- + +attr_accessor :lexer + +def initialize + @nodes = [] + @context = [] + @wiki_ast_length = 0 + super +end + +#Tokenizes input string and parses it. +def parse(input) + @yydebug=true + lexer.tokenize(input) + do_parse + return @nodes.last +end + +#Asks the lexer to return the next token. +def next_token + token = @lexer.lex + if token[0].to_s.upcase.include? "_START" + @context << token[2..3] + elsif token[0].to_s.upcase.include? "_END" + @ast_index = @context.last[0] + @ast_length = token[2] + token[3] - @context.last[0] + @context.pop + else + @ast_index = token[2] + @ast_length = token[3] + end + + @wiki_ast_length += token[3] + + return token[0..1] +end diff --git a/test/assets/mof.y b/test/assets/mof.y new file mode 100644 index 00000000..1adc5ade --- /dev/null +++ b/test/assets/mof.y @@ -0,0 +1,649 @@ +# Distributed under the Ruby license +# See http://www.ruby-lang.org/en/LICENSE.txt for the full license text +# Copyright (c) 2010 Klaus Kämpf + +/* + * According to appendix A of + * http://www.dmtf.org/standards/cim/cim_spec_v22 + */ + +class MOF::Parser + prechigh +/* nonassoc UMINUS */ + left '*' '/' + left '+' '-' + preclow + + token PRAGMA INCLUDE IDENTIFIER CLASS ASSOCIATION INDICATION + AMENDED ENABLEOVERRIDE DISABLEOVERRIDE RESTRICTED TOSUBCLASS TOINSTANCE + TRANSLATABLE QUALIFIER SCOPE SCHEMA PROPERTY REFERENCE + METHOD PARAMETER FLAVOR INSTANCE + AS REF ANY OF + DT_VOID + DT_UINT8 DT_SINT8 DT_UINT16 DT_SINT16 DT_UINT32 DT_SINT32 + DT_UINT64 DT_SINT64 DT_REAL32 DT_REAL64 DT_CHAR16 DT_STR + DT_BOOLEAN DT_DATETIME + positiveDecimalValue + stringValue + realValue + charValue + booleanValue + nullValue + binaryValue + octalValue + decimalValue + hexValue + +rule + + /* Returns a Hash of filename and MofResult */ + mofSpecification + : /* empty */ + { result = Hash.new } + | mofProduction + { result = { @name => @result } } + | mofSpecification mofProduction + { result = val[0] + result[@name] = @result + } + ; + + mofProduction + : compilerDirective + | classDeclaration + { #puts "Class '#{val[0].name}'" + @result.classes << val[0] + } + | qualifierDeclaration + { @result.qualifiers << val[0] + @qualifiers[val[0].name.downcase] = val[0] + } + | instanceDeclaration + { @result.instances << val[0] } + ; + +/*** + * compilerDirective + * + */ + + compilerDirective + : "#" PRAGMA INCLUDE pragmaParameters_opt + { raise MOF::Helper::Error.new(@name,@lineno,@line,"Missing filename after '#pragma include'") unless val[3] + open val[3], :pragma + } + | "#" PRAGMA pragmaName pragmaParameters_opt + | "#" INCLUDE pragmaParameters_opt + { raise StyleError.new(@name,@lineno,@line,"Use '#pragma include' instead of '#include'") unless @style == :wmi + raise MOF::Helper::Error.new(@name,@lineno,@line,"Missing filename after '#include'") unless val[2] + open val[2], :pragma + } + ; + + pragmaName + : IDENTIFIER + ; + + pragmaParameters_opt + : /* empty */ + { raise StyleError.new(@name,@lineno,@line,"#pragma parameter missing") unless @style == :wmi } + | "(" pragmaParameterValues ")" + { result = val[1] } + ; + + pragmaParameterValues + : pragmaParameterValue + | pragmaParameterValues "," pragmaParameterValue + ; + + pragmaParameterValue + : string + | integerValue + { raise StyleError.new(@name,@lineno,@line,"#pragma parameter missing") unless @style == :wmi } + | IDENTIFIER + ; + +/*** + * classDeclaration + * + */ + + classDeclaration + : qualifierList_opt CLASS className alias_opt superClass_opt "{" classFeatures "}" ";" + { qualifiers = val[0] + features = val[6] + # FIXME: features must not include references + result = CIM::Class.new(val[2],qualifiers,val[3],val[4],features) + } + ; + + classFeatures + : /* empty */ + { result = [] } + | classFeatures classFeature + { result = val[0] << val[1] } + ; + + classFeature + : propertyDeclaration + | methodDeclaration + | referenceDeclaration /* must have association qualifier */ + ; + + + qualifierList_opt + : /* empty */ + | qualifierList + { result = CIM::QualifierSet.new val[0] } + ; + + qualifierList + : "[" qualifier qualifiers "]" + { result = val[2] + result.unshift val[1] if val[1] } + ; + + qualifiers + : /* empty */ + { result = [] } + | qualifiers "," qualifier + { result = val[0] + result << val[2] if val[2] + } + ; + + qualifier + : qualifierName qualifierParameter_opt flavor_opt + { # Get qualifier decl + qualifier = case val[0] + when CIM::Qualifier then val[0].definition + when CIM::QualifierDeclaration then val[0] + when String then @qualifiers[val[0].downcase] + else + nil + end + raise MOF::Helper::Error.new(@name,@lineno,@line,"'#{val[0]}' is not a valid qualifier") unless qualifier + value = val[1] + raise MOF::Helper::Error.new(@name,@lineno,@line,"#{value.inspect} does not match qualifier type '#{qualifier.type}'") unless qualifier.type.matches?(value)||@style == :wmi + # Don't propagate a boolean 'false' + if qualifier.type == :boolean && value == false + result = nil + else + result = CIM::Qualifier.new(qualifier,value,val[2]) + end + } + ; + + flavor_opt + : /* empty */ + | ":" flavor + { result = CIM::QualifierFlavors.new val[1] } + ; + + qualifierParameter_opt + : /* empty */ + | qualifierParameter + ; + + qualifierParameter + : "(" constantValue ")" + { result = val[1] } + | arrayInitializer + ; + + /* CIM::Flavors */ + flavor + : AMENDED | ENABLEOVERRIDE | DISABLEOVERRIDE | RESTRICTED | TOSUBCLASS | TRANSLATABLE | TOINSTANCE + { case val[0].to_sym + when :amended, :toinstance + raise StyleError.new(@name,@lineno,@line,"'#{val[0]}' is not a valid flavor") unless @style == :wmi + end + } + ; + + alias_opt + : /* empty */ + | alias + ; + + superClass_opt + : /* empty */ + | superClass + ; + + className + : IDENTIFIER /* must be _ in CIM v2.x */ + { raise ParseError.new("Class name must be prefixed by '_'") unless val[0].include?("_") || @style == :wmi } + ; + + alias + : AS aliasIdentifier + { result = val[1] } + ; + + aliasIdentifier + : "$" IDENTIFIER /* NO whitespace ! */ + { result = val[1] } + ; + + superClass + : ":" className + { result = val[1] } + ; + + + propertyDeclaration + : qualifierList_opt dataType propertyName array_opt defaultValue_opt ";" + { if val[3] + type = CIM::Array.new val[3],val[1] + else + type = val[1] + end + result = CIM::Property.new(type,val[2],val[0],val[4]) + } + ; + + referenceDeclaration + : qualifierList_opt objectRef referenceName array_opt defaultValue_opt ";" + { if val[4] + raise StyleError.new(@name,@lineno,@line,"Array not allowed in reference declaration") unless @style == :wmi + end + result = CIM::Reference.new(val[1],val[2],val[0],val[4]) } + ; + + methodDeclaration + : qualifierList_opt dataType methodName "(" parameterList_opt ")" ";" + { result = CIM::Method.new(val[1],val[2],val[0],val[4]) } + ; + + propertyName + : IDENTIFIER + | PROPERTY + { # tmplprov.mof has 'string Property;' + raise StyleError.new(@name,@lineno,@line,"Invalid keyword '#{val[0]}' used for property name") unless @style == :wmi + } + ; + + referenceName + : IDENTIFIER + | INDICATION + { result = "Indication" } + ; + + methodName + : IDENTIFIER + ; + + dataType + : DT_UINT8 + | DT_SINT8 + | DT_UINT16 + | DT_SINT16 + | DT_UINT32 + | DT_SINT32 + | DT_UINT64 + | DT_SINT64 + | DT_REAL32 + | DT_REAL64 + | DT_CHAR16 + | DT_STR + | DT_BOOLEAN + | DT_DATETIME + | DT_VOID + { raise StyleError.new(@name,@lineno,@line,"'void' is not a valid datatype") unless @style == :wmi } + ; + + objectRef + : className + { # WMI uses class names as data types (without REF ?!) + raise StyleError.new(@name,@lineno,@line,"Expected 'ref' keyword after classname '#{val[0]}'") unless @style == :wmi + result = CIM::ReferenceType.new val[0] + } + + | className REF + { result = CIM::ReferenceType.new val[0] } + ; + + parameterList_opt + : /* empty */ + | parameterList + ; + + parameterList + : parameter parameters + { result = val[1].unshift val[0] } + ; + + parameters + : /* empty */ + { result = [] } + | parameters "," parameter + { result = val[0] << val[2] } + ; + + parameter + : qualifierList_opt typespec parameterName array_opt parameterValue_opt + { if val[3] + type = CIM::Array.new val[3], val[1] + else + type = val[1] + end + result = CIM::Property.new(type,val[2],val[0]) + } + ; + + typespec + : dataType + | objectRef + ; + + parameterName + : IDENTIFIER + ; + + array_opt + : /* empty */ + | array + ; + + parameterValue_opt + : /* empty */ + | defaultValue + { raise "Default parameter value not allowed in syntax style '{@style}'" unless @style == :wmi } + ; + + array + : "[" positiveDecimalValue_opt "]" + { result = val[1] } + ; + + positiveDecimalValue_opt + : /* empty */ + { result = -1 } + | positiveDecimalValue + ; + + defaultValue_opt + : /* empty */ + | defaultValue + ; + + defaultValue + : "=" initializer + { result = val[1] } + ; + + initializer + : constantValue + | arrayInitializer + | referenceInitializer + ; + + arrayInitializer + : "{" constantValues "}" + { result = val[1] } + ; + + constantValues + : /* empty */ + | constantValue + { result = [ val[0] ] } + | constantValues "," constantValue + { result = val[0] << val[2] } + ; + + constantValue + : integerValue + | realValue + | charValue + | string + | booleanValue + | nullValue + | instance + { raise "Instance as property value not allowed in syntax style '{@style}'" unless @style == :wmi } + ; + + integerValue + : binaryValue + | octalValue + | decimalValue + | positiveDecimalValue + | hexValue + ; + + string + : stringValue + | string stringValue + { result = val[0] + val[1] } + ; + + referenceInitializer + : objectHandle + | aliasIdentifier + ; + + objectHandle + : namespace_opt modelPath + ; + + namespace_opt + : /* empty */ + | namespaceHandle ":" + ; + + namespaceHandle + : IDENTIFIER + ; + + /* + * Note + : structure depends on type of namespace + */ + + modelPath + : className "." keyValuePairList + ; + + keyValuePairList + : keyValuePair keyValuePairs + ; + + keyValuePairs + : /* empty */ + | keyValuePairs "," keyValuePair + ; + + keyValuePair + : keyname "=" initializer + ; + + keyname + : propertyName | referenceName + ; + +/*** + * qualifierDeclaration + * + */ + + qualifierDeclaration + /* 0 1 2 3 4 */ + : QUALIFIER qualifierName qualifierType scope defaultFlavor_opt ";" + { result = CIM::QualifierDeclaration.new( val[1], val[2][0], val[2][1], val[3], val[4]) } + ; + + defaultFlavor_opt + : /* empty */ + | defaultFlavor + ; + + qualifierName + : IDENTIFIER + | ASSOCIATION /* meta qualifier */ + | INDICATION /* meta qualifier */ + | REFERENCE /* Added in DSP0004 2.7.0 */ + | SCHEMA + ; + + /* [type, value] */ + qualifierType + : ":" dataType array_opt defaultValue_opt + { type = val[2].nil? ? val[1] : CIM::Array.new(val[2],val[1]) + result = [ type, val[3] ] + } + ; + + scope + : "," SCOPE "(" metaElements ")" + { result = CIM::QualifierScopes.new(val[3]) } + ; + + metaElements + : metaElement + { result = [ val[0] ] } + | metaElements "," metaElement + { result = val[0] << val[2] } + ; + + metaElement + : SCHEMA + | CLASS + | ASSOCIATION + | INDICATION + | QUALIFIER + | PROPERTY + | REFERENCE + | METHOD + | PARAMETER + | ANY + ; + + defaultFlavor + : "," FLAVOR "(" flavors ")" + { result = CIM::QualifierFlavors.new val[3] } + ; + + flavors + : flavor + { result = [ val[0] ] } + | flavors "," flavor + { result = val[0] << val[2] } + ; + +/*** + * instanceDeclaration + * + */ + + instanceDeclaration + : instance ";" + ; + + instance + : qualifierList_opt INSTANCE OF className alias_opt "{" valueInitializers "}" + ; + + valueInitializers + : valueInitializer + | valueInitializers valueInitializer + ; + + valueInitializer + : qualifierList_opt keyname "=" initializer ";" + | qualifierList_opt keyname ";" + { raise "Instance property '#{val[1]} must have a value" unless @style == :wmi } + ; + +end # class Parser + +---- header ---- + +# parser.rb - generated by racc + +require 'strscan' +require 'rubygems' +require 'cim' +require File.join(File.dirname(__FILE__), 'result') +require File.join(File.dirname(__FILE__), 'scanner') +require File.join(File.dirname(__FILE__), 'helper') + +---- inner ---- + +# +# Initialize MOF::Parser +# MOF::Parser.new options = {} +# +# options -> Hash of options +# :debug -> boolean +# :includes -> array of include dirs +# :style -> :cim or :wmi +# +def initialize options = {} + @yydebug = options[:debug] + @includes = options[:includes] || [] + @quiet = options[:quiet] + @style = options[:style] || :cim # default to style CIM v2.2 syntax + + @lineno = 1 + @file = nil + @iconv = nil + @eol = "\n" + @fname = nil + @fstack = [] + @in_comment = false + @seen_files = [] + @qualifiers = {} +end + +# +# Make options hash from argv +# +# returns [ files, options ] +# + + def self.argv_handler name, argv + files = [] + options = { :namespace => "" } + while argv.size > 0 + case opt = argv.shift + when "-h" + $stderr.puts "Ruby MOF compiler" + $stderr.puts "#{name} [-h] [-d] [-I ] []" + $stderr.puts "Compiles " + $stderr.puts "\t-d debug" + $stderr.puts "\t-h this help" + $stderr.puts "\t-I include dir" + $stderr.puts "\t-f force" + $stderr.puts "\t-n " + $stderr.puts "\t-o " + $stderr.puts "\t-s + + + + +

State 0 (start state)

+ +

+ +
$start:. document $end $end

+ + + +

+ + From here, we reduce by @action1 : regardless of what token + comes next.
+ + (This takes us to 2) + + +

+
+ +

State 1

+ +

+ +
$start:document . $end $end

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stylesheet by:
stylesheet :
stylesheet
Reduce to document by:
document : stylesheet
document
+

+ +

+ + Action table:
+
Lookahead tokenAction
$endShift and go to state 3
OtherError
+ +

+
+ +

State 2

+ +

+ +
document:. stylesheet

+ + + +

+ + Action table:
+
Lookahead tokenAction
CHARSET_SYMShift and go to state 9
IMPORT_SYMShift and go to state 10
IDENTShift and go to state 37
SShift and go to state 31
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
MEDIA_SYMShift and go to state 20
DOCUMENT_QUERY_SYMShift and go to state 23
KEYFRAMES_SYMShift and go to state 27
NAMESPACE_SYMShift and go to state 11
COLONShift and go to state 48
SUPPORTS_SYMShift and go to state 25
FONTFACE_SYMShift and go to state 29
"|"Shift and go to state 38
"."Shift and go to state 46
OtherReduce by stylesheet :
(This takes us to 4)
+ +

+
+ +

State 3

+ +

+ +
$start:document $end . $end

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stylesheet by:
stylesheet :
stylesheet
Reduce to document by:
document : stylesheet
document
Shift $end document $end
+

+ +

+ + Action table:
+
Lookahead tokenAction
$endShift and go to state 49
OtherError
+ +

+
+ +

State 4

+ +

+ +
document:stylesheet .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stylesheet by:
stylesheet :
stylesheet
+

+ +

+ + From here, we reduce by document : stylesheet regardless of what token + comes next.
+ + (This takes us to 1) + + +

+
+ +

State 5

+ +

+ +
stylesheet:charset . stylesheet
stylesheet:charset .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift CHARSET_SYM CHARSET_SYM
Shift STRING CHARSET_SYM STRING
Shift SEMI CHARSET_SYM STRING SEMI
Reduce to charset by:
charset : CHARSET_SYM STRING SEMI
charset
+

+ +

+ + Action table:
+
Lookahead tokenAction
CHARSET_SYMShift and go to state 9
IMPORT_SYMShift and go to state 10
IDENTShift and go to state 37
SShift and go to state 31
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
MEDIA_SYMShift and go to state 20
DOCUMENT_QUERY_SYMShift and go to state 23
KEYFRAMES_SYMShift and go to state 27
NAMESPACE_SYMShift and go to state 11
COLONShift and go to state 48
SUPPORTS_SYMShift and go to state 25
FONTFACE_SYMShift and go to state 29
"|"Shift and go to state 38
"."Shift and go to state 46
OtherReduce by stylesheet : charset
(This can take us to 4, 50, 51 or 52)
+ +

+
+ +

State 6

+ +

+ +
stylesheet:import . stylesheet
stylesheet:import .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift STRING IMPORT_SYM STRING
Reduce to import_location by:
import_location : STRING
IMPORT_SYM import_location
Shift SEMI IMPORT_SYM import_location SEMI
Reduce to import by:
import : IMPORT_SYM import_location SEMI
import
+

+ +

+ + Action table:
+
Lookahead tokenAction
CHARSET_SYMShift and go to state 9
IMPORT_SYMShift and go to state 10
IDENTShift and go to state 37
SShift and go to state 31
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
MEDIA_SYMShift and go to state 20
DOCUMENT_QUERY_SYMShift and go to state 23
KEYFRAMES_SYMShift and go to state 27
NAMESPACE_SYMShift and go to state 11
COLONShift and go to state 48
SUPPORTS_SYMShift and go to state 25
FONTFACE_SYMShift and go to state 29
"|"Shift and go to state 38
"."Shift and go to state 46
OtherReduce by stylesheet : import
(This can take us to 4, 50, 51 or 52)
+ +

+
+ +

State 7

+ +

+ +
stylesheet:namespace . stylesheet
stylesheet:namespace .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift NAMESPACE_SYM NAMESPACE_SYM
Shift STRING NAMESPACE_SYM STRING
Reduce to import_location by:
import_location : STRING
NAMESPACE_SYM import_location
Shift SEMI NAMESPACE_SYM import_location SEMI
Reduce to namespace by:
namespace : NAMESPACE_SYM import_location SEMI
namespace
+

+ +

+ + Action table:
+
Lookahead tokenAction
CHARSET_SYMShift and go to state 9
IMPORT_SYMShift and go to state 10
IDENTShift and go to state 37
SShift and go to state 31
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
MEDIA_SYMShift and go to state 20
DOCUMENT_QUERY_SYMShift and go to state 23
KEYFRAMES_SYMShift and go to state 27
NAMESPACE_SYMShift and go to state 11
COLONShift and go to state 48
SUPPORTS_SYMShift and go to state 25
FONTFACE_SYMShift and go to state 29
"|"Shift and go to state 38
"."Shift and go to state 46
OtherReduce by stylesheet : namespace
(This can take us to 4, 50, 51 or 52)
+ +

+
+ +

State 8

+ +

+ +
stylesheet:body .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
Reduce to selectors by:
selectors : selector
selectors
Shift LBRACE selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_selector
Shift RBRACE start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
ruleset
Reduce to body by:
body : ruleset
body
+

+ +

+ + From here, we reduce by stylesheet : body regardless of what token + comes next.
+ + (This can take us to 4, 50, 51 or 52) + + +

+
+ +

State 9

+ +

+ +
charset:CHARSET_SYM . STRING SEMI

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift CHARSET_SYM CHARSET_SYM
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 53
OtherError
+ +

+
+ +

State 10

+ +

+ +
import:IMPORT_SYM . import_location medium SEMI
import:IMPORT_SYM . import_location SEMI

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 55
URIShift and go to state 56
OtherError
+ +

+
+ +

State 11

+ +

+ +
namespace:NAMESPACE_SYM . ident import_location SEMI
namespace:NAMESPACE_SYM . import_location SEMI

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift NAMESPACE_SYM NAMESPACE_SYM
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 55
IDENTShift and go to state 59
URIShift and go to state 56
OtherError
+ +

+
+ +

State 12

+ +

+ +
body:ruleset . body
body:ruleset .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
Reduce to selectors by:
selectors : selector
selectors
Shift LBRACE selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_selector
Shift RBRACE start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
ruleset
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
SShift and go to state 31
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
MEDIA_SYMShift and go to state 20
DOCUMENT_QUERY_SYMShift and go to state 23
KEYFRAMES_SYMShift and go to state 27
COLONShift and go to state 48
SUPPORTS_SYMShift and go to state 25
FONTFACE_SYMShift and go to state 29
"|"Shift and go to state 38
"."Shift and go to state 46
OtherReduce by body : ruleset
(This can take us to 8, 60, 61, 62, 63, 65, 76 or 86)
+ +

+
+ +

State 13

+ +

+ +
body:conditional_rule . body
body:conditional_rule .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift LBRACE MEDIA_SYM media_query_list LBRACE
Reduce to start_media by:
start_media : MEDIA_SYM media_query_list LBRACE
start_media
Reduce to optional_space by:
optional_space :
start_media optional_space
Reduce to empty_ruleset by:
empty_ruleset : optional_space
start_media empty_ruleset
Reduce to body_in_media by:
body_in_media : empty_ruleset
start_media body_in_media
Shift RBRACE start_media body_in_media RBRACE
Reduce to media by:
media : start_media body_in_media RBRACE
media
Reduce to conditional_rule by:
conditional_rule : media
conditional_rule
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
SShift and go to state 31
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
MEDIA_SYMShift and go to state 20
DOCUMENT_QUERY_SYMShift and go to state 23
KEYFRAMES_SYMShift and go to state 27
COLONShift and go to state 48
SUPPORTS_SYMShift and go to state 25
FONTFACE_SYMShift and go to state 29
"|"Shift and go to state 38
"."Shift and go to state 46
OtherReduce by body : conditional_rule
(This can take us to 8, 60, 61, 62, 63, 65, 76 or 86)
+ +

+
+ +

State 14

+ +

+ +
body:keyframes_rule . body
body:keyframes_rule .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Shift RBRACE start_keyframes_rule RBRACE
Reduce to keyframes_rule by:
keyframes_rule : start_keyframes_rule RBRACE
keyframes_rule
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
SShift and go to state 31
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
MEDIA_SYMShift and go to state 20
DOCUMENT_QUERY_SYMShift and go to state 23
KEYFRAMES_SYMShift and go to state 27
COLONShift and go to state 48
SUPPORTS_SYMShift and go to state 25
FONTFACE_SYMShift and go to state 29
"|"Shift and go to state 38
"."Shift and go to state 46
OtherReduce by body : keyframes_rule
(This can take us to 8, 60, 61, 62, 63, 65, 76 or 86)
+ +

+
+ +

State 15

+ +

+ +
body:fontface_rule . body
body:fontface_rule .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift RBRACE start_fontface_rule RBRACE
Reduce to fontface_rule by:
fontface_rule : start_fontface_rule RBRACE
fontface_rule
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
SShift and go to state 31
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
MEDIA_SYMShift and go to state 20
DOCUMENT_QUERY_SYMShift and go to state 23
KEYFRAMES_SYMShift and go to state 27
COLONShift and go to state 48
SUPPORTS_SYMShift and go to state 25
FONTFACE_SYMShift and go to state 29
"|"Shift and go to state 38
"."Shift and go to state 46
OtherReduce by body : fontface_rule
(This can take us to 8, 60, 61, 62, 63, 65, 76 or 86)
+ +

+
+ +

State 16

+ +

+ +
conditional_rule:media .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift LBRACE MEDIA_SYM media_query_list LBRACE
Reduce to start_media by:
start_media : MEDIA_SYM media_query_list LBRACE
start_media
Reduce to optional_space by:
optional_space :
start_media optional_space
Reduce to empty_ruleset by:
empty_ruleset : optional_space
start_media empty_ruleset
Reduce to body_in_media by:
body_in_media : empty_ruleset
start_media body_in_media
Shift RBRACE start_media body_in_media RBRACE
Reduce to media by:
media : start_media body_in_media RBRACE
media
+

+ +

+ + From here, we reduce by conditional_rule : media regardless of what token + comes next.
+ + (This takes us to 13) + + +

+
+ +

State 17

+ +

+ +
conditional_rule:document_query .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
Reduce to url_match_fn by:
url_match_fn : function_no_quote
start_document_query_pos url_match_fn
Reduce to url_match_fns by:
url_match_fns : url_match_fn
start_document_query_pos url_match_fns
Shift LBRACE start_document_query_pos url_match_fns LBRACE
Reduce to start_document_query by:
start_document_query : start_document_query_pos url_match_fns LBRACE
start_document_query
Shift RBRACE start_document_query RBRACE
Reduce to document_query by:
document_query : start_document_query RBRACE
document_query
+

+ +

+ + From here, we reduce by conditional_rule : document_query regardless of what token + comes next.
+ + (This takes us to 13) + + +

+
+ +

State 18

+ +

+ +
conditional_rule:supports .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Reduce to supports_condition_root by:
supports_condition_root : supports_condition_in_parens
SUPPORTS_SYM supports_condition_root
Shift LBRACE SUPPORTS_SYM supports_condition_root LBRACE
Reduce to start_supports by:
start_supports : SUPPORTS_SYM supports_condition_root LBRACE
start_supports
Shift RBRACE start_supports RBRACE
Reduce to supports by:
supports : start_supports RBRACE
supports
+

+ +

+ + From here, we reduce by conditional_rule : supports regardless of what token + comes next.
+ + (This takes us to 13) + + +

+
+ +

State 19

+ +

+ +
media:start_media . body_in_media RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift LBRACE MEDIA_SYM media_query_list LBRACE
Reduce to start_media by:
start_media : MEDIA_SYM media_query_list LBRACE
start_media
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
SShift and go to state 64
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
MEDIA_SYMShift and go to state 20
DOCUMENT_QUERY_SYMShift and go to state 23
KEYFRAMES_SYMShift and go to state 27
COLONShift and go to state 48
SUPPORTS_SYMShift and go to state 25
FONTFACE_SYMShift and go to state 29
"|"Shift and go to state 38
"."Shift and go to state 46
OtherReduce by optional_space :
(This takes us to 68)
+ +

+
+ +

State 20

+ +

+ +
start_media:MEDIA_SYM . media_query_list LBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTReduce by optional_only_or_not :
(This takes us to 71)
LPARENShift and go to state 75
NOTShift and go to state 74
ONLYShift and go to state 73
OtherReduce by media_query_list :
(This takes us to 70)
+ +

+
+ +

State 21

+ +

+ +
document_query:start_document_query . body RBRACE
document_query:start_document_query . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
Reduce to url_match_fn by:
url_match_fn : function_no_quote
start_document_query_pos url_match_fn
Reduce to url_match_fns by:
url_match_fns : url_match_fn
start_document_query_pos url_match_fns
Shift LBRACE start_document_query_pos url_match_fns LBRACE
Reduce to start_document_query by:
start_document_query : start_document_query_pos url_match_fns LBRACE
start_document_query
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
SShift and go to state 31
RBRACEShift and go to state 77
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
MEDIA_SYMShift and go to state 20
DOCUMENT_QUERY_SYMShift and go to state 23
KEYFRAMES_SYMShift and go to state 27
COLONShift and go to state 48
SUPPORTS_SYMShift and go to state 25
FONTFACE_SYMShift and go to state 29
"|"Shift and go to state 38
"."Shift and go to state 46
OtherError
+ +

+
+ +

State 22

+ +

+ +
start_document_query:start_document_query_pos . url_match_fns LBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
+

+ +

+ + Action table:
+
Lookahead tokenAction
FUNCTIONShift and go to state 83
URIShift and go to state 85
FUNCTION_NO_QUOTEShift and go to state 84
OtherError
+ +

+
+ +

State 23

+ +

+ +
start_document_query_pos:DOCUMENT_QUERY_SYM .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
+

+ +

+ + From here, we reduce by start_document_query_pos : DOCUMENT_QUERY_SYM regardless of what token + comes next.
+ + (This takes us to 22) + + +

+
+ +

State 24

+ +

+ +
supports:start_supports . body RBRACE
supports:start_supports . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Reduce to supports_condition_root by:
supports_condition_root : supports_condition_in_parens
SUPPORTS_SYM supports_condition_root
Shift LBRACE SUPPORTS_SYM supports_condition_root LBRACE
Reduce to start_supports by:
start_supports : SUPPORTS_SYM supports_condition_root LBRACE
start_supports
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
SShift and go to state 31
RBRACEShift and go to state 87
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
MEDIA_SYMShift and go to state 20
DOCUMENT_QUERY_SYMShift and go to state 23
KEYFRAMES_SYMShift and go to state 27
COLONShift and go to state 48
SUPPORTS_SYMShift and go to state 25
FONTFACE_SYMShift and go to state 29
"|"Shift and go to state 38
"."Shift and go to state 46
OtherError
+ +

+
+ +

State 25

+ +

+ +
start_supports:SUPPORTS_SYM . supports_condition_root LBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 92
NOTShift and go to state 94
OtherError
+ +

+
+ +

State 26

+ +

+ +
keyframes_rule:start_keyframes_rule . keyframes_blocks RBRACE
keyframes_rule:start_keyframes_rule . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 103
RBRACEShift and go to state 98
PERCENTAGEShift and go to state 104
OtherReduce by keyframes_selectors :
(This takes us to 101)
+ +

+
+ +

State 27

+ +

+ +
start_keyframes_rule:KEYFRAMES_SYM . IDENT LBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 105
OtherError
+ +

+
+ +

State 28

+ +

+ +
fontface_rule:start_fontface_rule . declarations RBRACE
fontface_rule:start_fontface_rule . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 108
IDENTShift and go to state 113
RBRACEShift and go to state 107
STARShift and go to state 114
VARIABLE_NAMEShift and go to state 115
OtherError
+ +

+
+ +

State 29

+ +

+ +
start_fontface_rule:FONTFACE_SYM . LBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
+

+ +

+ + Action table:
+
Lookahead tokenAction
LBRACEShift and go to state 116
OtherError
+ +

+
+ +

State 30

+ +

+ +
ruleset:start_selector . declarations RBRACE
ruleset:start_selector . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
Reduce to selectors by:
selectors : selector
selectors
Shift LBRACE selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_selector
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 108
IDENTShift and go to state 113
RBRACEShift and go to state 118
STARShift and go to state 114
VARIABLE_NAMEShift and go to state 115
OtherError
+ +

+
+ +

State 31

+ +

+ +
start_selector:S . start_selector

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift S S
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
SShift and go to state 31
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"|"Shift and go to state 38
"."Shift and go to state 46
OtherError
+ +

+
+ +

State 32

+ +

+ +
start_selector:selectors . LBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
Reduce to selectors by:
selectors : selector
selectors
+

+ +

+ + Action table:
+
Lookahead tokenAction
LBRACEShift and go to state 120
OtherError
+ +

+
+ +

State 33

+ +

+ +
selectors:selector . COMMA selectors
selectors:selector .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
+

+ +

+ + Action table:
+
Lookahead tokenAction
COMMAShift and go to state 121
OtherReduce by selectors : selector
(This can take us to 32 or 227)
+ +

+
+ +

State 34

+ +

+ +
selector:simple_selector . combinator selector
selector:simple_selector .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 123
GREATERShift and go to state 124
PLUSShift and go to state 125
TILDEShift and go to state 126
OtherReduce by selector : simple_selector
(This can take us to 33 or 228)
+ +

+
+ +

State 35

+ +

+ +
simple_selector:element_name . hcap
simple_selector:element_name .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
+

+ +

+ + Action table:
+
Lookahead tokenAction
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"."Shift and go to state 46
OtherReduce by simple_selector : element_name
(This can take us to 34, 246 or 247)
+ +

+
+ +

State 36

+ +

+ +
simple_selector:hcap .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift HASH HASH
Reduce to hash by:
hash : HASH
hash
Reduce to hcap by:
hcap : hash
hcap
+

+ +

+ + From here, we reduce by simple_selector : hcap regardless of what token + comes next.
+ + (This can take us to 34, 246 or 247) + + +

+
+ +

State 37

+ +

+ +
ident_with_namespace:IDENT .
ident_with_namespace:IDENT . "|" IDENT
element_name:IDENT . "|" STAR

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
"|"Shift and go to state 128
OtherReduce by ident_with_namespace : IDENT
(This takes us to 40)
+ +

+
+ +

State 38

+ +

+ +
ident_with_namespace:"|" . IDENT
element_name:"|" . STAR

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift "|" "|"
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 129
STARShift and go to state 130
OtherError
+ +

+
+ +

State 39

+ +

+ +
ident_with_namespace:STAR . "|" IDENT
element_name:STAR .
element_name:STAR . "|" STAR

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift STAR STAR
+

+ +

+ + Action table:
+
Lookahead tokenAction
"|"Shift and go to state 131
OtherReduce by element_name : STAR
(This takes us to 35)
+ +

+
+ +

State 40

+ +

+ +
element_name:ident_with_namespace .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
+

+ +

+ + From here, we reduce by element_name : ident_with_namespace regardless of what token + comes next.
+ + (This takes us to 35) + + +

+
+ +

State 41

+ +

+ +
hcap:hash .
hcap:hash . hcap

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift HASH HASH
Reduce to hash by:
hash : HASH
hash
+

+ +

+ + Action table:
+
Lookahead tokenAction
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"."Shift and go to state 46
OtherReduce by hcap : hash
(This can take us to 36, 127, 132, 133, 134 or 135)
+ +

+
+ +

State 42

+ +

+ +
hcap:class .
hcap:class . hcap

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift "." "."
Shift IDENT "." IDENT
Reduce to class by:
class : "." IDENT
class
+

+ +

+ + Action table:
+
Lookahead tokenAction
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"."Shift and go to state 46
OtherReduce by hcap : class
(This can take us to 36, 127, 132, 133, 134 or 135)
+ +

+
+ +

State 43

+ +

+ +
hcap:attrib .
hcap:attrib . hcap

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift RSQUARE LSQUARE ident_with_namespace RSQUARE
Reduce to attrib by:
attrib : LSQUARE ident_with_namespace RSQUARE
attrib
+

+ +

+ + Action table:
+
Lookahead tokenAction
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"."Shift and go to state 46
OtherReduce by hcap : attrib
(This can take us to 36, 127, 132, 133, 134 or 135)
+ +

+
+ +

State 44

+ +

+ +
hcap:pseudo .
hcap:pseudo . hcap

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift IDENT COLON IDENT
Reduce to pseudo by:
pseudo : COLON IDENT
pseudo
+

+ +

+ + Action table:
+
Lookahead tokenAction
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"."Shift and go to state 46
OtherReduce by hcap : pseudo
(This can take us to 36, 127, 132, 133, 134 or 135)
+ +

+
+ +

State 45

+ +

+ +
hash:HASH .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift HASH HASH
+

+ +

+ + From here, we reduce by hash : HASH regardless of what token + comes next.
+ + (This takes us to 41) + + +

+
+ +

State 46

+ +

+ +
class:"." . IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift "." "."
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 136
OtherError
+ +

+
+ +

State 47

+ +

+ +
attrib:LSQUARE . ident_with_namespace EQUAL IDENT RSQUARE
attrib:LSQUARE . ident_with_namespace EQUAL STRING RSQUARE
attrib:LSQUARE . ident_with_namespace INCLUDES STRING RSQUARE
attrib:LSQUARE . ident_with_namespace INCLUDES IDENT RSQUARE
attrib:LSQUARE . ident_with_namespace DASHMATCH IDENT RSQUARE
attrib:LSQUARE . ident_with_namespace DASHMATCH STRING RSQUARE
attrib:LSQUARE . ident_with_namespace PREFIXMATCH IDENT RSQUARE
attrib:LSQUARE . ident_with_namespace PREFIXMATCH STRING RSQUARE
attrib:LSQUARE . ident_with_namespace SUFFIXMATCH IDENT RSQUARE
attrib:LSQUARE . ident_with_namespace SUFFIXMATCH STRING RSQUARE
attrib:LSQUARE . ident_with_namespace SUBSTRINGMATCH IDENT RSQUARE
attrib:LSQUARE . ident_with_namespace SUBSTRINGMATCH STRING RSQUARE
attrib:LSQUARE . ident_with_namespace RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 137
STARShift and go to state 139
"|"Shift and go to state 138
OtherError
+ +

+
+ +

State 48

+ +

+ +
pseudo:COLON . IDENT
pseudo:COLON . COLON IDENT
pseudo:COLON . FUNCTION RPAREN
pseudo:COLON . FUNCTION IDENT RPAREN
pseudo:COLON . NOT_PSEUDO_CLASS simple_selector RPAREN
pseudo:COLON . NTH_PSEUDO_CLASS
pseudo:COLON . MATCHES_PSEUDO_CLASS simple_selectors RPAREN
pseudo:COLON . MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN
pseudo:COLON . COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 141
FUNCTIONShift and go to state 143
NTH_PSEUDO_CLASSShift and go to state 145
NOT_PSEUDO_CLASSShift and go to state 144
MATCHES_PSEUDO_CLASSShift and go to state 146
MOZ_PSEUDO_ELEMENTShift and go to state 147
COLONShift and go to state 142
OtherError
+ +

+
+ +

State 49 (end state)

+ +

+ +
$start:document $end $end .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stylesheet by:
stylesheet :
stylesheet
Reduce to document by:
document : stylesheet
document
Shift $end document $end
Shift $end document $end $end
+

+ +

+ + From here, we stop parsing and return success regardless of what token + comes next.
+ + +

+
+ +

State 50

+ +

+ +
stylesheet:charset stylesheet .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift CHARSET_SYM CHARSET_SYM
Shift STRING CHARSET_SYM STRING
Shift SEMI CHARSET_SYM STRING SEMI
Reduce to charset by:
charset : CHARSET_SYM STRING SEMI
charset
Reduce to stylesheet by:
stylesheet :
charset stylesheet
+

+ +

+ + From here, we reduce by stylesheet : charset stylesheet regardless of what token + comes next.
+ + (This can take us to 4, 50, 51 or 52) + + +

+
+ +

State 51

+ +

+ +
stylesheet:import stylesheet .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift STRING IMPORT_SYM STRING
Reduce to import_location by:
import_location : STRING
IMPORT_SYM import_location
Shift SEMI IMPORT_SYM import_location SEMI
Reduce to import by:
import : IMPORT_SYM import_location SEMI
import
Reduce to stylesheet by:
stylesheet :
import stylesheet
+

+ +

+ + From here, we reduce by stylesheet : import stylesheet regardless of what token + comes next.
+ + (This can take us to 4, 50, 51 or 52) + + +

+
+ +

State 52

+ +

+ +
stylesheet:namespace stylesheet .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift NAMESPACE_SYM NAMESPACE_SYM
Shift STRING NAMESPACE_SYM STRING
Reduce to import_location by:
import_location : STRING
NAMESPACE_SYM import_location
Shift SEMI NAMESPACE_SYM import_location SEMI
Reduce to namespace by:
namespace : NAMESPACE_SYM import_location SEMI
namespace
Reduce to stylesheet by:
stylesheet :
namespace stylesheet
+

+ +

+ + From here, we reduce by stylesheet : namespace stylesheet regardless of what token + comes next.
+ + (This can take us to 4, 50, 51 or 52) + + +

+
+ +

State 53

+ +

+ +
charset:CHARSET_SYM STRING . SEMI

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift CHARSET_SYM CHARSET_SYM
Shift STRING CHARSET_SYM STRING
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 148
OtherError
+ +

+
+ +

State 54

+ +

+ +
import:IMPORT_SYM import_location . medium SEMI
import:IMPORT_SYM import_location . SEMI
import_location:import_location . S

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift STRING IMPORT_SYM STRING
Reduce to import_location by:
import_location : STRING
IMPORT_SYM import_location
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 150
IDENTShift and go to state 152
SShift and go to state 151
OtherError
+ +

+
+ +

State 55

+ +

+ +
import_location:STRING .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift STRING IMPORT_SYM STRING
+

+ +

+ + From here, we reduce by import_location : STRING regardless of what token + comes next.
+ + (This can take us to 54, 57 or 154) + + +

+
+ +

State 56

+ +

+ +
import_location:URI .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift URI IMPORT_SYM URI
+

+ +

+ + From here, we reduce by import_location : URI regardless of what token + comes next.
+ + (This can take us to 54, 57 or 154) + + +

+
+ +

State 57

+ +

+ +
import_location:import_location . S
namespace:NAMESPACE_SYM import_location . SEMI

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift NAMESPACE_SYM NAMESPACE_SYM
Shift STRING NAMESPACE_SYM STRING
Reduce to import_location by:
import_location : STRING
NAMESPACE_SYM import_location
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 153
SShift and go to state 151
OtherError
+ +

+
+ +

State 58

+ +

+ +
namespace:NAMESPACE_SYM ident . import_location SEMI
ident:ident . S

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift NAMESPACE_SYM NAMESPACE_SYM
Shift IDENT NAMESPACE_SYM IDENT
Reduce to ident by:
ident : IDENT
NAMESPACE_SYM ident
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 55
SShift and go to state 155
URIShift and go to state 56
OtherError
+ +

+
+ +

State 59

+ +

+ +
ident:IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift NAMESPACE_SYM NAMESPACE_SYM
Shift IDENT NAMESPACE_SYM IDENT
+

+ +

+ + From here, we reduce by ident : IDENT regardless of what token + comes next.
+ + (This can take us to 58 or 172) + + +

+
+ +

State 60

+ +

+ +
body:ruleset body .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
Reduce to selectors by:
selectors : selector
selectors
Shift LBRACE selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_selector
Shift RBRACE start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
ruleset
Shift IDENT ruleset IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ruleset ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
ruleset element_name
Reduce to simple_selector by:
simple_selector : element_name
ruleset simple_selector
Reduce to selector by:
selector : simple_selector
ruleset selector
Reduce to selectors by:
selectors : selector
ruleset selectors
Shift LBRACE ruleset selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
ruleset start_selector
Shift RBRACE ruleset start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
ruleset ruleset
Reduce to body by:
body : ruleset
ruleset body
+

+ +

+ + From here, we reduce by body : ruleset body regardless of what token + comes next.
+ + (This can take us to 8, 60, 61, 62, 63, 65, 76 or 86) + + +

+
+ +

State 61

+ +

+ +
body:conditional_rule body .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift LBRACE MEDIA_SYM media_query_list LBRACE
Reduce to start_media by:
start_media : MEDIA_SYM media_query_list LBRACE
start_media
Reduce to optional_space by:
optional_space :
start_media optional_space
Reduce to empty_ruleset by:
empty_ruleset : optional_space
start_media empty_ruleset
Reduce to body_in_media by:
body_in_media : empty_ruleset
start_media body_in_media
Shift RBRACE start_media body_in_media RBRACE
Reduce to media by:
media : start_media body_in_media RBRACE
media
Reduce to conditional_rule by:
conditional_rule : media
conditional_rule
Shift IDENT conditional_rule IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
conditional_rule ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
conditional_rule element_name
Reduce to simple_selector by:
simple_selector : element_name
conditional_rule simple_selector
Reduce to selector by:
selector : simple_selector
conditional_rule selector
Reduce to selectors by:
selectors : selector
conditional_rule selectors
Shift LBRACE conditional_rule selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
conditional_rule start_selector
Shift RBRACE conditional_rule start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
conditional_rule ruleset
Reduce to body by:
body : ruleset
conditional_rule body
+

+ +

+ + From here, we reduce by body : conditional_rule body regardless of what token + comes next.
+ + (This can take us to 8, 60, 61, 62, 63, 65, 76 or 86) + + +

+
+ +

State 62

+ +

+ +
body:keyframes_rule body .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Shift RBRACE start_keyframes_rule RBRACE
Reduce to keyframes_rule by:
keyframes_rule : start_keyframes_rule RBRACE
keyframes_rule
Shift IDENT keyframes_rule IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
keyframes_rule ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
keyframes_rule element_name
Reduce to simple_selector by:
simple_selector : element_name
keyframes_rule simple_selector
Reduce to selector by:
selector : simple_selector
keyframes_rule selector
Reduce to selectors by:
selectors : selector
keyframes_rule selectors
Shift LBRACE keyframes_rule selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
keyframes_rule start_selector
Shift RBRACE keyframes_rule start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
keyframes_rule ruleset
Reduce to body by:
body : ruleset
keyframes_rule body
+

+ +

+ + From here, we reduce by body : keyframes_rule body regardless of what token + comes next.
+ + (This can take us to 8, 60, 61, 62, 63, 65, 76 or 86) + + +

+
+ +

State 63

+ +

+ +
body:fontface_rule body .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift RBRACE start_fontface_rule RBRACE
Reduce to fontface_rule by:
fontface_rule : start_fontface_rule RBRACE
fontface_rule
Shift IDENT fontface_rule IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
fontface_rule ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
fontface_rule element_name
Reduce to simple_selector by:
simple_selector : element_name
fontface_rule simple_selector
Reduce to selector by:
selector : simple_selector
fontface_rule selector
Reduce to selectors by:
selectors : selector
fontface_rule selectors
Shift LBRACE fontface_rule selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
fontface_rule start_selector
Shift RBRACE fontface_rule start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
fontface_rule ruleset
Reduce to body by:
body : ruleset
fontface_rule body
+

+ +

+ + From here, we reduce by body : fontface_rule body regardless of what token + comes next.
+ + (This can take us to 8, 60, 61, 62, 63, 65, 76 or 86) + + +

+
+ +

State 64

+ +

+ +
optional_space:S .
start_selector:S . start_selector

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift LBRACE MEDIA_SYM media_query_list LBRACE
Reduce to start_media by:
start_media : MEDIA_SYM media_query_list LBRACE
start_media
Shift S start_media S
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
SShift and go to state 31
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"|"Shift and go to state 38
"."Shift and go to state 46
OtherReduce by optional_space : S
(This takes us to 68)
+ +

+
+ +

State 65

+ +

+ +
body_in_media:body .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift LBRACE MEDIA_SYM media_query_list LBRACE
Reduce to start_media by:
start_media : MEDIA_SYM media_query_list LBRACE
start_media
Shift IDENT start_media IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
start_media ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
start_media element_name
Reduce to simple_selector by:
simple_selector : element_name
start_media simple_selector
Reduce to selector by:
selector : simple_selector
start_media selector
Reduce to selectors by:
selectors : selector
start_media selectors
Shift LBRACE start_media selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_media start_selector
Shift RBRACE start_media start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
start_media ruleset
Reduce to body by:
body : ruleset
start_media body
+

+ +

+ + From here, we reduce by body_in_media : body regardless of what token + comes next.
+ + (This takes us to 67) + + +

+
+ +

State 66

+ +

+ +
body_in_media:empty_ruleset .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift LBRACE MEDIA_SYM media_query_list LBRACE
Reduce to start_media by:
start_media : MEDIA_SYM media_query_list LBRACE
start_media
Reduce to optional_space by:
optional_space :
start_media optional_space
Reduce to empty_ruleset by:
empty_ruleset : optional_space
start_media empty_ruleset
+

+ +

+ + From here, we reduce by body_in_media : empty_ruleset regardless of what token + comes next.
+ + (This takes us to 67) + + +

+
+ +

State 67

+ +

+ +
media:start_media body_in_media . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift LBRACE MEDIA_SYM media_query_list LBRACE
Reduce to start_media by:
start_media : MEDIA_SYM media_query_list LBRACE
start_media
Reduce to optional_space by:
optional_space :
start_media optional_space
Reduce to empty_ruleset by:
empty_ruleset : optional_space
start_media empty_ruleset
Reduce to body_in_media by:
body_in_media : empty_ruleset
start_media body_in_media
+

+ +

+ + Action table:
+
Lookahead tokenAction
RBRACEShift and go to state 156
OtherError
+ +

+
+ +

State 68

+ +

+ +
empty_ruleset:optional_space .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift LBRACE MEDIA_SYM media_query_list LBRACE
Reduce to start_media by:
start_media : MEDIA_SYM media_query_list LBRACE
start_media
Reduce to optional_space by:
optional_space :
start_media optional_space
+

+ +

+ + From here, we reduce by empty_ruleset : optional_space regardless of what token + comes next.
+ + (This takes us to 66) + + +

+
+ +

State 69

+ +

+ +
media_query_list:media_query .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to optional_only_or_not by:
optional_only_or_not :
MEDIA_SYM optional_only_or_not
Shift IDENT MEDIA_SYM optional_only_or_not IDENT
Reduce to media_type by:
media_type : IDENT
MEDIA_SYM optional_only_or_not media_type
Reduce to optional_and_exprs by:
optional_and_exprs :
MEDIA_SYM optional_only_or_not media_type optional_and_exprs
Reduce to media_query by:
media_query : optional_only_or_not media_type optional_and_exprs
MEDIA_SYM media_query
+

+ +

+ + From here, we reduce by media_query_list : media_query regardless of what token + comes next.
+ + (This takes us to 70) + + +

+
+ +

State 70

+ +

+ +
media_query_list:media_query_list . COMMA media_query
start_media:MEDIA_SYM media_query_list . LBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
+

+ +

+ + Action table:
+
Lookahead tokenAction
COMMAShift and go to state 157
LBRACEShift and go to state 158
OtherError
+ +

+
+ +

State 71

+ +

+ +
media_query:optional_only_or_not . media_type optional_and_exprs

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to optional_only_or_not by:
optional_only_or_not :
MEDIA_SYM optional_only_or_not
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 160
OtherError
+ +

+
+ +

State 72

+ +

+ +
media_query:media_expr . optional_and_exprs

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space
Shift IDENT MEDIA_SYM LPAREN optional_space IDENT
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space IDENT optional_space
Shift RPAREN MEDIA_SYM LPAREN optional_space IDENT optional_space RPAREN
Reduce to media_expr by:
media_expr : LPAREN optional_space IDENT optional_space RPAREN
MEDIA_SYM media_expr
+

+ +

+ + From here, we reduce by optional_and_exprs : regardless of what token + comes next.
+ + (This takes us to 161) + + +

+
+ +

State 73

+ +

+ +
optional_only_or_not:ONLY .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift ONLY MEDIA_SYM ONLY
+

+ +

+ + From here, we reduce by optional_only_or_not : ONLY regardless of what token + comes next.
+ + (This takes us to 71) + + +

+
+ +

State 74

+ +

+ +
optional_only_or_not:NOT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift NOT MEDIA_SYM NOT
+

+ +

+ + From here, we reduce by optional_only_or_not : NOT regardless of what token + comes next.
+ + (This takes us to 71) + + +

+
+ +

State 75

+ +

+ +
media_expr:LPAREN . optional_space IDENT optional_space RPAREN
media_expr:LPAREN . optional_space IDENT optional_space COLON optional_space expr RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 163
OtherReduce by optional_space :
(This takes us to 162)
+ +

+
+ +

State 76

+ +

+ +
document_query:start_document_query body . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
Reduce to url_match_fn by:
url_match_fn : function_no_quote
start_document_query_pos url_match_fn
Reduce to url_match_fns by:
url_match_fns : url_match_fn
start_document_query_pos url_match_fns
Shift LBRACE start_document_query_pos url_match_fns LBRACE
Reduce to start_document_query by:
start_document_query : start_document_query_pos url_match_fns LBRACE
start_document_query
Shift IDENT start_document_query IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
start_document_query ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
start_document_query element_name
Reduce to simple_selector by:
simple_selector : element_name
start_document_query simple_selector
Reduce to selector by:
selector : simple_selector
start_document_query selector
Reduce to selectors by:
selectors : selector
start_document_query selectors
Shift LBRACE start_document_query selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_document_query start_selector
Shift RBRACE start_document_query start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
start_document_query ruleset
Reduce to body by:
body : ruleset
start_document_query body
+

+ +

+ + Action table:
+
Lookahead tokenAction
RBRACEShift and go to state 164
OtherError
+ +

+
+ +

State 77

+ +

+ +
document_query:start_document_query RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
Reduce to url_match_fn by:
url_match_fn : function_no_quote
start_document_query_pos url_match_fn
Reduce to url_match_fns by:
url_match_fns : url_match_fn
start_document_query_pos url_match_fns
Shift LBRACE start_document_query_pos url_match_fns LBRACE
Reduce to start_document_query by:
start_document_query : start_document_query_pos url_match_fns LBRACE
start_document_query
Shift RBRACE start_document_query RBRACE
+

+ +

+ + From here, we reduce by document_query : start_document_query RBRACE regardless of what token + comes next.
+ + (This takes us to 17) + + +

+
+ +

State 78

+ +

+ +
start_document_query:start_document_query_pos url_match_fns . LBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
Reduce to url_match_fn by:
url_match_fn : function_no_quote
start_document_query_pos url_match_fn
Reduce to url_match_fns by:
url_match_fns : url_match_fn
start_document_query_pos url_match_fns
+

+ +

+ + Action table:
+
Lookahead tokenAction
LBRACEShift and go to state 165
OtherError
+ +

+
+ +

State 79

+ +

+ +
url_match_fns:url_match_fn . COMMA url_match_fns
url_match_fns:url_match_fn .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
Reduce to url_match_fn by:
url_match_fn : function_no_quote
start_document_query_pos url_match_fn
+

+ +

+ + Action table:
+
Lookahead tokenAction
COMMAShift and go to state 166
OtherReduce by url_match_fns : url_match_fn
(This can take us to 78 or 257)
+ +

+
+ +

State 80

+ +

+ +
url_match_fn:function_no_quote .
function_no_quote:function_no_quote . S

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 167
OtherReduce by url_match_fn : function_no_quote
(This takes us to 79)
+ +

+
+ +

State 81

+ +

+ +
url_match_fn:function .
function:function . S

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift RPAREN start_document_query_pos FUNCTION RPAREN
Reduce to function by:
function : FUNCTION RPAREN
start_document_query_pos function
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 168
OtherReduce by url_match_fn : function
(This takes us to 79)
+ +

+
+ +

State 82

+ +

+ +
url_match_fn:uri .
uri:uri . S

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift URI start_document_query_pos URI
Reduce to uri by:
uri : URI
start_document_query_pos uri
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 169
OtherReduce by url_match_fn : uri
(This takes us to 79)
+ +

+
+ +

State 83

+ +

+ +
function:FUNCTION . expr RPAREN
function:FUNCTION . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 188
IDENTShift and go to state 59
HASHShift and go to state 187
RPARENShift and go to state 184
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
URIShift and go to state 85
RESOLUTIONShift and go to state 170
VARIABLE_NAMEShift and go to state 181
CALC_SYMShift and go to state 186
UNICODE_RANGEShift and go to state 185
RATIOShift and go to state 196
OtherError
+ +

+
+ +

State 84

+ +

+ +
function_no_quote:FUNCTION_NO_QUOTE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
+

+ +

+ + From here, we reduce by function_no_quote : FUNCTION_NO_QUOTE regardless of what token + comes next.
+ + (This takes us to 80) + + +

+
+ +

State 85

+ +

+ +
uri:URI .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift URI start_document_query_pos URI
+

+ +

+ + From here, we reduce by uri : URI regardless of what token + comes next.
+ + (This can take us to 82 or 176) + + +

+
+ +

State 86

+ +

+ +
supports:start_supports body . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Reduce to supports_condition_root by:
supports_condition_root : supports_condition_in_parens
SUPPORTS_SYM supports_condition_root
Shift LBRACE SUPPORTS_SYM supports_condition_root LBRACE
Reduce to start_supports by:
start_supports : SUPPORTS_SYM supports_condition_root LBRACE
start_supports
Shift IDENT start_supports IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
start_supports ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
start_supports element_name
Reduce to simple_selector by:
simple_selector : element_name
start_supports simple_selector
Reduce to selector by:
selector : simple_selector
start_supports selector
Reduce to selectors by:
selectors : selector
start_supports selectors
Shift LBRACE start_supports selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_supports start_selector
Shift RBRACE start_supports start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
start_supports ruleset
Reduce to body by:
body : ruleset
start_supports body
+

+ +

+ + Action table:
+
Lookahead tokenAction
RBRACEShift and go to state 199
OtherError
+ +

+
+ +

State 87

+ +

+ +
supports:start_supports RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Reduce to supports_condition_root by:
supports_condition_root : supports_condition_in_parens
SUPPORTS_SYM supports_condition_root
Shift LBRACE SUPPORTS_SYM supports_condition_root LBRACE
Reduce to start_supports by:
start_supports : SUPPORTS_SYM supports_condition_root LBRACE
start_supports
Shift RBRACE start_supports RBRACE
+

+ +

+ + From here, we reduce by supports : start_supports RBRACE regardless of what token + comes next.
+ + (This takes us to 18) + + +

+
+ +

State 88

+ +

+ +
start_supports:SUPPORTS_SYM supports_condition_root . LBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Reduce to supports_condition_root by:
supports_condition_root : supports_condition_in_parens
SUPPORTS_SYM supports_condition_root
+

+ +

+ + Action table:
+
Lookahead tokenAction
LBRACEShift and go to state 200
OtherError
+ +

+
+ +

State 89

+ +

+ +
supports_condition_root:supports_negation .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift NOT SUPPORTS_SYM NOT
Shift LPAREN SUPPORTS_SYM NOT LPAREN
Shift IDENT SUPPORTS_SYM NOT LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM NOT LPAREN property
Shift COLON SUPPORTS_SYM NOT LPAREN property COLON
Shift IDENT SUPPORTS_SYM NOT LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM NOT LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM NOT LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM NOT LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM NOT LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM NOT LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM NOT LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM NOT supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM NOT supports_condition_in_parens
Reduce to supports_negation by:
supports_negation : NOT supports_condition_in_parens
SUPPORTS_SYM supports_negation
+

+ +

+ + From here, we reduce by supports_condition_root : supports_negation regardless of what token + comes next.
+ + (This takes us to 88) + + +

+
+ +

State 90

+ +

+ +
supports_condition_root:supports_conjunction_or_disjunction .
supports_conjunction:supports_conjunction_or_disjunction . AND supports_condition_in_parens
supports_disjunction:supports_conjunction_or_disjunction . OR supports_condition_in_parens

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Shift AND SUPPORTS_SYM supports_condition_in_parens AND
Shift LPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property
Shift COLON SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_condition_in_parens AND supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens AND supports_condition_in_parens
Reduce to supports_conjunction by:
supports_conjunction : supports_condition_in_parens AND supports_condition_in_parens
SUPPORTS_SYM supports_conjunction
Reduce to supports_conjunction_or_disjunction by:
supports_conjunction_or_disjunction : supports_conjunction
SUPPORTS_SYM supports_conjunction_or_disjunction
+

+ +

+ + Action table:
+
Lookahead tokenAction
ANDShift and go to state 201
ORShift and go to state 202
OtherReduce by supports_condition_root : supports_conjunction_or_disjunction
(This takes us to 88)
+ +

+
+ +

State 91

+ +

+ +
supports_condition_root:supports_condition_in_parens .
supports_conjunction:supports_condition_in_parens . AND supports_condition_in_parens
supports_disjunction:supports_condition_in_parens . OR supports_condition_in_parens

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
+

+ +

+ + Action table:
+
Lookahead tokenAction
ANDShift and go to state 203
ORShift and go to state 204
OtherReduce by supports_condition_root : supports_condition_in_parens
(This takes us to 88)
+ +

+
+ +

State 92

+ +

+ +
supports_condition_in_parens:LPAREN . supports_condition RPAREN
supports_declaration_condition:LPAREN . declaration_internal RPAREN
supports_declaration_condition:LPAREN . S declaration_internal RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 113
SShift and go to state 210
STARShift and go to state 114
LPARENShift and go to state 92
NOTShift and go to state 94
VARIABLE_NAMEShift and go to state 115
OtherError
+ +

+
+ +

State 93

+ +

+ +
supports_condition_in_parens:supports_declaration_condition .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
+

+ +

+ + From here, we reduce by supports_condition_in_parens : supports_declaration_condition regardless of what token + comes next.
+ + (This can take us to 91, 207, 211, 274, 275, 276 or 277) + + +

+
+ +

State 94

+ +

+ +
supports_negation:NOT . supports_condition_in_parens

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift NOT SUPPORTS_SYM NOT
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 92
OtherError
+ +

+
+ +

State 95

+ +

+ +
supports_conjunction_or_disjunction:supports_conjunction .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Shift AND SUPPORTS_SYM supports_condition_in_parens AND
Shift LPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property
Shift COLON SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_condition_in_parens AND supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens AND supports_condition_in_parens
Reduce to supports_conjunction by:
supports_conjunction : supports_condition_in_parens AND supports_condition_in_parens
SUPPORTS_SYM supports_conjunction
+

+ +

+ + From here, we reduce by supports_conjunction_or_disjunction : supports_conjunction regardless of what token + comes next.
+ + (This can take us to 90 or 206) + + +

+
+ +

State 96

+ +

+ +
supports_conjunction_or_disjunction:supports_disjunction .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Shift OR SUPPORTS_SYM supports_condition_in_parens OR
Shift LPAREN SUPPORTS_SYM supports_condition_in_parens OR LPAREN
Shift IDENT SUPPORTS_SYM supports_condition_in_parens OR LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM supports_condition_in_parens OR LPAREN property
Shift COLON SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON
Shift IDENT SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM supports_condition_in_parens OR LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM supports_condition_in_parens OR LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_condition_in_parens OR supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens OR supports_condition_in_parens
Reduce to supports_disjunction by:
supports_disjunction : supports_condition_in_parens OR supports_condition_in_parens
SUPPORTS_SYM supports_disjunction
+

+ +

+ + From here, we reduce by supports_conjunction_or_disjunction : supports_disjunction regardless of what token + comes next.
+ + (This can take us to 90 or 206) + + +

+
+ +

State 97

+ +

+ +
keyframes_rule:start_keyframes_rule keyframes_blocks . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_selectors
Shift LBRACE start_keyframes_rule keyframes_selectors LBRACE
Reduce to start_keyframes_block by:
start_keyframes_block : keyframes_selectors LBRACE
start_keyframes_rule start_keyframes_block
Shift RBRACE start_keyframes_rule start_keyframes_block RBRACE
Reduce to keyframes_block by:
keyframes_block : start_keyframes_block RBRACE
start_keyframes_rule keyframes_block
Reduce to keyframes_blocks by:
keyframes_blocks : keyframes_block
start_keyframes_rule keyframes_blocks
+

+ +

+ + Action table:
+
Lookahead tokenAction
RBRACEShift and go to state 212
OtherError
+ +

+
+ +

State 98

+ +

+ +
keyframes_rule:start_keyframes_rule RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Shift RBRACE start_keyframes_rule RBRACE
+

+ +

+ + From here, we reduce by keyframes_rule : start_keyframes_rule RBRACE regardless of what token + comes next.
+ + (This takes us to 14) + + +

+
+ +

State 99

+ +

+ +
keyframes_blocks:keyframes_block . keyframes_blocks
keyframes_blocks:keyframes_block .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_selectors
Shift LBRACE start_keyframes_rule keyframes_selectors LBRACE
Reduce to start_keyframes_block by:
start_keyframes_block : keyframes_selectors LBRACE
start_keyframes_rule start_keyframes_block
Shift RBRACE start_keyframes_rule start_keyframes_block RBRACE
Reduce to keyframes_block by:
keyframes_block : start_keyframes_block RBRACE
start_keyframes_rule keyframes_block
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 103
LBRACEReduce by keyframes_selectors :
(This takes us to 101)
PERCENTAGEShift and go to state 104
OtherReduce by keyframes_blocks : keyframes_block
(This can take us to 97 or 213)
+ +

+
+ +

State 100

+ +

+ +
keyframes_block:start_keyframes_block . declarations RBRACE
keyframes_block:start_keyframes_block . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_selectors
Shift LBRACE start_keyframes_rule keyframes_selectors LBRACE
Reduce to start_keyframes_block by:
start_keyframes_block : keyframes_selectors LBRACE
start_keyframes_rule start_keyframes_block
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 108
IDENTShift and go to state 113
RBRACEShift and go to state 215
STARShift and go to state 114
VARIABLE_NAMEShift and go to state 115
OtherError
+ +

+
+ +

State 101

+ +

+ +
start_keyframes_block:keyframes_selectors . LBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_selectors
+

+ +

+ + Action table:
+
Lookahead tokenAction
LBRACEShift and go to state 216
OtherError
+ +

+
+ +

State 102

+ +

+ +
keyframes_selectors:keyframes_selector . COMMA keyframes_selectors
keyframes_selectors:keyframes_selector .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Shift IDENT start_keyframes_rule IDENT
Reduce to keyframes_selector by:
keyframes_selector : IDENT
start_keyframes_rule keyframes_selector
+

+ +

+ + Action table:
+
Lookahead tokenAction
COMMAShift and go to state 217
OtherReduce by keyframes_selectors : keyframes_selector
(This can take us to 101 or 282)
+ +

+
+ +

State 103

+ +

+ +
keyframes_selector:IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Shift IDENT start_keyframes_rule IDENT
+

+ +

+ + From here, we reduce by keyframes_selector : IDENT regardless of what token + comes next.
+ + (This takes us to 102) + + +

+
+ +

State 104

+ +

+ +
keyframes_selector:PERCENTAGE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Shift PERCENTAGE start_keyframes_rule PERCENTAGE
+

+ +

+ + From here, we reduce by keyframes_selector : PERCENTAGE regardless of what token + comes next.
+ + (This takes us to 102) + + +

+
+ +

State 105

+ +

+ +
start_keyframes_rule:KEYFRAMES_SYM IDENT . LBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
LBRACEShift and go to state 218
OtherError
+ +

+
+ +

State 106

+ +

+ +
fontface_rule:start_fontface_rule declarations . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift SEMI start_fontface_rule SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_fontface_rule one_or_more_semis
Reduce to declarations by:
declarations : one_or_more_semis
start_fontface_rule declarations
+

+ +

+ + Action table:
+
Lookahead tokenAction
RBRACEShift and go to state 219
OtherError
+ +

+
+ +

State 107

+ +

+ +
fontface_rule:start_fontface_rule RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift RBRACE start_fontface_rule RBRACE
+

+ +

+ + From here, we reduce by fontface_rule : start_fontface_rule RBRACE regardless of what token + comes next.
+ + (This takes us to 15) + + +

+
+ +

State 108

+ +

+ +
one_or_more_semis:SEMI .
one_or_more_semis:SEMI . one_or_more_semis

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift SEMI start_fontface_rule SEMI
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 108
(Overridden: reduce by one_or_more_semis : SEMI)
OtherReduce by one_or_more_semis : SEMI
(This can take us to 110, 220 or 221)
+ +

+
+ +

State 109

+ +

+ +
declarations:declaration . one_or_more_semis declarations
declarations:declaration . one_or_more_semis
declarations:declaration .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift IDENT start_fontface_rule IDENT
Reduce to property by:
property : IDENT
start_fontface_rule property
Shift COLON start_fontface_rule property COLON
Shift IDENT start_fontface_rule property COLON IDENT
Reduce to ident by:
ident : IDENT
start_fontface_rule property COLON ident
Reduce to term by:
term : ident
start_fontface_rule property COLON term
Reduce to expr by:
expr : term
start_fontface_rule property COLON expr
Reduce to prio by:
prio :
start_fontface_rule property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
start_fontface_rule declaration_internal
Reduce to declaration by:
declaration : declaration_internal
start_fontface_rule declaration
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 108
OtherReduce by declarations : declaration
(This can take us to 106, 117, 214, 222 or 283)
+ +

+
+ +

State 110

+ +

+ +
declarations:one_or_more_semis . declarations
declarations:one_or_more_semis .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift SEMI start_fontface_rule SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_fontface_rule one_or_more_semis
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 108
IDENTShift and go to state 113
STARShift and go to state 114
VARIABLE_NAMEShift and go to state 115
OtherReduce by declarations : one_or_more_semis
(This can take us to 106, 117, 214, 222 or 283)
+ +

+
+ +

State 111

+ +

+ +
declaration:declaration_internal .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift IDENT start_fontface_rule IDENT
Reduce to property by:
property : IDENT
start_fontface_rule property
Shift COLON start_fontface_rule property COLON
Shift IDENT start_fontface_rule property COLON IDENT
Reduce to ident by:
ident : IDENT
start_fontface_rule property COLON ident
Reduce to term by:
term : ident
start_fontface_rule property COLON term
Reduce to expr by:
expr : term
start_fontface_rule property COLON expr
Reduce to prio by:
prio :
start_fontface_rule property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
start_fontface_rule declaration_internal
+

+ +

+ + From here, we reduce by declaration : declaration_internal regardless of what token + comes next.
+ + (This takes us to 109) + + +

+
+ +

State 112

+ +

+ +
declaration_internal:property . COLON expr prio
declaration_internal:property . COLON S expr prio
declaration_internal:property . S COLON expr prio
declaration_internal:property . S COLON S expr prio

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 224
COLONShift and go to state 223
OtherError
+ +

+
+ +

State 113

+ +

+ +
property:IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
+

+ +

+ + From here, we reduce by property : IDENT regardless of what token + comes next.
+ + (This takes us to 112) + + +

+
+ +

State 114

+ +

+ +
property:STAR . IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift STAR SUPPORTS_SYM LPAREN STAR
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 225
OtherError
+ +

+
+ +

State 115

+ +

+ +
property:VARIABLE_NAME .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift VARIABLE_NAME SUPPORTS_SYM LPAREN VARIABLE_NAME
+

+ +

+ + From here, we reduce by property : VARIABLE_NAME regardless of what token + comes next.
+ + (This takes us to 112) + + +

+
+ +

State 116

+ +

+ +
start_fontface_rule:FONTFACE_SYM LBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
+

+ +

+ + From here, we reduce by start_fontface_rule : FONTFACE_SYM LBRACE regardless of what token + comes next.
+ + (This takes us to 28) + + +

+
+ +

State 117

+ +

+ +
ruleset:start_selector declarations . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
Reduce to selectors by:
selectors : selector
selectors
Shift LBRACE selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_selector
Shift SEMI start_selector SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_selector one_or_more_semis
Reduce to declarations by:
declarations : one_or_more_semis
start_selector declarations
+

+ +

+ + Action table:
+
Lookahead tokenAction
RBRACEShift and go to state 226
OtherError
+ +

+
+ +

State 118

+ +

+ +
ruleset:start_selector RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
Reduce to selectors by:
selectors : selector
selectors
Shift LBRACE selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_selector
Shift RBRACE start_selector RBRACE
+

+ +

+ + From here, we reduce by ruleset : start_selector RBRACE regardless of what token + comes next.
+ + (This takes us to 12) + + +

+
+ +

State 119

+ +

+ +
start_selector:S start_selector .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift S S
Shift IDENT S IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
S ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
S element_name
Reduce to simple_selector by:
simple_selector : element_name
S simple_selector
Reduce to selector by:
selector : simple_selector
S selector
Reduce to selectors by:
selectors : selector
S selectors
Shift LBRACE S selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
S start_selector
+

+ +

+ + From here, we reduce by start_selector : S start_selector regardless of what token + comes next.
+ + (This can take us to 30 or 119) + + +

+
+ +

State 120

+ +

+ +
start_selector:selectors LBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
Reduce to selectors by:
selectors : selector
selectors
Shift LBRACE selectors LBRACE
+

+ +

+ + From here, we reduce by start_selector : selectors LBRACE regardless of what token + comes next.
+ + (This can take us to 30 or 119) + + +

+
+ +

State 121

+ +

+ +
selectors:selector COMMA . selectors

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
Shift COMMA selector COMMA
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"|"Shift and go to state 38
"."Shift and go to state 46
OtherError
+ +

+
+ +

State 122

+ +

+ +
selector:simple_selector combinator . selector

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Shift S simple_selector S
Reduce to combinator by:
combinator : S
simple_selector combinator
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"|"Shift and go to state 38
"."Shift and go to state 46
OtherError
+ +

+
+ +

State 123

+ +

+ +
combinator:S .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Shift S simple_selector S
+

+ +

+ + From here, we reduce by combinator : S regardless of what token + comes next.
+ + (This takes us to 122) + + +

+
+ +

State 124

+ +

+ +
combinator:GREATER .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Shift GREATER simple_selector GREATER
+

+ +

+ + From here, we reduce by combinator : GREATER regardless of what token + comes next.
+ + (This takes us to 122) + + +

+
+ +

State 125

+ +

+ +
combinator:PLUS .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Shift PLUS simple_selector PLUS
+

+ +

+ + From here, we reduce by combinator : PLUS regardless of what token + comes next.
+ + (This takes us to 122) + + +

+
+ +

State 126

+ +

+ +
combinator:TILDE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Shift TILDE simple_selector TILDE
+

+ +

+ + From here, we reduce by combinator : TILDE regardless of what token + comes next.
+ + (This takes us to 122) + + +

+
+ +

State 127

+ +

+ +
simple_selector:element_name hcap .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Shift HASH element_name HASH
Reduce to hash by:
hash : HASH
element_name hash
Reduce to hcap by:
hcap : hash
element_name hcap
+

+ +

+ + From here, we reduce by simple_selector : element_name hcap regardless of what token + comes next.
+ + (This can take us to 34, 246 or 247) + + +

+
+ +

State 128

+ +

+ +
ident_with_namespace:IDENT "|" . IDENT
element_name:IDENT "|" . STAR

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Shift "|" IDENT "|"
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 229
STARShift and go to state 230
OtherError
+ +

+
+ +

State 129

+ +

+ +
ident_with_namespace:"|" IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift "|" "|"
Shift IDENT "|" IDENT
+

+ +

+ + From here, we reduce by ident_with_namespace : "|" IDENT regardless of what token + comes next.
+ + (This can take us to 40 or 140) + + +

+
+ +

State 130

+ +

+ +
element_name:"|" STAR .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift "|" "|"
Shift STAR "|" STAR
+

+ +

+ + From here, we reduce by element_name : "|" STAR regardless of what token + comes next.
+ + (This takes us to 35) + + +

+
+ +

State 131

+ +

+ +
ident_with_namespace:STAR "|" . IDENT
element_name:STAR "|" . STAR

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift STAR STAR
Shift "|" STAR "|"
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 231
STARShift and go to state 232
OtherError
+ +

+
+ +

State 132

+ +

+ +
hcap:hash hcap .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift HASH HASH
Reduce to hash by:
hash : HASH
hash
Shift HASH hash HASH
Reduce to hash by:
hash : HASH
hash hash
Reduce to hcap by:
hcap : hash
hash hcap
+

+ +

+ + From here, we reduce by hcap : hash hcap regardless of what token + comes next.
+ + (This can take us to 36, 127, 132, 133, 134 or 135) + + +

+
+ +

State 133

+ +

+ +
hcap:class hcap .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift "." "."
Shift IDENT "." IDENT
Reduce to class by:
class : "." IDENT
class
Shift HASH class HASH
Reduce to hash by:
hash : HASH
class hash
Reduce to hcap by:
hcap : hash
class hcap
+

+ +

+ + From here, we reduce by hcap : class hcap regardless of what token + comes next.
+ + (This can take us to 36, 127, 132, 133, 134 or 135) + + +

+
+ +

State 134

+ +

+ +
hcap:attrib hcap .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift RSQUARE LSQUARE ident_with_namespace RSQUARE
Reduce to attrib by:
attrib : LSQUARE ident_with_namespace RSQUARE
attrib
Shift HASH attrib HASH
Reduce to hash by:
hash : HASH
attrib hash
Reduce to hcap by:
hcap : hash
attrib hcap
+

+ +

+ + From here, we reduce by hcap : attrib hcap regardless of what token + comes next.
+ + (This can take us to 36, 127, 132, 133, 134 or 135) + + +

+
+ +

State 135

+ +

+ +
hcap:pseudo hcap .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift IDENT COLON IDENT
Reduce to pseudo by:
pseudo : COLON IDENT
pseudo
Shift HASH pseudo HASH
Reduce to hash by:
hash : HASH
pseudo hash
Reduce to hcap by:
hcap : hash
pseudo hcap
+

+ +

+ + From here, we reduce by hcap : pseudo hcap regardless of what token + comes next.
+ + (This can take us to 36, 127, 132, 133, 134 or 135) + + +

+
+ +

State 136

+ +

+ +
class:"." IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift "." "."
Shift IDENT "." IDENT
+

+ +

+ + From here, we reduce by class : "." IDENT regardless of what token + comes next.
+ + (This takes us to 42) + + +

+
+ +

State 137

+ +

+ +
ident_with_namespace:IDENT .
ident_with_namespace:IDENT . "|" IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
"|"Shift and go to state 233
OtherReduce by ident_with_namespace : IDENT
(This takes us to 140)
+ +

+
+ +

State 138

+ +

+ +
ident_with_namespace:"|" . IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift "|" LSQUARE "|"
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 129
OtherError
+ +

+
+ +

State 139

+ +

+ +
ident_with_namespace:STAR . "|" IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift STAR LSQUARE STAR
+

+ +

+ + Action table:
+
Lookahead tokenAction
"|"Shift and go to state 234
OtherError
+ +

+
+ +

State 140

+ +

+ +
attrib:LSQUARE ident_with_namespace . EQUAL IDENT RSQUARE
attrib:LSQUARE ident_with_namespace . EQUAL STRING RSQUARE
attrib:LSQUARE ident_with_namespace . INCLUDES STRING RSQUARE
attrib:LSQUARE ident_with_namespace . INCLUDES IDENT RSQUARE
attrib:LSQUARE ident_with_namespace . DASHMATCH IDENT RSQUARE
attrib:LSQUARE ident_with_namespace . DASHMATCH STRING RSQUARE
attrib:LSQUARE ident_with_namespace . PREFIXMATCH IDENT RSQUARE
attrib:LSQUARE ident_with_namespace . PREFIXMATCH STRING RSQUARE
attrib:LSQUARE ident_with_namespace . SUFFIXMATCH IDENT RSQUARE
attrib:LSQUARE ident_with_namespace . SUFFIXMATCH STRING RSQUARE
attrib:LSQUARE ident_with_namespace . SUBSTRINGMATCH IDENT RSQUARE
attrib:LSQUARE ident_with_namespace . SUBSTRINGMATCH STRING RSQUARE
attrib:LSQUARE ident_with_namespace . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 241
EQUALShift and go to state 235
INCLUDESShift and go to state 236
DASHMATCHShift and go to state 237
PREFIXMATCHShift and go to state 238
SUFFIXMATCHShift and go to state 239
SUBSTRINGMATCHShift and go to state 240
OtherError
+ +

+
+ +

State 141

+ +

+ +
pseudo:COLON IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift IDENT COLON IDENT
+

+ +

+ + From here, we reduce by pseudo : COLON IDENT regardless of what token + comes next.
+ + (This takes us to 44) + + +

+
+ +

State 142

+ +

+ +
pseudo:COLON COLON . IDENT
pseudo:COLON COLON . MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift COLON COLON COLON
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 242
MOZ_PSEUDO_ELEMENTShift and go to state 243
OtherError
+ +

+
+ +

State 143

+ +

+ +
pseudo:COLON FUNCTION . RPAREN
pseudo:COLON FUNCTION . IDENT RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift FUNCTION COLON FUNCTION
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 245
RPARENShift and go to state 244
OtherError
+ +

+
+ +

State 144

+ +

+ +
pseudo:COLON NOT_PSEUDO_CLASS . simple_selector RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift NOT_PSEUDO_CLASS COLON NOT_PSEUDO_CLASS
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"|"Shift and go to state 38
"."Shift and go to state 46
OtherError
+ +

+
+ +

State 145

+ +

+ +
pseudo:COLON NTH_PSEUDO_CLASS .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift NTH_PSEUDO_CLASS COLON NTH_PSEUDO_CLASS
+

+ +

+ + From here, we reduce by pseudo : COLON NTH_PSEUDO_CLASS regardless of what token + comes next.
+ + (This takes us to 44) + + +

+
+ +

State 146

+ +

+ +
pseudo:COLON MATCHES_PSEUDO_CLASS . simple_selectors RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MATCHES_PSEUDO_CLASS COLON MATCHES_PSEUDO_CLASS
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"|"Shift and go to state 38
"."Shift and go to state 46
OtherError
+ +

+
+ +

State 147

+ +

+ +
pseudo:COLON MOZ_PSEUDO_ELEMENT . optional_space any_number_of_idents optional_space RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON MOZ_PSEUDO_ELEMENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 163
(Overridden: reduce by optional_space :)
OtherReduce by optional_space :
(This takes us to 249)
+ +

+
+ +

State 148

+ +

+ +
charset:CHARSET_SYM STRING SEMI .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift CHARSET_SYM CHARSET_SYM
Shift STRING CHARSET_SYM STRING
Shift SEMI CHARSET_SYM STRING SEMI
+

+ +

+ + From here, we reduce by charset : CHARSET_SYM STRING SEMI regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 149

+ +

+ +
import:IMPORT_SYM import_location medium . SEMI
medium:medium . COMMA IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift STRING IMPORT_SYM STRING
Reduce to import_location by:
import_location : STRING
IMPORT_SYM import_location
Shift IDENT IMPORT_SYM import_location IDENT
Reduce to medium by:
medium : IDENT
IMPORT_SYM import_location medium
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 250
COMMAShift and go to state 251
OtherError
+ +

+
+ +

State 150

+ +

+ +
import:IMPORT_SYM import_location SEMI .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift STRING IMPORT_SYM STRING
Reduce to import_location by:
import_location : STRING
IMPORT_SYM import_location
Shift SEMI IMPORT_SYM import_location SEMI
+

+ +

+ + From here, we reduce by import : IMPORT_SYM import_location SEMI regardless of what token + comes next.
+ + (This takes us to 6) + + +

+
+ +

State 151

+ +

+ +
import_location:import_location S .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift STRING IMPORT_SYM STRING
Reduce to import_location by:
import_location : STRING
IMPORT_SYM import_location
Shift S IMPORT_SYM import_location S
+

+ +

+ + From here, we reduce by import_location : import_location S regardless of what token + comes next.
+ + (This can take us to 54, 57 or 154) + + +

+
+ +

State 152

+ +

+ +
medium:IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift STRING IMPORT_SYM STRING
Reduce to import_location by:
import_location : STRING
IMPORT_SYM import_location
Shift IDENT IMPORT_SYM import_location IDENT
+

+ +

+ + From here, we reduce by medium : IDENT regardless of what token + comes next.
+ + (This takes us to 149) + + +

+
+ +

State 153

+ +

+ +
namespace:NAMESPACE_SYM import_location SEMI .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift NAMESPACE_SYM NAMESPACE_SYM
Shift STRING NAMESPACE_SYM STRING
Reduce to import_location by:
import_location : STRING
NAMESPACE_SYM import_location
Shift SEMI NAMESPACE_SYM import_location SEMI
+

+ +

+ + From here, we reduce by namespace : NAMESPACE_SYM import_location SEMI regardless of what token + comes next.
+ + (This takes us to 7) + + +

+
+ +

State 154

+ +

+ +
import_location:import_location . S
namespace:NAMESPACE_SYM ident import_location . SEMI

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift NAMESPACE_SYM NAMESPACE_SYM
Shift IDENT NAMESPACE_SYM IDENT
Reduce to ident by:
ident : IDENT
NAMESPACE_SYM ident
Shift STRING NAMESPACE_SYM ident STRING
Reduce to import_location by:
import_location : STRING
NAMESPACE_SYM ident import_location
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 252
SShift and go to state 151
OtherError
+ +

+
+ +

State 155

+ +

+ +
ident:ident S .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift NAMESPACE_SYM NAMESPACE_SYM
Shift IDENT NAMESPACE_SYM IDENT
Reduce to ident by:
ident : IDENT
NAMESPACE_SYM ident
Shift S NAMESPACE_SYM ident S
+

+ +

+ + From here, we reduce by ident : ident S regardless of what token + comes next.
+ + (This can take us to 58 or 172) + + +

+
+ +

State 156

+ +

+ +
media:start_media body_in_media RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift LBRACE MEDIA_SYM media_query_list LBRACE
Reduce to start_media by:
start_media : MEDIA_SYM media_query_list LBRACE
start_media
Reduce to optional_space by:
optional_space :
start_media optional_space
Reduce to empty_ruleset by:
empty_ruleset : optional_space
start_media empty_ruleset
Reduce to body_in_media by:
body_in_media : empty_ruleset
start_media body_in_media
Shift RBRACE start_media body_in_media RBRACE
+

+ +

+ + From here, we reduce by media : start_media body_in_media RBRACE regardless of what token + comes next.
+ + (This takes us to 16) + + +

+
+ +

State 157

+ +

+ +
media_query_list:media_query_list COMMA . media_query

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift COMMA MEDIA_SYM media_query_list COMMA
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 75
NOTShift and go to state 74
ONLYShift and go to state 73
OtherReduce by optional_only_or_not :
(This takes us to 71)
+ +

+
+ +

State 158

+ +

+ +
start_media:MEDIA_SYM media_query_list LBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift LBRACE MEDIA_SYM media_query_list LBRACE
+

+ +

+ + From here, we reduce by start_media : MEDIA_SYM media_query_list LBRACE regardless of what token + comes next.
+ + (This takes us to 19) + + +

+
+ +

State 159

+ +

+ +
media_query:optional_only_or_not media_type . optional_and_exprs

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to optional_only_or_not by:
optional_only_or_not :
MEDIA_SYM optional_only_or_not
Shift IDENT MEDIA_SYM optional_only_or_not IDENT
Reduce to media_type by:
media_type : IDENT
MEDIA_SYM optional_only_or_not media_type
+

+ +

+ + From here, we reduce by optional_and_exprs : regardless of what token + comes next.
+ + (This takes us to 254) + + +

+
+ +

State 160

+ +

+ +
media_type:IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to optional_only_or_not by:
optional_only_or_not :
MEDIA_SYM optional_only_or_not
Shift IDENT MEDIA_SYM optional_only_or_not IDENT
+

+ +

+ + From here, we reduce by media_type : IDENT regardless of what token + comes next.
+ + (This takes us to 159) + + +

+
+ +

State 161

+ +

+ +
media_query:media_expr optional_and_exprs .
optional_and_exprs:optional_and_exprs . AND media_expr

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space
Shift IDENT MEDIA_SYM LPAREN optional_space IDENT
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space IDENT optional_space
Shift RPAREN MEDIA_SYM LPAREN optional_space IDENT optional_space RPAREN
Reduce to media_expr by:
media_expr : LPAREN optional_space IDENT optional_space RPAREN
MEDIA_SYM media_expr
Reduce to optional_and_exprs by:
optional_and_exprs :
MEDIA_SYM media_expr optional_and_exprs
+

+ +

+ + Action table:
+
Lookahead tokenAction
ANDShift and go to state 255
OtherReduce by media_query : media_expr optional_and_exprs
(This can take us to 69 or 253)
+ +

+
+ +

State 162

+ +

+ +
media_expr:LPAREN optional_space . IDENT optional_space RPAREN
media_expr:LPAREN optional_space . IDENT optional_space COLON optional_space expr RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 256
OtherError
+ +

+
+ +

State 163

+ +

+ +
optional_space:S .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
Shift S MEDIA_SYM LPAREN S
+

+ +

+ + From here, we reduce by optional_space : S regardless of what token + comes next.
+ + (This can take us to 162, 249, 299, 309, 315, 337, 341, 350 or 353) + + +

+
+ +

State 164

+ +

+ +
document_query:start_document_query body RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
Reduce to url_match_fn by:
url_match_fn : function_no_quote
start_document_query_pos url_match_fn
Reduce to url_match_fns by:
url_match_fns : url_match_fn
start_document_query_pos url_match_fns
Shift LBRACE start_document_query_pos url_match_fns LBRACE
Reduce to start_document_query by:
start_document_query : start_document_query_pos url_match_fns LBRACE
start_document_query
Shift IDENT start_document_query IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
start_document_query ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
start_document_query element_name
Reduce to simple_selector by:
simple_selector : element_name
start_document_query simple_selector
Reduce to selector by:
selector : simple_selector
start_document_query selector
Reduce to selectors by:
selectors : selector
start_document_query selectors
Shift LBRACE start_document_query selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_document_query start_selector
Shift RBRACE start_document_query start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
start_document_query ruleset
Reduce to body by:
body : ruleset
start_document_query body
Shift RBRACE start_document_query body RBRACE
+

+ +

+ + From here, we reduce by document_query : start_document_query body RBRACE regardless of what token + comes next.
+ + (This takes us to 17) + + +

+
+ +

State 165

+ +

+ +
start_document_query:start_document_query_pos url_match_fns LBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
Reduce to url_match_fn by:
url_match_fn : function_no_quote
start_document_query_pos url_match_fn
Reduce to url_match_fns by:
url_match_fns : url_match_fn
start_document_query_pos url_match_fns
Shift LBRACE start_document_query_pos url_match_fns LBRACE
+

+ +

+ + From here, we reduce by start_document_query : start_document_query_pos url_match_fns LBRACE regardless of what token + comes next.
+ + (This takes us to 21) + + +

+
+ +

State 166

+ +

+ +
url_match_fns:url_match_fn COMMA . url_match_fns

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
Reduce to url_match_fn by:
url_match_fn : function_no_quote
start_document_query_pos url_match_fn
Shift COMMA start_document_query_pos url_match_fn COMMA
+

+ +

+ + Action table:
+
Lookahead tokenAction
FUNCTIONShift and go to state 83
URIShift and go to state 85
FUNCTION_NO_QUOTEShift and go to state 84
OtherError
+ +

+
+ +

State 167

+ +

+ +
function_no_quote:function_no_quote S .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
Shift S start_document_query_pos function_no_quote S
+

+ +

+ + From here, we reduce by function_no_quote : function_no_quote S regardless of what token + comes next.
+ + (This takes us to 80) + + +

+
+ +

State 168

+ +

+ +
function:function S .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift RPAREN start_document_query_pos FUNCTION RPAREN
Reduce to function by:
function : FUNCTION RPAREN
start_document_query_pos function
Shift S start_document_query_pos function S
+

+ +

+ + From here, we reduce by function : function S regardless of what token + comes next.
+ + (This can take us to 81, 179 or 267) + + +

+
+ +

State 169

+ +

+ +
uri:uri S .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift URI start_document_query_pos URI
Reduce to uri by:
uri : URI
start_document_query_pos uri
Shift S start_document_query_pos uri S
+

+ +

+ + From here, we reduce by uri : uri S regardless of what token + comes next.
+ + (This can take us to 82 or 176) + + +

+
+ +

State 170

+ +

+ +
resolution:RESOLUTION .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift RESOLUTION start_document_query_pos FUNCTION RESOLUTION
+

+ +

+ + From here, we reduce by resolution : RESOLUTION regardless of what token + comes next.
+ + (This takes us to 180) + + +

+
+ +

State 171

+ +

+ +
expr:term . operator expr
expr:term . expr
expr:term .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift IDENT start_document_query_pos FUNCTION IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION ident
Reduce to term by:
term : ident
start_document_query_pos FUNCTION term
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 188
IDENTShift and go to state 59
COMMAShift and go to state 258
HASHShift and go to state 187
EQUALShift and go to state 260
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
SLASHShift and go to state 259
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
URIShift and go to state 85
RESOLUTIONShift and go to state 170
VARIABLE_NAMEShift and go to state 181
CALC_SYMShift and go to state 186
UNICODE_RANGEShift and go to state 185
RATIOShift and go to state 196
OtherReduce by expr : term
(This can take us to 183, 262, 284, 310, 320, 321, 349 or 358)
+ +

+
+ +

State 172

+ +

+ +
term:ident .
ident:ident . S

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift IDENT start_document_query_pos FUNCTION IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION ident
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 155
OtherReduce by term : ident
(This takes us to 171)
+ +

+
+ +

State 173

+ +

+ +
term:ratio .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift RATIO start_document_query_pos FUNCTION RATIO
Reduce to ratio by:
ratio : RATIO
start_document_query_pos FUNCTION ratio
+

+ +

+ + From here, we reduce by term : ratio regardless of what token + comes next.
+ + (This takes us to 171) + + +

+
+ +

State 174

+ +

+ +
term:numeric .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift NUMBER start_document_query_pos FUNCTION NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION numeric
+

+ +

+ + From here, we reduce by term : numeric regardless of what token + comes next.
+ + (This takes us to 171) + + +

+
+ +

State 175

+ +

+ +
term:string .
string:string . S

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift STRING start_document_query_pos FUNCTION STRING
Reduce to string by:
string : STRING
start_document_query_pos FUNCTION string
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 263
OtherReduce by term : string
(This takes us to 171)
+ +

+
+ +

State 176

+ +

+ +
term:uri .
uri:uri . S

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift URI start_document_query_pos FUNCTION URI
Reduce to uri by:
uri : URI
start_document_query_pos FUNCTION uri
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 169
OtherReduce by term : uri
(This takes us to 171)
+ +

+
+ +

State 177

+ +

+ +
term:hexcolor .
hexcolor:hexcolor . S

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift HASH start_document_query_pos FUNCTION HASH
Reduce to hexcolor by:
hexcolor : HASH
start_document_query_pos FUNCTION hexcolor
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 264
OtherReduce by term : hexcolor
(This takes us to 171)
+ +

+
+ +

State 178

+ +

+ +
term:calc .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM calc_product
Reduce to calc_sum by:
calc_sum : calc_product
start_document_query_pos FUNCTION CALC_SYM calc_sum
Shift RPAREN start_document_query_pos FUNCTION CALC_SYM calc_sum RPAREN
Reduce to optional_space by:
optional_space :
start_document_query_pos FUNCTION CALC_SYM calc_sum RPAREN optional_space
Reduce to calc by:
calc : CALC_SYM calc_sum RPAREN optional_space
start_document_query_pos FUNCTION calc
+

+ +

+ + From here, we reduce by term : calc regardless of what token + comes next.
+ + (This takes us to 171) + + +

+
+ +

State 179

+ +

+ +
term:function .
function:function . S

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift FUNCTION start_document_query_pos FUNCTION FUNCTION
Shift RPAREN start_document_query_pos FUNCTION FUNCTION RPAREN
Reduce to function by:
function : FUNCTION RPAREN
start_document_query_pos FUNCTION function
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 168
OtherReduce by term : function
(This takes us to 171)
+ +

+
+ +

State 180

+ +

+ +
term:resolution .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift RESOLUTION start_document_query_pos FUNCTION RESOLUTION
Reduce to resolution by:
resolution : RESOLUTION
start_document_query_pos FUNCTION resolution
+

+ +

+ + From here, we reduce by term : resolution regardless of what token + comes next.
+ + (This takes us to 171) + + +

+
+ +

State 181

+ +

+ +
term:VARIABLE_NAME .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift VARIABLE_NAME start_document_query_pos FUNCTION VARIABLE_NAME
+

+ +

+ + From here, we reduce by term : VARIABLE_NAME regardless of what token + comes next.
+ + (This takes us to 171) + + +

+
+ +

State 182

+ +

+ +
term:uranges .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift UNICODE_RANGE start_document_query_pos FUNCTION UNICODE_RANGE
Reduce to uranges by:
uranges : UNICODE_RANGE
start_document_query_pos FUNCTION uranges
+

+ +

+ + From here, we reduce by term : uranges regardless of what token + comes next.
+ + (This takes us to 171) + + +

+
+ +

State 183

+ +

+ +
function:FUNCTION expr . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift IDENT start_document_query_pos FUNCTION IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION ident
Reduce to term by:
term : ident
start_document_query_pos FUNCTION term
Reduce to expr by:
expr : term
start_document_query_pos FUNCTION expr
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 265
OtherError
+ +

+
+ +

State 184

+ +

+ +
function:FUNCTION RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift RPAREN start_document_query_pos FUNCTION RPAREN
+

+ +

+ + From here, we reduce by function : FUNCTION RPAREN regardless of what token + comes next.
+ + (This can take us to 81, 179 or 267) + + +

+
+ +

State 185

+ +

+ +
uranges:UNICODE_RANGE . COMMA uranges
uranges:UNICODE_RANGE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift UNICODE_RANGE start_document_query_pos FUNCTION UNICODE_RANGE
+

+ +

+ + Action table:
+
Lookahead tokenAction
COMMAShift and go to state 266
(Overridden: reduce by uranges : UNICODE_RANGE)
OtherReduce by uranges : UNICODE_RANGE
(This can take us to 182 or 311)
+ +

+
+ +

State 186

+ +

+ +
calc:CALC_SYM . calc_sum RPAREN optional_space

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 272
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
OtherError
+ +

+
+ +

State 187

+ +

+ +
hexcolor:HASH .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift HASH start_document_query_pos FUNCTION HASH
+

+ +

+ + From here, we reduce by hexcolor : HASH regardless of what token + comes next.
+ + (This takes us to 177) + + +

+
+ +

State 188

+ +

+ +
string:STRING .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift STRING start_document_query_pos FUNCTION STRING
+

+ +

+ + From here, we reduce by string : STRING regardless of what token + comes next.
+ + (This takes us to 175) + + +

+
+ +

State 189

+ +

+ +
numeric:unary_operator . numeric

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift MINUS start_document_query_pos FUNCTION MINUS
Reduce to unary_operator by:
unary_operator : MINUS
start_document_query_pos FUNCTION unary_operator
+

+ +

+ + Action table:
+
Lookahead tokenAction
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
OtherError
+ +

+
+ +

State 190

+ +

+ +
numeric:NUMBER .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift NUMBER start_document_query_pos FUNCTION NUMBER
+

+ +

+ + From here, we reduce by numeric : NUMBER regardless of what token + comes next.
+ + (This can take us to 174, 271 or 273) + + +

+
+ +

State 191

+ +

+ +
numeric:PERCENTAGE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift PERCENTAGE start_document_query_pos FUNCTION PERCENTAGE
+

+ +

+ + From here, we reduce by numeric : PERCENTAGE regardless of what token + comes next.
+ + (This can take us to 174, 271 or 273) + + +

+
+ +

State 192

+ +

+ +
numeric:LENGTH .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift LENGTH start_document_query_pos FUNCTION LENGTH
+

+ +

+ + From here, we reduce by numeric : LENGTH regardless of what token + comes next.
+ + (This can take us to 174, 271 or 273) + + +

+
+ +

State 193

+ +

+ +
numeric:ANGLE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift ANGLE start_document_query_pos FUNCTION ANGLE
+

+ +

+ + From here, we reduce by numeric : ANGLE regardless of what token + comes next.
+ + (This can take us to 174, 271 or 273) + + +

+
+ +

State 194

+ +

+ +
numeric:TIME .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift TIME start_document_query_pos FUNCTION TIME
+

+ +

+ + From here, we reduce by numeric : TIME regardless of what token + comes next.
+ + (This can take us to 174, 271 or 273) + + +

+
+ +

State 195

+ +

+ +
numeric:FREQ .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift FREQ start_document_query_pos FUNCTION FREQ
+

+ +

+ + From here, we reduce by numeric : FREQ regardless of what token + comes next.
+ + (This can take us to 174, 271 or 273) + + +

+
+ +

State 196

+ +

+ +
ratio:RATIO .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift RATIO start_document_query_pos FUNCTION RATIO
+

+ +

+ + From here, we reduce by ratio : RATIO regardless of what token + comes next.
+ + (This takes us to 173) + + +

+
+ +

State 197

+ +

+ +
unary_operator:MINUS .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift MINUS start_document_query_pos FUNCTION MINUS
+

+ +

+ + From here, we reduce by unary_operator : MINUS regardless of what token + comes next.
+ + (This takes us to 189) + + +

+
+ +

State 198

+ +

+ +
unary_operator:PLUS .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift PLUS start_document_query_pos FUNCTION PLUS
+

+ +

+ + From here, we reduce by unary_operator : PLUS regardless of what token + comes next.
+ + (This takes us to 189) + + +

+
+ +

State 199

+ +

+ +
supports:start_supports body RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Reduce to supports_condition_root by:
supports_condition_root : supports_condition_in_parens
SUPPORTS_SYM supports_condition_root
Shift LBRACE SUPPORTS_SYM supports_condition_root LBRACE
Reduce to start_supports by:
start_supports : SUPPORTS_SYM supports_condition_root LBRACE
start_supports
Shift IDENT start_supports IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
start_supports ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
start_supports element_name
Reduce to simple_selector by:
simple_selector : element_name
start_supports simple_selector
Reduce to selector by:
selector : simple_selector
start_supports selector
Reduce to selectors by:
selectors : selector
start_supports selectors
Shift LBRACE start_supports selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_supports start_selector
Shift RBRACE start_supports start_selector RBRACE
Reduce to ruleset by:
ruleset : start_selector RBRACE
start_supports ruleset
Reduce to body by:
body : ruleset
start_supports body
Shift RBRACE start_supports body RBRACE
+

+ +

+ + From here, we reduce by supports : start_supports body RBRACE regardless of what token + comes next.
+ + (This takes us to 18) + + +

+
+ +

State 200

+ +

+ +
start_supports:SUPPORTS_SYM supports_condition_root LBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Reduce to supports_condition_root by:
supports_condition_root : supports_condition_in_parens
SUPPORTS_SYM supports_condition_root
Shift LBRACE SUPPORTS_SYM supports_condition_root LBRACE
+

+ +

+ + From here, we reduce by start_supports : SUPPORTS_SYM supports_condition_root LBRACE regardless of what token + comes next.
+ + (This takes us to 24) + + +

+
+ +

State 201

+ +

+ +
supports_conjunction:supports_conjunction_or_disjunction AND . supports_condition_in_parens

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Shift AND SUPPORTS_SYM supports_condition_in_parens AND
Shift LPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property
Shift COLON SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_condition_in_parens AND supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens AND supports_condition_in_parens
Reduce to supports_conjunction by:
supports_conjunction : supports_condition_in_parens AND supports_condition_in_parens
SUPPORTS_SYM supports_conjunction
Reduce to supports_conjunction_or_disjunction by:
supports_conjunction_or_disjunction : supports_conjunction
SUPPORTS_SYM supports_conjunction_or_disjunction
Shift AND SUPPORTS_SYM supports_conjunction_or_disjunction AND
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 92
OtherError
+ +

+
+ +

State 202

+ +

+ +
supports_disjunction:supports_conjunction_or_disjunction OR . supports_condition_in_parens

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Shift AND SUPPORTS_SYM supports_condition_in_parens AND
Shift LPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property
Shift COLON SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_condition_in_parens AND supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens AND supports_condition_in_parens
Reduce to supports_conjunction by:
supports_conjunction : supports_condition_in_parens AND supports_condition_in_parens
SUPPORTS_SYM supports_conjunction
Reduce to supports_conjunction_or_disjunction by:
supports_conjunction_or_disjunction : supports_conjunction
SUPPORTS_SYM supports_conjunction_or_disjunction
Shift OR SUPPORTS_SYM supports_conjunction_or_disjunction OR
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 92
OtherError
+ +

+
+ +

State 203

+ +

+ +
supports_conjunction:supports_condition_in_parens AND . supports_condition_in_parens

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Shift AND SUPPORTS_SYM supports_condition_in_parens AND
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 92
OtherError
+ +

+
+ +

State 204

+ +

+ +
supports_disjunction:supports_condition_in_parens OR . supports_condition_in_parens

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Shift OR SUPPORTS_SYM supports_condition_in_parens OR
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 92
OtherError
+ +

+
+ +

State 205

+ +

+ +
supports_condition:supports_negation .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift NOT SUPPORTS_SYM LPAREN NOT
Shift LPAREN SUPPORTS_SYM LPAREN NOT LPAREN
Shift IDENT SUPPORTS_SYM LPAREN NOT LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN NOT LPAREN property
Shift COLON SUPPORTS_SYM LPAREN NOT LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN NOT LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN NOT LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN NOT LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN NOT LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN NOT LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN NOT LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN NOT LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM LPAREN NOT supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM LPAREN NOT supports_condition_in_parens
Reduce to supports_negation by:
supports_negation : NOT supports_condition_in_parens
SUPPORTS_SYM LPAREN supports_negation
+

+ +

+ + From here, we reduce by supports_condition : supports_negation regardless of what token + comes next.
+ + (This takes us to 208) + + +

+
+ +

State 206

+ +

+ +
supports_condition:supports_conjunction_or_disjunction .
supports_conjunction:supports_conjunction_or_disjunction . AND supports_condition_in_parens
supports_disjunction:supports_conjunction_or_disjunction . OR supports_condition_in_parens

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift LPAREN SUPPORTS_SYM LPAREN LPAREN
Shift IDENT SUPPORTS_SYM LPAREN LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN LPAREN property
Shift COLON SUPPORTS_SYM LPAREN LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM LPAREN supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM LPAREN supports_condition_in_parens
Shift AND SUPPORTS_SYM LPAREN supports_condition_in_parens AND
Shift LPAREN SUPPORTS_SYM LPAREN supports_condition_in_parens AND LPAREN
Shift IDENT SUPPORTS_SYM LPAREN supports_condition_in_parens AND LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN supports_condition_in_parens AND LPAREN property
Shift COLON SUPPORTS_SYM LPAREN supports_condition_in_parens AND LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN supports_condition_in_parens AND LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN supports_condition_in_parens AND LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN supports_condition_in_parens AND LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN supports_condition_in_parens AND LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN supports_condition_in_parens AND LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN supports_condition_in_parens AND LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN supports_condition_in_parens AND LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM LPAREN supports_condition_in_parens AND supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM LPAREN supports_condition_in_parens AND supports_condition_in_parens
Reduce to supports_conjunction by:
supports_conjunction : supports_condition_in_parens AND supports_condition_in_parens
SUPPORTS_SYM LPAREN supports_conjunction
Reduce to supports_conjunction_or_disjunction by:
supports_conjunction_or_disjunction : supports_conjunction
SUPPORTS_SYM LPAREN supports_conjunction_or_disjunction
+

+ +

+ + Action table:
+
Lookahead tokenAction
ANDShift and go to state 201
ORShift and go to state 202
OtherReduce by supports_condition : supports_conjunction_or_disjunction
(This takes us to 208)
+ +

+
+ +

State 207

+ +

+ +
supports_condition:supports_condition_in_parens .
supports_conjunction:supports_condition_in_parens . AND supports_condition_in_parens
supports_disjunction:supports_condition_in_parens . OR supports_condition_in_parens

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift LPAREN SUPPORTS_SYM LPAREN LPAREN
Shift IDENT SUPPORTS_SYM LPAREN LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN LPAREN property
Shift COLON SUPPORTS_SYM LPAREN LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM LPAREN supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM LPAREN supports_condition_in_parens
+

+ +

+ + Action table:
+
Lookahead tokenAction
ANDShift and go to state 203
ORShift and go to state 204
OtherReduce by supports_condition : supports_condition_in_parens
(This takes us to 208)
+ +

+
+ +

State 208

+ +

+ +
supports_condition_in_parens:LPAREN supports_condition . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift LPAREN SUPPORTS_SYM LPAREN LPAREN
Shift IDENT SUPPORTS_SYM LPAREN LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN LPAREN property
Shift COLON SUPPORTS_SYM LPAREN LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM LPAREN supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM LPAREN supports_condition_in_parens
Reduce to supports_condition by:
supports_condition : supports_condition_in_parens
SUPPORTS_SYM LPAREN supports_condition
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 278
OtherError
+ +

+
+ +

State 209

+ +

+ +
supports_declaration_condition:LPAREN declaration_internal . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 279
OtherError
+ +

+
+ +

State 210

+ +

+ +
supports_declaration_condition:LPAREN S . declaration_internal RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift S SUPPORTS_SYM LPAREN S
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 113
STARShift and go to state 114
VARIABLE_NAMEShift and go to state 115
OtherError
+ +

+
+ +

State 211

+ +

+ +
supports_negation:NOT supports_condition_in_parens .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift NOT SUPPORTS_SYM NOT
Shift LPAREN SUPPORTS_SYM NOT LPAREN
Shift IDENT SUPPORTS_SYM NOT LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM NOT LPAREN property
Shift COLON SUPPORTS_SYM NOT LPAREN property COLON
Shift IDENT SUPPORTS_SYM NOT LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM NOT LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM NOT LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM NOT LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM NOT LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM NOT LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM NOT LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM NOT supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM NOT supports_condition_in_parens
+

+ +

+ + From here, we reduce by supports_negation : NOT supports_condition_in_parens regardless of what token + comes next.
+ + (This can take us to 89 or 205) + + +

+
+ +

State 212

+ +

+ +
keyframes_rule:start_keyframes_rule keyframes_blocks RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_selectors
Shift LBRACE start_keyframes_rule keyframes_selectors LBRACE
Reduce to start_keyframes_block by:
start_keyframes_block : keyframes_selectors LBRACE
start_keyframes_rule start_keyframes_block
Shift RBRACE start_keyframes_rule start_keyframes_block RBRACE
Reduce to keyframes_block by:
keyframes_block : start_keyframes_block RBRACE
start_keyframes_rule keyframes_block
Reduce to keyframes_blocks by:
keyframes_blocks : keyframes_block
start_keyframes_rule keyframes_blocks
Shift RBRACE start_keyframes_rule keyframes_blocks RBRACE
+

+ +

+ + From here, we reduce by keyframes_rule : start_keyframes_rule keyframes_blocks RBRACE regardless of what token + comes next.
+ + (This takes us to 14) + + +

+
+ +

State 213

+ +

+ +
keyframes_blocks:keyframes_block keyframes_blocks .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_selectors
Shift LBRACE start_keyframes_rule keyframes_selectors LBRACE
Reduce to start_keyframes_block by:
start_keyframes_block : keyframes_selectors LBRACE
start_keyframes_rule start_keyframes_block
Shift RBRACE start_keyframes_rule start_keyframes_block RBRACE
Reduce to keyframes_block by:
keyframes_block : start_keyframes_block RBRACE
start_keyframes_rule keyframes_block
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_block keyframes_selectors
Shift LBRACE start_keyframes_rule keyframes_block keyframes_selectors LBRACE
Reduce to start_keyframes_block by:
start_keyframes_block : keyframes_selectors LBRACE
start_keyframes_rule keyframes_block start_keyframes_block
Shift RBRACE start_keyframes_rule keyframes_block start_keyframes_block RBRACE
Reduce to keyframes_block by:
keyframes_block : start_keyframes_block RBRACE
start_keyframes_rule keyframes_block keyframes_block
Reduce to keyframes_blocks by:
keyframes_blocks : keyframes_block
start_keyframes_rule keyframes_block keyframes_blocks
+

+ +

+ + From here, we reduce by keyframes_blocks : keyframes_block keyframes_blocks regardless of what token + comes next.
+ + (This can take us to 97 or 213) + + +

+
+ +

State 214

+ +

+ +
keyframes_block:start_keyframes_block declarations . RBRACE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_selectors
Shift LBRACE start_keyframes_rule keyframes_selectors LBRACE
Reduce to start_keyframes_block by:
start_keyframes_block : keyframes_selectors LBRACE
start_keyframes_rule start_keyframes_block
Shift SEMI start_keyframes_rule start_keyframes_block SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_keyframes_rule start_keyframes_block one_or_more_semis
Reduce to declarations by:
declarations : one_or_more_semis
start_keyframes_rule start_keyframes_block declarations
+

+ +

+ + Action table:
+
Lookahead tokenAction
RBRACEShift and go to state 281
OtherError
+ +

+
+ +

State 215

+ +

+ +
keyframes_block:start_keyframes_block RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_selectors
Shift LBRACE start_keyframes_rule keyframes_selectors LBRACE
Reduce to start_keyframes_block by:
start_keyframes_block : keyframes_selectors LBRACE
start_keyframes_rule start_keyframes_block
Shift RBRACE start_keyframes_rule start_keyframes_block RBRACE
+

+ +

+ + From here, we reduce by keyframes_block : start_keyframes_block RBRACE regardless of what token + comes next.
+ + (This takes us to 99) + + +

+
+ +

State 216

+ +

+ +
start_keyframes_block:keyframes_selectors LBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_selectors
Shift LBRACE start_keyframes_rule keyframes_selectors LBRACE
+

+ +

+ + From here, we reduce by start_keyframes_block : keyframes_selectors LBRACE regardless of what token + comes next.
+ + (This takes us to 100) + + +

+
+ +

State 217

+ +

+ +
keyframes_selectors:keyframes_selector COMMA . keyframes_selectors

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Shift IDENT start_keyframes_rule IDENT
Reduce to keyframes_selector by:
keyframes_selector : IDENT
start_keyframes_rule keyframes_selector
Shift COMMA start_keyframes_rule keyframes_selector COMMA
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 103
PERCENTAGEShift and go to state 104
OtherReduce by keyframes_selectors :
(This takes us to 282)
+ +

+
+ +

State 218

+ +

+ +
start_keyframes_rule:KEYFRAMES_SYM IDENT LBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
+

+ +

+ + From here, we reduce by start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE regardless of what token + comes next.
+ + (This takes us to 26) + + +

+
+ +

State 219

+ +

+ +
fontface_rule:start_fontface_rule declarations RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift SEMI start_fontface_rule SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_fontface_rule one_or_more_semis
Reduce to declarations by:
declarations : one_or_more_semis
start_fontface_rule declarations
Shift RBRACE start_fontface_rule declarations RBRACE
+

+ +

+ + From here, we reduce by fontface_rule : start_fontface_rule declarations RBRACE regardless of what token + comes next.
+ + (This takes us to 15) + + +

+
+ +

State 220

+ +

+ +
one_or_more_semis:SEMI one_or_more_semis .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift SEMI start_fontface_rule SEMI
Shift SEMI start_fontface_rule SEMI SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_fontface_rule SEMI one_or_more_semis
+

+ +

+ + From here, we reduce by one_or_more_semis : SEMI one_or_more_semis regardless of what token + comes next.
+ + (This can take us to 110, 220 or 221) + + +

+
+ +

State 221

+ +

+ +
declarations:declaration one_or_more_semis . declarations
declarations:declaration one_or_more_semis .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift IDENT start_fontface_rule IDENT
Reduce to property by:
property : IDENT
start_fontface_rule property
Shift COLON start_fontface_rule property COLON
Shift IDENT start_fontface_rule property COLON IDENT
Reduce to ident by:
ident : IDENT
start_fontface_rule property COLON ident
Reduce to term by:
term : ident
start_fontface_rule property COLON term
Reduce to expr by:
expr : term
start_fontface_rule property COLON expr
Reduce to prio by:
prio :
start_fontface_rule property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
start_fontface_rule declaration_internal
Reduce to declaration by:
declaration : declaration_internal
start_fontface_rule declaration
Shift SEMI start_fontface_rule declaration SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_fontface_rule declaration one_or_more_semis
+

+ +

+ + Action table:
+
Lookahead tokenAction
SEMIShift and go to state 108
IDENTShift and go to state 113
STARShift and go to state 114
VARIABLE_NAMEShift and go to state 115
OtherReduce by declarations : declaration one_or_more_semis
(This can take us to 106, 117, 214, 222 or 283)
+ +

+
+ +

State 222

+ +

+ +
declarations:one_or_more_semis declarations .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift SEMI start_fontface_rule SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_fontface_rule one_or_more_semis
Shift SEMI start_fontface_rule one_or_more_semis SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_fontface_rule one_or_more_semis one_or_more_semis
Reduce to declarations by:
declarations : one_or_more_semis
start_fontface_rule one_or_more_semis declarations
+

+ +

+ + From here, we reduce by declarations : one_or_more_semis declarations regardless of what token + comes next.
+ + (This can take us to 106, 117, 214, 222 or 283) + + +

+
+ +

State 223

+ +

+ +
declaration_internal:property COLON . expr prio
declaration_internal:property COLON . S expr prio

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 188
IDENTShift and go to state 59
SShift and go to state 285
HASHShift and go to state 187
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
URIShift and go to state 85
RESOLUTIONShift and go to state 170
VARIABLE_NAMEShift and go to state 181
CALC_SYMShift and go to state 186
UNICODE_RANGEShift and go to state 185
RATIOShift and go to state 196
OtherError
+ +

+
+ +

State 224

+ +

+ +
declaration_internal:property S . COLON expr prio
declaration_internal:property S . COLON S expr prio

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift S SUPPORTS_SYM LPAREN property S
+

+ +

+ + Action table:
+
Lookahead tokenAction
COLONShift and go to state 286
OtherError
+ +

+
+ +

State 225

+ +

+ +
property:STAR IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift STAR SUPPORTS_SYM LPAREN STAR
Shift IDENT SUPPORTS_SYM LPAREN STAR IDENT
+

+ +

+ + From here, we reduce by property : STAR IDENT regardless of what token + comes next.
+ + (This takes us to 112) + + +

+
+ +

State 226

+ +

+ +
ruleset:start_selector declarations RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
Reduce to selectors by:
selectors : selector
selectors
Shift LBRACE selectors LBRACE
Reduce to start_selector by:
start_selector : selectors LBRACE
start_selector
Shift SEMI start_selector SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_selector one_or_more_semis
Reduce to declarations by:
declarations : one_or_more_semis
start_selector declarations
Shift RBRACE start_selector declarations RBRACE
+

+ +

+ + From here, we reduce by ruleset : start_selector declarations RBRACE regardless of what token + comes next.
+ + (This takes us to 12) + + +

+
+ +

State 227

+ +

+ +
selectors:selector COMMA selectors .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Reduce to selector by:
selector : simple_selector
selector
Shift COMMA selector COMMA
Shift IDENT selector COMMA IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
selector COMMA ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
selector COMMA element_name
Reduce to simple_selector by:
simple_selector : element_name
selector COMMA simple_selector
Reduce to selector by:
selector : simple_selector
selector COMMA selector
Reduce to selectors by:
selectors : selector
selector COMMA selectors
+

+ +

+ + From here, we reduce by selectors : selector COMMA selectors regardless of what token + comes next.
+ + (This can take us to 32 or 227) + + +

+
+ +

State 228

+ +

+ +
selector:simple_selector combinator selector .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector
Shift S simple_selector S
Reduce to combinator by:
combinator : S
simple_selector combinator
Shift IDENT simple_selector combinator IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
simple_selector combinator ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
simple_selector combinator element_name
Reduce to simple_selector by:
simple_selector : element_name
simple_selector combinator simple_selector
Reduce to selector by:
selector : simple_selector
simple_selector combinator selector
+

+ +

+ + From here, we reduce by selector : simple_selector combinator selector regardless of what token + comes next.
+ + (This can take us to 33 or 228) + + +

+
+ +

State 229

+ +

+ +
ident_with_namespace:IDENT "|" IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Shift "|" IDENT "|"
Shift IDENT IDENT "|" IDENT
+

+ +

+ + From here, we reduce by ident_with_namespace : IDENT "|" IDENT regardless of what token + comes next.
+ + (This can take us to 40 or 140) + + +

+
+ +

State 230

+ +

+ +
element_name:IDENT "|" STAR .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IDENT IDENT
Shift "|" IDENT "|"
Shift STAR IDENT "|" STAR
+

+ +

+ + From here, we reduce by element_name : IDENT "|" STAR regardless of what token + comes next.
+ + (This takes us to 35) + + +

+
+ +

State 231

+ +

+ +
ident_with_namespace:STAR "|" IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift STAR STAR
Shift "|" STAR "|"
Shift IDENT STAR "|" IDENT
+

+ +

+ + From here, we reduce by ident_with_namespace : STAR "|" IDENT regardless of what token + comes next.
+ + (This can take us to 40 or 140) + + +

+
+ +

State 232

+ +

+ +
element_name:STAR "|" STAR .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift STAR STAR
Shift "|" STAR "|"
Shift STAR STAR "|" STAR
+

+ +

+ + From here, we reduce by element_name : STAR "|" STAR regardless of what token + comes next.
+ + (This takes us to 35) + + +

+
+ +

State 233

+ +

+ +
ident_with_namespace:IDENT "|" . IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Shift "|" LSQUARE IDENT "|"
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 229
OtherError
+ +

+
+ +

State 234

+ +

+ +
ident_with_namespace:STAR "|" . IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift STAR LSQUARE STAR
Shift "|" LSQUARE STAR "|"
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 231
OtherError
+ +

+
+ +

State 235

+ +

+ +
attrib:LSQUARE ident_with_namespace EQUAL . IDENT RSQUARE
attrib:LSQUARE ident_with_namespace EQUAL . STRING RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift EQUAL LSQUARE ident_with_namespace EQUAL
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 288
IDENTShift and go to state 287
OtherError
+ +

+
+ +

State 236

+ +

+ +
attrib:LSQUARE ident_with_namespace INCLUDES . STRING RSQUARE
attrib:LSQUARE ident_with_namespace INCLUDES . IDENT RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift INCLUDES LSQUARE ident_with_namespace INCLUDES
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 289
IDENTShift and go to state 290
OtherError
+ +

+
+ +

State 237

+ +

+ +
attrib:LSQUARE ident_with_namespace DASHMATCH . IDENT RSQUARE
attrib:LSQUARE ident_with_namespace DASHMATCH . STRING RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift DASHMATCH LSQUARE ident_with_namespace DASHMATCH
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 292
IDENTShift and go to state 291
OtherError
+ +

+
+ +

State 238

+ +

+ +
attrib:LSQUARE ident_with_namespace PREFIXMATCH . IDENT RSQUARE
attrib:LSQUARE ident_with_namespace PREFIXMATCH . STRING RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift PREFIXMATCH LSQUARE ident_with_namespace PREFIXMATCH
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 294
IDENTShift and go to state 293
OtherError
+ +

+
+ +

State 239

+ +

+ +
attrib:LSQUARE ident_with_namespace SUFFIXMATCH . IDENT RSQUARE
attrib:LSQUARE ident_with_namespace SUFFIXMATCH . STRING RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift SUFFIXMATCH LSQUARE ident_with_namespace SUFFIXMATCH
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 296
IDENTShift and go to state 295
OtherError
+ +

+
+ +

State 240

+ +

+ +
attrib:LSQUARE ident_with_namespace SUBSTRINGMATCH . IDENT RSQUARE
attrib:LSQUARE ident_with_namespace SUBSTRINGMATCH . STRING RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift SUBSTRINGMATCH LSQUARE ident_with_namespace SUBSTRINGMATCH
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 298
IDENTShift and go to state 297
OtherError
+ +

+
+ +

State 241

+ +

+ +
attrib:LSQUARE ident_with_namespace RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift RSQUARE LSQUARE ident_with_namespace RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 242

+ +

+ +
pseudo:COLON COLON IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift COLON COLON COLON
Shift IDENT COLON COLON IDENT
+

+ +

+ + From here, we reduce by pseudo : COLON COLON IDENT regardless of what token + comes next.
+ + (This takes us to 44) + + +

+
+ +

State 243

+ +

+ +
pseudo:COLON COLON MOZ_PSEUDO_ELEMENT . optional_space any_number_of_idents optional_space RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift COLON COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON COLON MOZ_PSEUDO_ELEMENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 163
(Overridden: reduce by optional_space :)
OtherReduce by optional_space :
(This takes us to 299)
+ +

+
+ +

State 244

+ +

+ +
pseudo:COLON FUNCTION RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift FUNCTION COLON FUNCTION
Shift RPAREN COLON FUNCTION RPAREN
+

+ +

+ + From here, we reduce by pseudo : COLON FUNCTION RPAREN regardless of what token + comes next.
+ + (This takes us to 44) + + +

+
+ +

State 245

+ +

+ +
pseudo:COLON FUNCTION IDENT . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift FUNCTION COLON FUNCTION
Shift IDENT COLON FUNCTION IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 300
OtherError
+ +

+
+ +

State 246

+ +

+ +
pseudo:COLON NOT_PSEUDO_CLASS simple_selector . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift NOT_PSEUDO_CLASS COLON NOT_PSEUDO_CLASS
Shift IDENT COLON NOT_PSEUDO_CLASS IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
COLON NOT_PSEUDO_CLASS ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
COLON NOT_PSEUDO_CLASS element_name
Reduce to simple_selector by:
simple_selector : element_name
COLON NOT_PSEUDO_CLASS simple_selector
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 301
OtherError
+ +

+
+ +

State 247

+ +

+ +
simple_selectors:simple_selector . COMMA simple_selectors
simple_selectors:simple_selector .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MATCHES_PSEUDO_CLASS COLON MATCHES_PSEUDO_CLASS
Shift IDENT COLON MATCHES_PSEUDO_CLASS IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
COLON MATCHES_PSEUDO_CLASS ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
COLON MATCHES_PSEUDO_CLASS element_name
Reduce to simple_selector by:
simple_selector : element_name
COLON MATCHES_PSEUDO_CLASS simple_selector
+

+ +

+ + Action table:
+
Lookahead tokenAction
COMMAShift and go to state 302
OtherReduce by simple_selectors : simple_selector
(This can take us to 248 or 336)
+ +

+
+ +

State 248

+ +

+ +
pseudo:COLON MATCHES_PSEUDO_CLASS simple_selectors . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MATCHES_PSEUDO_CLASS COLON MATCHES_PSEUDO_CLASS
Shift IDENT COLON MATCHES_PSEUDO_CLASS IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
COLON MATCHES_PSEUDO_CLASS ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
COLON MATCHES_PSEUDO_CLASS element_name
Reduce to simple_selector by:
simple_selector : element_name
COLON MATCHES_PSEUDO_CLASS simple_selector
Reduce to simple_selectors by:
simple_selectors : simple_selector
COLON MATCHES_PSEUDO_CLASS simple_selectors
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 303
OtherError
+ +

+
+ +

State 249

+ +

+ +
pseudo:COLON MOZ_PSEUDO_ELEMENT optional_space . any_number_of_idents optional_space RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON MOZ_PSEUDO_ELEMENT optional_space
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 306
OtherReduce by any_number_of_idents :
(This takes us to 304)
+ +

+
+ +

State 250

+ +

+ +
import:IMPORT_SYM import_location medium SEMI .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift STRING IMPORT_SYM STRING
Reduce to import_location by:
import_location : STRING
IMPORT_SYM import_location
Shift IDENT IMPORT_SYM import_location IDENT
Reduce to medium by:
medium : IDENT
IMPORT_SYM import_location medium
Shift SEMI IMPORT_SYM import_location medium SEMI
+

+ +

+ + From here, we reduce by import : IMPORT_SYM import_location medium SEMI regardless of what token + comes next.
+ + (This takes us to 6) + + +

+
+ +

State 251

+ +

+ +
medium:medium COMMA . IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift STRING IMPORT_SYM STRING
Reduce to import_location by:
import_location : STRING
IMPORT_SYM import_location
Shift IDENT IMPORT_SYM import_location IDENT
Reduce to medium by:
medium : IDENT
IMPORT_SYM import_location medium
Shift COMMA IMPORT_SYM import_location medium COMMA
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 307
OtherError
+ +

+
+ +

State 252

+ +

+ +
namespace:NAMESPACE_SYM ident import_location SEMI .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift NAMESPACE_SYM NAMESPACE_SYM
Shift IDENT NAMESPACE_SYM IDENT
Reduce to ident by:
ident : IDENT
NAMESPACE_SYM ident
Shift STRING NAMESPACE_SYM ident STRING
Reduce to import_location by:
import_location : STRING
NAMESPACE_SYM ident import_location
Shift SEMI NAMESPACE_SYM ident import_location SEMI
+

+ +

+ + From here, we reduce by namespace : NAMESPACE_SYM ident import_location SEMI regardless of what token + comes next.
+ + (This takes us to 7) + + +

+
+ +

State 253

+ +

+ +
media_query_list:media_query_list COMMA media_query .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to media_query_list by:
media_query_list :
MEDIA_SYM media_query_list
Shift COMMA MEDIA_SYM media_query_list COMMA
Reduce to optional_only_or_not by:
optional_only_or_not :
MEDIA_SYM media_query_list COMMA optional_only_or_not
Shift IDENT MEDIA_SYM media_query_list COMMA optional_only_or_not IDENT
Reduce to media_type by:
media_type : IDENT
MEDIA_SYM media_query_list COMMA optional_only_or_not media_type
Reduce to optional_and_exprs by:
optional_and_exprs :
MEDIA_SYM media_query_list COMMA optional_only_or_not media_type optional_and_exprs
Reduce to media_query by:
media_query : optional_only_or_not media_type optional_and_exprs
MEDIA_SYM media_query_list COMMA media_query
+

+ +

+ + From here, we reduce by media_query_list : media_query_list COMMA media_query regardless of what token + comes next.
+ + (This takes us to 70) + + +

+
+ +

State 254

+ +

+ +
media_query:optional_only_or_not media_type optional_and_exprs .
optional_and_exprs:optional_and_exprs . AND media_expr

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to optional_only_or_not by:
optional_only_or_not :
MEDIA_SYM optional_only_or_not
Shift IDENT MEDIA_SYM optional_only_or_not IDENT
Reduce to media_type by:
media_type : IDENT
MEDIA_SYM optional_only_or_not media_type
Reduce to optional_and_exprs by:
optional_and_exprs :
MEDIA_SYM optional_only_or_not media_type optional_and_exprs
+

+ +

+ + Action table:
+
Lookahead tokenAction
ANDShift and go to state 255
OtherReduce by media_query : optional_only_or_not media_type optional_and_exprs
(This can take us to 69 or 253)
+ +

+
+ +

State 255

+ +

+ +
optional_and_exprs:optional_and_exprs AND . media_expr

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to optional_only_or_not by:
optional_only_or_not :
MEDIA_SYM optional_only_or_not
Shift IDENT MEDIA_SYM optional_only_or_not IDENT
Reduce to media_type by:
media_type : IDENT
MEDIA_SYM optional_only_or_not media_type
Reduce to optional_and_exprs by:
optional_and_exprs :
MEDIA_SYM optional_only_or_not media_type optional_and_exprs
Shift AND MEDIA_SYM optional_only_or_not media_type optional_and_exprs AND
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 75
OtherError
+ +

+
+ +

State 256

+ +

+ +
media_expr:LPAREN optional_space IDENT . optional_space RPAREN
media_expr:LPAREN optional_space IDENT . optional_space COLON optional_space expr RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space
Shift IDENT MEDIA_SYM LPAREN optional_space IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 163
OtherReduce by optional_space :
(This takes us to 309)
+ +

+
+ +

State 257

+ +

+ +
url_match_fns:url_match_fn COMMA url_match_fns .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION_NO_QUOTE start_document_query_pos FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos function_no_quote
Reduce to url_match_fn by:
url_match_fn : function_no_quote
start_document_query_pos url_match_fn
Shift COMMA start_document_query_pos url_match_fn COMMA
Shift FUNCTION_NO_QUOTE start_document_query_pos url_match_fn COMMA FUNCTION_NO_QUOTE
Reduce to function_no_quote by:
function_no_quote : FUNCTION_NO_QUOTE
start_document_query_pos url_match_fn COMMA function_no_quote
Reduce to url_match_fn by:
url_match_fn : function_no_quote
start_document_query_pos url_match_fn COMMA url_match_fn
Reduce to url_match_fns by:
url_match_fns : url_match_fn
start_document_query_pos url_match_fn COMMA url_match_fns
+

+ +

+ + From here, we reduce by url_match_fns : url_match_fn COMMA url_match_fns regardless of what token + comes next.
+ + (This can take us to 78 or 257) + + +

+
+ +

State 258

+ +

+ +
operator:COMMA .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift IDENT start_document_query_pos FUNCTION IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION ident
Reduce to term by:
term : ident
start_document_query_pos FUNCTION term
Shift COMMA start_document_query_pos FUNCTION term COMMA
+

+ +

+ + From here, we reduce by operator : COMMA regardless of what token + comes next.
+ + (This takes us to 261) + + +

+
+ +

State 259

+ +

+ +
operator:SLASH .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift IDENT start_document_query_pos FUNCTION IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION ident
Reduce to term by:
term : ident
start_document_query_pos FUNCTION term
Shift SLASH start_document_query_pos FUNCTION term SLASH
+

+ +

+ + From here, we reduce by operator : SLASH regardless of what token + comes next.
+ + (This takes us to 261) + + +

+
+ +

State 260

+ +

+ +
operator:EQUAL .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift IDENT start_document_query_pos FUNCTION IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION ident
Reduce to term by:
term : ident
start_document_query_pos FUNCTION term
Shift EQUAL start_document_query_pos FUNCTION term EQUAL
+

+ +

+ + From here, we reduce by operator : EQUAL regardless of what token + comes next.
+ + (This takes us to 261) + + +

+
+ +

State 261

+ +

+ +
expr:term operator . expr

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift IDENT start_document_query_pos FUNCTION IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION ident
Reduce to term by:
term : ident
start_document_query_pos FUNCTION term
Shift COMMA start_document_query_pos FUNCTION term COMMA
Reduce to operator by:
operator : COMMA
start_document_query_pos FUNCTION term operator
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 188
IDENTShift and go to state 59
HASHShift and go to state 187
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
URIShift and go to state 85
RESOLUTIONShift and go to state 170
VARIABLE_NAMEShift and go to state 181
CALC_SYMShift and go to state 186
UNICODE_RANGEShift and go to state 185
RATIOShift and go to state 196
OtherError
+ +

+
+ +

State 262

+ +

+ +
expr:term expr .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift IDENT start_document_query_pos FUNCTION IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION ident
Reduce to term by:
term : ident
start_document_query_pos FUNCTION term
Shift IDENT start_document_query_pos FUNCTION term IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION term ident
Reduce to term by:
term : ident
start_document_query_pos FUNCTION term term
Reduce to expr by:
expr : term
start_document_query_pos FUNCTION term expr
+

+ +

+ + From here, we reduce by expr : term expr regardless of what token + comes next.
+ + (This can take us to 183, 262, 284, 310, 320, 321, 349 or 358) + + +

+
+ +

State 263

+ +

+ +
string:string S .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift STRING start_document_query_pos FUNCTION STRING
Reduce to string by:
string : STRING
start_document_query_pos FUNCTION string
Shift S start_document_query_pos FUNCTION string S
+

+ +

+ + From here, we reduce by string : string S regardless of what token + comes next.
+ + (This takes us to 175) + + +

+
+ +

State 264

+ +

+ +
hexcolor:hexcolor S .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift HASH start_document_query_pos FUNCTION HASH
Reduce to hexcolor by:
hexcolor : HASH
start_document_query_pos FUNCTION hexcolor
Shift S start_document_query_pos FUNCTION hexcolor S
+

+ +

+ + From here, we reduce by hexcolor : hexcolor S regardless of what token + comes next.
+ + (This takes us to 177) + + +

+
+ +

State 265

+ +

+ +
function:FUNCTION expr RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift IDENT start_document_query_pos FUNCTION IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION ident
Reduce to term by:
term : ident
start_document_query_pos FUNCTION term
Reduce to expr by:
expr : term
start_document_query_pos FUNCTION expr
Shift RPAREN start_document_query_pos FUNCTION expr RPAREN
+

+ +

+ + From here, we reduce by function : FUNCTION expr RPAREN regardless of what token + comes next.
+ + (This can take us to 81, 179 or 267) + + +

+
+ +

State 266

+ +

+ +
uranges:UNICODE_RANGE COMMA . uranges

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift UNICODE_RANGE start_document_query_pos FUNCTION UNICODE_RANGE
Shift COMMA start_document_query_pos FUNCTION UNICODE_RANGE COMMA
+

+ +

+ + Action table:
+
Lookahead tokenAction
UNICODE_RANGEShift and go to state 185
OtherError
+ +

+
+ +

State 267

+ +

+ +
function:function . S
calc_value:function .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift FUNCTION start_document_query_pos FUNCTION CALC_SYM FUNCTION
Shift RPAREN start_document_query_pos FUNCTION CALC_SYM FUNCTION RPAREN
Reduce to function by:
function : FUNCTION RPAREN
start_document_query_pos FUNCTION CALC_SYM function
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 168
(Overridden: reduce by calc_value : function)
OtherReduce by calc_value : function
(This can take us to 270, 354 or 355)
+ +

+
+ +

State 268

+ +

+ +
calc:CALC_SYM calc_sum . RPAREN optional_space

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM calc_product
Reduce to calc_sum by:
calc_sum : calc_product
start_document_query_pos FUNCTION CALC_SYM calc_sum
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 312
OtherError
+ +

+
+ +

State 269

+ +

+ +
calc_sum:calc_product .
calc_sum:calc_product . PLUS calc_sum
calc_sum:calc_product . MINUS calc_sum

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM calc_product
+

+ +

+ + Action table:
+
Lookahead tokenAction
PLUSShift and go to state 313
MINUSShift and go to state 314
OtherReduce by calc_sum : calc_product
(This can take us to 268, 316, 342 or 343)
+ +

+
+ +

State 270

+ +

+ +
calc_product:calc_value .
calc_product:calc_value . optional_space STAR calc_value
calc_product:calc_value . optional_space SLASH calc_value

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 163
STARReduce by optional_space :
(This takes us to 315)
SLASHReduce by optional_space :
(This takes us to 315)
OtherReduce by calc_product : calc_value
(This takes us to 269)
+ +

+
+ +

State 271

+ +

+ +
calc_value:numeric .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
+

+ +

+ + From here, we reduce by calc_value : numeric regardless of what token + comes next.
+ + (This can take us to 270, 354 or 355) + + +

+
+ +

State 272

+ +

+ +
calc_value:LPAREN . calc_sum RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift LPAREN start_document_query_pos FUNCTION CALC_SYM LPAREN
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 272
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
OtherError
+ +

+
+ +

State 273

+ +

+ +
numeric:unary_operator numeric .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift MINUS start_document_query_pos FUNCTION MINUS
Reduce to unary_operator by:
unary_operator : MINUS
start_document_query_pos FUNCTION unary_operator
Shift NUMBER start_document_query_pos FUNCTION unary_operator NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION unary_operator numeric
+

+ +

+ + From here, we reduce by numeric : unary_operator numeric regardless of what token + comes next.
+ + (This can take us to 174, 271 or 273) + + +

+
+ +

State 274

+ +

+ +
supports_conjunction:supports_conjunction_or_disjunction AND supports_condition_in_parens .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Shift AND SUPPORTS_SYM supports_condition_in_parens AND
Shift LPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property
Shift COLON SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_condition_in_parens AND supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens AND supports_condition_in_parens
Reduce to supports_conjunction by:
supports_conjunction : supports_condition_in_parens AND supports_condition_in_parens
SUPPORTS_SYM supports_conjunction
Reduce to supports_conjunction_or_disjunction by:
supports_conjunction_or_disjunction : supports_conjunction
SUPPORTS_SYM supports_conjunction_or_disjunction
Shift AND SUPPORTS_SYM supports_conjunction_or_disjunction AND
Shift LPAREN SUPPORTS_SYM supports_conjunction_or_disjunction AND LPAREN
Shift IDENT SUPPORTS_SYM supports_conjunction_or_disjunction AND LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM supports_conjunction_or_disjunction AND LPAREN property
Shift COLON SUPPORTS_SYM supports_conjunction_or_disjunction AND LPAREN property COLON
Shift IDENT SUPPORTS_SYM supports_conjunction_or_disjunction AND LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM supports_conjunction_or_disjunction AND LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM supports_conjunction_or_disjunction AND LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM supports_conjunction_or_disjunction AND LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM supports_conjunction_or_disjunction AND LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM supports_conjunction_or_disjunction AND LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM supports_conjunction_or_disjunction AND LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_conjunction_or_disjunction AND supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_conjunction_or_disjunction AND supports_condition_in_parens
+

+ +

+ + From here, we reduce by supports_conjunction : supports_conjunction_or_disjunction AND supports_condition_in_parens regardless of what token + comes next.
+ + (This takes us to 95) + + +

+
+ +

State 275

+ +

+ +
supports_disjunction:supports_conjunction_or_disjunction OR supports_condition_in_parens .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Shift AND SUPPORTS_SYM supports_condition_in_parens AND
Shift LPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property
Shift COLON SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_condition_in_parens AND supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens AND supports_condition_in_parens
Reduce to supports_conjunction by:
supports_conjunction : supports_condition_in_parens AND supports_condition_in_parens
SUPPORTS_SYM supports_conjunction
Reduce to supports_conjunction_or_disjunction by:
supports_conjunction_or_disjunction : supports_conjunction
SUPPORTS_SYM supports_conjunction_or_disjunction
Shift OR SUPPORTS_SYM supports_conjunction_or_disjunction OR
Shift LPAREN SUPPORTS_SYM supports_conjunction_or_disjunction OR LPAREN
Shift IDENT SUPPORTS_SYM supports_conjunction_or_disjunction OR LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM supports_conjunction_or_disjunction OR LPAREN property
Shift COLON SUPPORTS_SYM supports_conjunction_or_disjunction OR LPAREN property COLON
Shift IDENT SUPPORTS_SYM supports_conjunction_or_disjunction OR LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM supports_conjunction_or_disjunction OR LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM supports_conjunction_or_disjunction OR LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM supports_conjunction_or_disjunction OR LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM supports_conjunction_or_disjunction OR LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM supports_conjunction_or_disjunction OR LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM supports_conjunction_or_disjunction OR LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_conjunction_or_disjunction OR supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_conjunction_or_disjunction OR supports_condition_in_parens
+

+ +

+ + From here, we reduce by supports_disjunction : supports_conjunction_or_disjunction OR supports_condition_in_parens regardless of what token + comes next.
+ + (This takes us to 96) + + +

+
+ +

State 276

+ +

+ +
supports_conjunction:supports_condition_in_parens AND supports_condition_in_parens .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Shift AND SUPPORTS_SYM supports_condition_in_parens AND
Shift LPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property
Shift COLON SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON
Shift IDENT SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM supports_condition_in_parens AND LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM supports_condition_in_parens AND LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_condition_in_parens AND supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens AND supports_condition_in_parens
+

+ +

+ + From here, we reduce by supports_conjunction : supports_condition_in_parens AND supports_condition_in_parens regardless of what token + comes next.
+ + (This takes us to 95) + + +

+
+ +

State 277

+ +

+ +
supports_disjunction:supports_condition_in_parens OR supports_condition_in_parens .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens
Shift OR SUPPORTS_SYM supports_condition_in_parens OR
Shift LPAREN SUPPORTS_SYM supports_condition_in_parens OR LPAREN
Shift IDENT SUPPORTS_SYM supports_condition_in_parens OR LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM supports_condition_in_parens OR LPAREN property
Shift COLON SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON
Shift IDENT SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM supports_condition_in_parens OR LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM supports_condition_in_parens OR LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM supports_condition_in_parens OR LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM supports_condition_in_parens OR supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM supports_condition_in_parens OR supports_condition_in_parens
+

+ +

+ + From here, we reduce by supports_disjunction : supports_condition_in_parens OR supports_condition_in_parens regardless of what token + comes next.
+ + (This takes us to 96) + + +

+
+ +

State 278

+ +

+ +
supports_condition_in_parens:LPAREN supports_condition RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift LPAREN SUPPORTS_SYM LPAREN LPAREN
Shift IDENT SUPPORTS_SYM LPAREN LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN LPAREN property
Shift COLON SUPPORTS_SYM LPAREN LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN LPAREN declaration_internal RPAREN
Reduce to supports_declaration_condition by:
supports_declaration_condition : LPAREN declaration_internal RPAREN
SUPPORTS_SYM LPAREN supports_declaration_condition
Reduce to supports_condition_in_parens by:
supports_condition_in_parens : supports_declaration_condition
SUPPORTS_SYM LPAREN supports_condition_in_parens
Reduce to supports_condition by:
supports_condition : supports_condition_in_parens
SUPPORTS_SYM LPAREN supports_condition
Shift RPAREN SUPPORTS_SYM LPAREN supports_condition RPAREN
+

+ +

+ + From here, we reduce by supports_condition_in_parens : LPAREN supports_condition RPAREN regardless of what token + comes next.
+ + (This can take us to 91, 207, 211, 274, 275, 276 or 277) + + +

+
+ +

State 279

+ +

+ +
supports_declaration_condition:LPAREN declaration_internal RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN declaration_internal RPAREN
+

+ +

+ + From here, we reduce by supports_declaration_condition : LPAREN declaration_internal RPAREN regardless of what token + comes next.
+ + (This takes us to 93) + + +

+
+ +

State 280

+ +

+ +
supports_declaration_condition:LPAREN S declaration_internal . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift S SUPPORTS_SYM LPAREN S
Shift IDENT SUPPORTS_SYM LPAREN S IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN S property
Shift COLON SUPPORTS_SYM LPAREN S property COLON
Shift IDENT SUPPORTS_SYM LPAREN S property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN S property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN S property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN S property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN S property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN S declaration_internal
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 317
OtherError
+ +

+
+ +

State 281

+ +

+ +
keyframes_block:start_keyframes_block declarations RBRACE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_selectors
Shift LBRACE start_keyframes_rule keyframes_selectors LBRACE
Reduce to start_keyframes_block by:
start_keyframes_block : keyframes_selectors LBRACE
start_keyframes_rule start_keyframes_block
Shift SEMI start_keyframes_rule start_keyframes_block SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_keyframes_rule start_keyframes_block one_or_more_semis
Reduce to declarations by:
declarations : one_or_more_semis
start_keyframes_rule start_keyframes_block declarations
Shift RBRACE start_keyframes_rule start_keyframes_block declarations RBRACE
+

+ +

+ + From here, we reduce by keyframes_block : start_keyframes_block declarations RBRACE regardless of what token + comes next.
+ + (This takes us to 99) + + +

+
+ +

State 282

+ +

+ +
keyframes_selectors:keyframes_selector COMMA keyframes_selectors .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift KEYFRAMES_SYM KEYFRAMES_SYM
Shift IDENT KEYFRAMES_SYM IDENT
Shift LBRACE KEYFRAMES_SYM IDENT LBRACE
Reduce to start_keyframes_rule by:
start_keyframes_rule : KEYFRAMES_SYM IDENT LBRACE
start_keyframes_rule
Shift IDENT start_keyframes_rule IDENT
Reduce to keyframes_selector by:
keyframes_selector : IDENT
start_keyframes_rule keyframes_selector
Shift COMMA start_keyframes_rule keyframes_selector COMMA
Reduce to keyframes_selectors by:
keyframes_selectors :
start_keyframes_rule keyframes_selector COMMA keyframes_selectors
+

+ +

+ + From here, we reduce by keyframes_selectors : keyframes_selector COMMA keyframes_selectors regardless of what token + comes next.
+ + (This can take us to 101 or 282) + + +

+
+ +

State 283

+ +

+ +
declarations:declaration one_or_more_semis declarations .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift FONTFACE_SYM FONTFACE_SYM
Shift LBRACE FONTFACE_SYM LBRACE
Reduce to start_fontface_rule by:
start_fontface_rule : FONTFACE_SYM LBRACE
start_fontface_rule
Shift IDENT start_fontface_rule IDENT
Reduce to property by:
property : IDENT
start_fontface_rule property
Shift COLON start_fontface_rule property COLON
Shift IDENT start_fontface_rule property COLON IDENT
Reduce to ident by:
ident : IDENT
start_fontface_rule property COLON ident
Reduce to term by:
term : ident
start_fontface_rule property COLON term
Reduce to expr by:
expr : term
start_fontface_rule property COLON expr
Reduce to prio by:
prio :
start_fontface_rule property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
start_fontface_rule declaration_internal
Reduce to declaration by:
declaration : declaration_internal
start_fontface_rule declaration
Shift SEMI start_fontface_rule declaration SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_fontface_rule declaration one_or_more_semis
Shift SEMI start_fontface_rule declaration one_or_more_semis SEMI
Reduce to one_or_more_semis by:
one_or_more_semis : SEMI
start_fontface_rule declaration one_or_more_semis one_or_more_semis
Reduce to declarations by:
declarations : one_or_more_semis
start_fontface_rule declaration one_or_more_semis declarations
+

+ +

+ + From here, we reduce by declarations : declaration one_or_more_semis declarations regardless of what token + comes next.
+ + (This can take us to 106, 117, 214, 222 or 283) + + +

+
+ +

State 284

+ +

+ +
declaration_internal:property COLON expr . prio

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
+

+ +

+ + Action table:
+
Lookahead tokenAction
IMPORTANT_SYMShift and go to state 319
OtherReduce by prio :
(This takes us to 318)
+ +

+
+ +

State 285

+ +

+ +
declaration_internal:property COLON S . expr prio

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift S SUPPORTS_SYM LPAREN property COLON S
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 188
IDENTShift and go to state 59
HASHShift and go to state 187
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
URIShift and go to state 85
RESOLUTIONShift and go to state 170
VARIABLE_NAMEShift and go to state 181
CALC_SYMShift and go to state 186
UNICODE_RANGEShift and go to state 185
RATIOShift and go to state 196
OtherError
+ +

+
+ +

State 286

+ +

+ +
declaration_internal:property S COLON . expr prio
declaration_internal:property S COLON . S expr prio

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift S SUPPORTS_SYM LPAREN property S
Shift COLON SUPPORTS_SYM LPAREN property S COLON
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 188
IDENTShift and go to state 59
SShift and go to state 322
HASHShift and go to state 187
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
URIShift and go to state 85
RESOLUTIONShift and go to state 170
VARIABLE_NAMEShift and go to state 181
CALC_SYMShift and go to state 186
UNICODE_RANGEShift and go to state 185
RATIOShift and go to state 196
OtherError
+ +

+
+ +

State 287

+ +

+ +
attrib:LSQUARE ident_with_namespace EQUAL IDENT . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift EQUAL LSQUARE ident_with_namespace EQUAL
Shift IDENT LSQUARE ident_with_namespace EQUAL IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 323
OtherError
+ +

+
+ +

State 288

+ +

+ +
attrib:LSQUARE ident_with_namespace EQUAL STRING . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift EQUAL LSQUARE ident_with_namespace EQUAL
Shift STRING LSQUARE ident_with_namespace EQUAL STRING
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 324
OtherError
+ +

+
+ +

State 289

+ +

+ +
attrib:LSQUARE ident_with_namespace INCLUDES STRING . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift INCLUDES LSQUARE ident_with_namespace INCLUDES
Shift STRING LSQUARE ident_with_namespace INCLUDES STRING
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 325
OtherError
+ +

+
+ +

State 290

+ +

+ +
attrib:LSQUARE ident_with_namespace INCLUDES IDENT . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift INCLUDES LSQUARE ident_with_namespace INCLUDES
Shift IDENT LSQUARE ident_with_namespace INCLUDES IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 326
OtherError
+ +

+
+ +

State 291

+ +

+ +
attrib:LSQUARE ident_with_namespace DASHMATCH IDENT . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift DASHMATCH LSQUARE ident_with_namespace DASHMATCH
Shift IDENT LSQUARE ident_with_namespace DASHMATCH IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 327
OtherError
+ +

+
+ +

State 292

+ +

+ +
attrib:LSQUARE ident_with_namespace DASHMATCH STRING . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift DASHMATCH LSQUARE ident_with_namespace DASHMATCH
Shift STRING LSQUARE ident_with_namespace DASHMATCH STRING
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 328
OtherError
+ +

+
+ +

State 293

+ +

+ +
attrib:LSQUARE ident_with_namespace PREFIXMATCH IDENT . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift PREFIXMATCH LSQUARE ident_with_namespace PREFIXMATCH
Shift IDENT LSQUARE ident_with_namespace PREFIXMATCH IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 329
OtherError
+ +

+
+ +

State 294

+ +

+ +
attrib:LSQUARE ident_with_namespace PREFIXMATCH STRING . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift PREFIXMATCH LSQUARE ident_with_namespace PREFIXMATCH
Shift STRING LSQUARE ident_with_namespace PREFIXMATCH STRING
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 330
OtherError
+ +

+
+ +

State 295

+ +

+ +
attrib:LSQUARE ident_with_namespace SUFFIXMATCH IDENT . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift SUFFIXMATCH LSQUARE ident_with_namespace SUFFIXMATCH
Shift IDENT LSQUARE ident_with_namespace SUFFIXMATCH IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 331
OtherError
+ +

+
+ +

State 296

+ +

+ +
attrib:LSQUARE ident_with_namespace SUFFIXMATCH STRING . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift SUFFIXMATCH LSQUARE ident_with_namespace SUFFIXMATCH
Shift STRING LSQUARE ident_with_namespace SUFFIXMATCH STRING
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 332
OtherError
+ +

+
+ +

State 297

+ +

+ +
attrib:LSQUARE ident_with_namespace SUBSTRINGMATCH IDENT . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift SUBSTRINGMATCH LSQUARE ident_with_namespace SUBSTRINGMATCH
Shift IDENT LSQUARE ident_with_namespace SUBSTRINGMATCH IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 333
OtherError
+ +

+
+ +

State 298

+ +

+ +
attrib:LSQUARE ident_with_namespace SUBSTRINGMATCH STRING . RSQUARE

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift SUBSTRINGMATCH LSQUARE ident_with_namespace SUBSTRINGMATCH
Shift STRING LSQUARE ident_with_namespace SUBSTRINGMATCH STRING
+

+ +

+ + Action table:
+
Lookahead tokenAction
RSQUAREShift and go to state 334
OtherError
+ +

+
+ +

State 299

+ +

+ +
pseudo:COLON COLON MOZ_PSEUDO_ELEMENT optional_space . any_number_of_idents optional_space RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift COLON COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON COLON MOZ_PSEUDO_ELEMENT optional_space
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 306
OtherReduce by any_number_of_idents :
(This takes us to 335)
+ +

+
+ +

State 300

+ +

+ +
pseudo:COLON FUNCTION IDENT RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift FUNCTION COLON FUNCTION
Shift IDENT COLON FUNCTION IDENT
Shift RPAREN COLON FUNCTION IDENT RPAREN
+

+ +

+ + From here, we reduce by pseudo : COLON FUNCTION IDENT RPAREN regardless of what token + comes next.
+ + (This takes us to 44) + + +

+
+ +

State 301

+ +

+ +
pseudo:COLON NOT_PSEUDO_CLASS simple_selector RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift NOT_PSEUDO_CLASS COLON NOT_PSEUDO_CLASS
Shift IDENT COLON NOT_PSEUDO_CLASS IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
COLON NOT_PSEUDO_CLASS ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
COLON NOT_PSEUDO_CLASS element_name
Reduce to simple_selector by:
simple_selector : element_name
COLON NOT_PSEUDO_CLASS simple_selector
Shift RPAREN COLON NOT_PSEUDO_CLASS simple_selector RPAREN
+

+ +

+ + From here, we reduce by pseudo : COLON NOT_PSEUDO_CLASS simple_selector RPAREN regardless of what token + comes next.
+ + (This takes us to 44) + + +

+
+ +

State 302

+ +

+ +
simple_selectors:simple_selector COMMA . simple_selectors

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MATCHES_PSEUDO_CLASS COLON MATCHES_PSEUDO_CLASS
Shift IDENT COLON MATCHES_PSEUDO_CLASS IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
COLON MATCHES_PSEUDO_CLASS ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
COLON MATCHES_PSEUDO_CLASS element_name
Reduce to simple_selector by:
simple_selector : element_name
COLON MATCHES_PSEUDO_CLASS simple_selector
Shift COMMA COLON MATCHES_PSEUDO_CLASS simple_selector COMMA
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 37
STARShift and go to state 39
HASHShift and go to state 45
LSQUAREShift and go to state 47
COLONShift and go to state 48
"|"Shift and go to state 38
"."Shift and go to state 46
OtherError
+ +

+
+ +

State 303

+ +

+ +
pseudo:COLON MATCHES_PSEUDO_CLASS simple_selectors RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MATCHES_PSEUDO_CLASS COLON MATCHES_PSEUDO_CLASS
Shift IDENT COLON MATCHES_PSEUDO_CLASS IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
COLON MATCHES_PSEUDO_CLASS ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
COLON MATCHES_PSEUDO_CLASS element_name
Reduce to simple_selector by:
simple_selector : element_name
COLON MATCHES_PSEUDO_CLASS simple_selector
Reduce to simple_selectors by:
simple_selectors : simple_selector
COLON MATCHES_PSEUDO_CLASS simple_selectors
Shift RPAREN COLON MATCHES_PSEUDO_CLASS simple_selectors RPAREN
+

+ +

+ + From here, we reduce by pseudo : COLON MATCHES_PSEUDO_CLASS simple_selectors RPAREN regardless of what token + comes next.
+ + (This takes us to 44) + + +

+
+ +

State 304

+ +

+ +
pseudo:COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents . optional_space RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON MOZ_PSEUDO_ELEMENT optional_space
Reduce to any_number_of_idents by:
any_number_of_idents :
COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 163
OtherReduce by optional_space :
(This takes us to 337)
+ +

+
+ +

State 305

+ +

+ +
any_number_of_idents:multiple_idents .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON MOZ_PSEUDO_ELEMENT optional_space
Shift IDENT COLON MOZ_PSEUDO_ELEMENT optional_space IDENT
Reduce to multiple_idents by:
multiple_idents : IDENT
COLON MOZ_PSEUDO_ELEMENT optional_space multiple_idents
+

+ +

+ + From here, we reduce by any_number_of_idents : multiple_idents regardless of what token + comes next.
+ + (This can take us to 304 or 335) + + +

+
+ +

State 306

+ +

+ +
multiple_idents:IDENT .
multiple_idents:IDENT . COMMA multiple_idents

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON MOZ_PSEUDO_ELEMENT optional_space
Shift IDENT COLON MOZ_PSEUDO_ELEMENT optional_space IDENT
+

+ +

+ + Action table:
+
Lookahead tokenAction
COMMAShift and go to state 338
OtherReduce by multiple_idents : IDENT
(This can take us to 305 or 352)
+ +

+
+ +

State 307

+ +

+ +
medium:medium COMMA IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift IMPORT_SYM IMPORT_SYM
Shift STRING IMPORT_SYM STRING
Reduce to import_location by:
import_location : STRING
IMPORT_SYM import_location
Shift IDENT IMPORT_SYM import_location IDENT
Reduce to medium by:
medium : IDENT
IMPORT_SYM import_location medium
Shift COMMA IMPORT_SYM import_location medium COMMA
Shift IDENT IMPORT_SYM import_location medium COMMA IDENT
+

+ +

+ + From here, we reduce by medium : medium COMMA IDENT regardless of what token + comes next.
+ + (This takes us to 149) + + +

+
+ +

State 308

+ +

+ +
optional_and_exprs:optional_and_exprs AND media_expr .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Reduce to optional_only_or_not by:
optional_only_or_not :
MEDIA_SYM optional_only_or_not
Shift IDENT MEDIA_SYM optional_only_or_not IDENT
Reduce to media_type by:
media_type : IDENT
MEDIA_SYM optional_only_or_not media_type
Reduce to optional_and_exprs by:
optional_and_exprs :
MEDIA_SYM optional_only_or_not media_type optional_and_exprs
Shift AND MEDIA_SYM optional_only_or_not media_type optional_and_exprs AND
Shift LPAREN MEDIA_SYM optional_only_or_not media_type optional_and_exprs AND LPAREN
Reduce to optional_space by:
optional_space :
MEDIA_SYM optional_only_or_not media_type optional_and_exprs AND LPAREN optional_space
Shift IDENT MEDIA_SYM optional_only_or_not media_type optional_and_exprs AND LPAREN optional_space IDENT
Reduce to optional_space by:
optional_space :
MEDIA_SYM optional_only_or_not media_type optional_and_exprs AND LPAREN optional_space IDENT optional_space
Shift RPAREN MEDIA_SYM optional_only_or_not media_type optional_and_exprs AND LPAREN optional_space IDENT optional_space RPAREN
Reduce to media_expr by:
media_expr : LPAREN optional_space IDENT optional_space RPAREN
MEDIA_SYM optional_only_or_not media_type optional_and_exprs AND media_expr
+

+ +

+ + From here, we reduce by optional_and_exprs : optional_and_exprs AND media_expr regardless of what token + comes next.
+ + (This can take us to 161 or 254) + + +

+
+ +

State 309

+ +

+ +
media_expr:LPAREN optional_space IDENT optional_space . RPAREN
media_expr:LPAREN optional_space IDENT optional_space . COLON optional_space expr RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space
Shift IDENT MEDIA_SYM LPAREN optional_space IDENT
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space IDENT optional_space
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 339
COLONShift and go to state 340
OtherError
+ +

+
+ +

State 310

+ +

+ +
expr:term operator expr .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift IDENT start_document_query_pos FUNCTION IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION ident
Reduce to term by:
term : ident
start_document_query_pos FUNCTION term
Shift COMMA start_document_query_pos FUNCTION term COMMA
Reduce to operator by:
operator : COMMA
start_document_query_pos FUNCTION term operator
Shift IDENT start_document_query_pos FUNCTION term operator IDENT
Reduce to ident by:
ident : IDENT
start_document_query_pos FUNCTION term operator ident
Reduce to term by:
term : ident
start_document_query_pos FUNCTION term operator term
Reduce to expr by:
expr : term
start_document_query_pos FUNCTION term operator expr
+

+ +

+ + From here, we reduce by expr : term operator expr regardless of what token + comes next.
+ + (This can take us to 183, 262, 284, 310, 320, 321, 349 or 358) + + +

+
+ +

State 311

+ +

+ +
uranges:UNICODE_RANGE COMMA uranges .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift UNICODE_RANGE start_document_query_pos FUNCTION UNICODE_RANGE
Shift COMMA start_document_query_pos FUNCTION UNICODE_RANGE COMMA
Shift UNICODE_RANGE start_document_query_pos FUNCTION UNICODE_RANGE COMMA UNICODE_RANGE
Reduce to uranges by:
uranges : UNICODE_RANGE
start_document_query_pos FUNCTION UNICODE_RANGE COMMA uranges
+

+ +

+ + From here, we reduce by uranges : UNICODE_RANGE COMMA uranges regardless of what token + comes next.
+ + (This can take us to 182 or 311) + + +

+
+ +

State 312

+ +

+ +
calc:CALC_SYM calc_sum RPAREN . optional_space

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM calc_product
Reduce to calc_sum by:
calc_sum : calc_product
start_document_query_pos FUNCTION CALC_SYM calc_sum
Shift RPAREN start_document_query_pos FUNCTION CALC_SYM calc_sum RPAREN
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 163
OtherReduce by optional_space :
(This takes us to 341)
+ +

+
+ +

State 313

+ +

+ +
calc_sum:calc_product PLUS . calc_sum

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM calc_product
Shift PLUS start_document_query_pos FUNCTION CALC_SYM calc_product PLUS
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 272
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
OtherError
+ +

+
+ +

State 314

+ +

+ +
calc_sum:calc_product MINUS . calc_sum

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM calc_product
Shift MINUS start_document_query_pos FUNCTION CALC_SYM calc_product MINUS
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 272
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
OtherError
+ +

+
+ +

State 315

+ +

+ +
calc_product:calc_value optional_space . STAR calc_value
calc_product:calc_value optional_space . SLASH calc_value

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to optional_space by:
optional_space :
start_document_query_pos FUNCTION CALC_SYM calc_value optional_space
+

+ +

+ + Action table:
+
Lookahead tokenAction
STARShift and go to state 344
SLASHShift and go to state 345
OtherError
+ +

+
+ +

State 316

+ +

+ +
calc_value:LPAREN calc_sum . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift LPAREN start_document_query_pos FUNCTION CALC_SYM LPAREN
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM LPAREN NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM LPAREN numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM LPAREN calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM LPAREN calc_product
Reduce to calc_sum by:
calc_sum : calc_product
start_document_query_pos FUNCTION CALC_SYM LPAREN calc_sum
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 346
OtherError
+ +

+
+ +

State 317

+ +

+ +
supports_declaration_condition:LPAREN S declaration_internal RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift S SUPPORTS_SYM LPAREN S
Shift IDENT SUPPORTS_SYM LPAREN S IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN S property
Shift COLON SUPPORTS_SYM LPAREN S property COLON
Shift IDENT SUPPORTS_SYM LPAREN S property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN S property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN S property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN S property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN S property COLON expr prio
Reduce to declaration_internal by:
declaration_internal : property COLON expr prio
SUPPORTS_SYM LPAREN S declaration_internal
Shift RPAREN SUPPORTS_SYM LPAREN S declaration_internal RPAREN
+

+ +

+ + From here, we reduce by supports_declaration_condition : LPAREN S declaration_internal RPAREN regardless of what token + comes next.
+ + (This takes us to 93) + + +

+
+ +

State 318

+ +

+ +
declaration_internal:property COLON expr prio .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON expr prio
+

+ +

+ + From here, we reduce by declaration_internal : property COLON expr prio regardless of what token + comes next.
+ + (This can take us to 111, 209 or 280) + + +

+
+ +

State 319

+ +

+ +
prio:IMPORTANT_SYM .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift IDENT SUPPORTS_SYM LPAREN property COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON expr
Shift IMPORTANT_SYM SUPPORTS_SYM LPAREN property COLON expr IMPORTANT_SYM
+

+ +

+ + From here, we reduce by prio : IMPORTANT_SYM regardless of what token + comes next.
+ + (This can take us to 318, 347, 348 or 356) + + +

+
+ +

State 320

+ +

+ +
declaration_internal:property COLON S expr . prio

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift S SUPPORTS_SYM LPAREN property COLON S
Shift IDENT SUPPORTS_SYM LPAREN property COLON S IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON S ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON S term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON S expr
+

+ +

+ + Action table:
+
Lookahead tokenAction
IMPORTANT_SYMShift and go to state 319
OtherReduce by prio :
(This takes us to 347)
+ +

+
+ +

State 321

+ +

+ +
declaration_internal:property S COLON expr . prio

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift S SUPPORTS_SYM LPAREN property S
Shift COLON SUPPORTS_SYM LPAREN property S COLON
Shift IDENT SUPPORTS_SYM LPAREN property S COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property S COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property S COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property S COLON expr
+

+ +

+ + Action table:
+
Lookahead tokenAction
IMPORTANT_SYMShift and go to state 319
OtherReduce by prio :
(This takes us to 348)
+ +

+
+ +

State 322

+ +

+ +
declaration_internal:property S COLON S . expr prio

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift S SUPPORTS_SYM LPAREN property S
Shift COLON SUPPORTS_SYM LPAREN property S COLON
Shift S SUPPORTS_SYM LPAREN property S COLON S
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 188
IDENTShift and go to state 59
HASHShift and go to state 187
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
URIShift and go to state 85
RESOLUTIONShift and go to state 170
VARIABLE_NAMEShift and go to state 181
CALC_SYMShift and go to state 186
UNICODE_RANGEShift and go to state 185
RATIOShift and go to state 196
OtherError
+ +

+
+ +

State 323

+ +

+ +
attrib:LSQUARE ident_with_namespace EQUAL IDENT RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift EQUAL LSQUARE ident_with_namespace EQUAL
Shift IDENT LSQUARE ident_with_namespace EQUAL IDENT
Shift RSQUARE LSQUARE ident_with_namespace EQUAL IDENT RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace EQUAL IDENT RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 324

+ +

+ +
attrib:LSQUARE ident_with_namespace EQUAL STRING RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift EQUAL LSQUARE ident_with_namespace EQUAL
Shift STRING LSQUARE ident_with_namespace EQUAL STRING
Shift RSQUARE LSQUARE ident_with_namespace EQUAL STRING RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace EQUAL STRING RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 325

+ +

+ +
attrib:LSQUARE ident_with_namespace INCLUDES STRING RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift INCLUDES LSQUARE ident_with_namespace INCLUDES
Shift STRING LSQUARE ident_with_namespace INCLUDES STRING
Shift RSQUARE LSQUARE ident_with_namespace INCLUDES STRING RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace INCLUDES STRING RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 326

+ +

+ +
attrib:LSQUARE ident_with_namespace INCLUDES IDENT RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift INCLUDES LSQUARE ident_with_namespace INCLUDES
Shift IDENT LSQUARE ident_with_namespace INCLUDES IDENT
Shift RSQUARE LSQUARE ident_with_namespace INCLUDES IDENT RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace INCLUDES IDENT RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 327

+ +

+ +
attrib:LSQUARE ident_with_namespace DASHMATCH IDENT RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift DASHMATCH LSQUARE ident_with_namespace DASHMATCH
Shift IDENT LSQUARE ident_with_namespace DASHMATCH IDENT
Shift RSQUARE LSQUARE ident_with_namespace DASHMATCH IDENT RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace DASHMATCH IDENT RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 328

+ +

+ +
attrib:LSQUARE ident_with_namespace DASHMATCH STRING RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift DASHMATCH LSQUARE ident_with_namespace DASHMATCH
Shift STRING LSQUARE ident_with_namespace DASHMATCH STRING
Shift RSQUARE LSQUARE ident_with_namespace DASHMATCH STRING RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace DASHMATCH STRING RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 329

+ +

+ +
attrib:LSQUARE ident_with_namespace PREFIXMATCH IDENT RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift PREFIXMATCH LSQUARE ident_with_namespace PREFIXMATCH
Shift IDENT LSQUARE ident_with_namespace PREFIXMATCH IDENT
Shift RSQUARE LSQUARE ident_with_namespace PREFIXMATCH IDENT RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace PREFIXMATCH IDENT RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 330

+ +

+ +
attrib:LSQUARE ident_with_namespace PREFIXMATCH STRING RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift PREFIXMATCH LSQUARE ident_with_namespace PREFIXMATCH
Shift STRING LSQUARE ident_with_namespace PREFIXMATCH STRING
Shift RSQUARE LSQUARE ident_with_namespace PREFIXMATCH STRING RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace PREFIXMATCH STRING RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 331

+ +

+ +
attrib:LSQUARE ident_with_namespace SUFFIXMATCH IDENT RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift SUFFIXMATCH LSQUARE ident_with_namespace SUFFIXMATCH
Shift IDENT LSQUARE ident_with_namespace SUFFIXMATCH IDENT
Shift RSQUARE LSQUARE ident_with_namespace SUFFIXMATCH IDENT RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace SUFFIXMATCH IDENT RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 332

+ +

+ +
attrib:LSQUARE ident_with_namespace SUFFIXMATCH STRING RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift SUFFIXMATCH LSQUARE ident_with_namespace SUFFIXMATCH
Shift STRING LSQUARE ident_with_namespace SUFFIXMATCH STRING
Shift RSQUARE LSQUARE ident_with_namespace SUFFIXMATCH STRING RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace SUFFIXMATCH STRING RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 333

+ +

+ +
attrib:LSQUARE ident_with_namespace SUBSTRINGMATCH IDENT RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift SUBSTRINGMATCH LSQUARE ident_with_namespace SUBSTRINGMATCH
Shift IDENT LSQUARE ident_with_namespace SUBSTRINGMATCH IDENT
Shift RSQUARE LSQUARE ident_with_namespace SUBSTRINGMATCH IDENT RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace SUBSTRINGMATCH IDENT RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 334

+ +

+ +
attrib:LSQUARE ident_with_namespace SUBSTRINGMATCH STRING RSQUARE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift LSQUARE LSQUARE
Shift IDENT LSQUARE IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
LSQUARE ident_with_namespace
Shift SUBSTRINGMATCH LSQUARE ident_with_namespace SUBSTRINGMATCH
Shift STRING LSQUARE ident_with_namespace SUBSTRINGMATCH STRING
Shift RSQUARE LSQUARE ident_with_namespace SUBSTRINGMATCH STRING RSQUARE
+

+ +

+ + From here, we reduce by attrib : LSQUARE ident_with_namespace SUBSTRINGMATCH STRING RSQUARE regardless of what token + comes next.
+ + (This takes us to 43) + + +

+
+ +

State 335

+ +

+ +
pseudo:COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents . optional_space RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift COLON COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON COLON MOZ_PSEUDO_ELEMENT optional_space
Reduce to any_number_of_idents by:
any_number_of_idents :
COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 163
OtherReduce by optional_space :
(This takes us to 350)
+ +

+
+ +

State 336

+ +

+ +
simple_selectors:simple_selector COMMA simple_selectors .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MATCHES_PSEUDO_CLASS COLON MATCHES_PSEUDO_CLASS
Shift IDENT COLON MATCHES_PSEUDO_CLASS IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
COLON MATCHES_PSEUDO_CLASS ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
COLON MATCHES_PSEUDO_CLASS element_name
Reduce to simple_selector by:
simple_selector : element_name
COLON MATCHES_PSEUDO_CLASS simple_selector
Shift COMMA COLON MATCHES_PSEUDO_CLASS simple_selector COMMA
Shift IDENT COLON MATCHES_PSEUDO_CLASS simple_selector COMMA IDENT
Reduce to ident_with_namespace by:
ident_with_namespace : IDENT
COLON MATCHES_PSEUDO_CLASS simple_selector COMMA ident_with_namespace
Reduce to element_name by:
element_name : ident_with_namespace
COLON MATCHES_PSEUDO_CLASS simple_selector COMMA element_name
Reduce to simple_selector by:
simple_selector : element_name
COLON MATCHES_PSEUDO_CLASS simple_selector COMMA simple_selector
Reduce to simple_selectors by:
simple_selectors : simple_selector
COLON MATCHES_PSEUDO_CLASS simple_selector COMMA simple_selectors
+

+ +

+ + From here, we reduce by simple_selectors : simple_selector COMMA simple_selectors regardless of what token + comes next.
+ + (This can take us to 248 or 336) + + +

+
+ +

State 337

+ +

+ +
pseudo:COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON MOZ_PSEUDO_ELEMENT optional_space
Reduce to any_number_of_idents by:
any_number_of_idents :
COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents
Reduce to optional_space by:
optional_space :
COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 351
OtherError
+ +

+
+ +

State 338

+ +

+ +
multiple_idents:IDENT COMMA . multiple_idents

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON MOZ_PSEUDO_ELEMENT optional_space
Shift IDENT COLON MOZ_PSEUDO_ELEMENT optional_space IDENT
Shift COMMA COLON MOZ_PSEUDO_ELEMENT optional_space IDENT COMMA
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 306
OtherError
+ +

+
+ +

State 339

+ +

+ +
media_expr:LPAREN optional_space IDENT optional_space RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space
Shift IDENT MEDIA_SYM LPAREN optional_space IDENT
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space IDENT optional_space
Shift RPAREN MEDIA_SYM LPAREN optional_space IDENT optional_space RPAREN
+

+ +

+ + From here, we reduce by media_expr : LPAREN optional_space IDENT optional_space RPAREN regardless of what token + comes next.
+ + (This can take us to 72 or 308) + + +

+
+ +

State 340

+ +

+ +
media_expr:LPAREN optional_space IDENT optional_space COLON . optional_space expr RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space
Shift IDENT MEDIA_SYM LPAREN optional_space IDENT
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space IDENT optional_space
Shift COLON MEDIA_SYM LPAREN optional_space IDENT optional_space COLON
+

+ +

+ + Action table:
+
Lookahead tokenAction
SShift and go to state 163
OtherReduce by optional_space :
(This takes us to 353)
+ +

+
+ +

State 341

+ +

+ +
calc:CALC_SYM calc_sum RPAREN optional_space .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM calc_product
Reduce to calc_sum by:
calc_sum : calc_product
start_document_query_pos FUNCTION CALC_SYM calc_sum
Shift RPAREN start_document_query_pos FUNCTION CALC_SYM calc_sum RPAREN
Reduce to optional_space by:
optional_space :
start_document_query_pos FUNCTION CALC_SYM calc_sum RPAREN optional_space
+

+ +

+ + From here, we reduce by calc : CALC_SYM calc_sum RPAREN optional_space regardless of what token + comes next.
+ + (This takes us to 178) + + +

+
+ +

State 342

+ +

+ +
calc_sum:calc_product PLUS calc_sum .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM calc_product
Shift PLUS start_document_query_pos FUNCTION CALC_SYM calc_product PLUS
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM calc_product PLUS NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM calc_product PLUS numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_product PLUS calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM calc_product PLUS calc_product
Reduce to calc_sum by:
calc_sum : calc_product
start_document_query_pos FUNCTION CALC_SYM calc_product PLUS calc_sum
+

+ +

+ + From here, we reduce by calc_sum : calc_product PLUS calc_sum regardless of what token + comes next.
+ + (This can take us to 268, 316, 342 or 343) + + +

+
+ +

State 343

+ +

+ +
calc_sum:calc_product MINUS calc_sum .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM calc_product
Shift MINUS start_document_query_pos FUNCTION CALC_SYM calc_product MINUS
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM calc_product MINUS NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM calc_product MINUS numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_product MINUS calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM calc_product MINUS calc_product
Reduce to calc_sum by:
calc_sum : calc_product
start_document_query_pos FUNCTION CALC_SYM calc_product MINUS calc_sum
+

+ +

+ + From here, we reduce by calc_sum : calc_product MINUS calc_sum regardless of what token + comes next.
+ + (This can take us to 268, 316, 342 or 343) + + +

+
+ +

State 344

+ +

+ +
calc_product:calc_value optional_space STAR . calc_value

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to optional_space by:
optional_space :
start_document_query_pos FUNCTION CALC_SYM calc_value optional_space
Shift STAR start_document_query_pos FUNCTION CALC_SYM calc_value optional_space STAR
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 272
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
OtherError
+ +

+
+ +

State 345

+ +

+ +
calc_product:calc_value optional_space SLASH . calc_value

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to optional_space by:
optional_space :
start_document_query_pos FUNCTION CALC_SYM calc_value optional_space
Shift SLASH start_document_query_pos FUNCTION CALC_SYM calc_value optional_space SLASH
+

+ +

+ + Action table:
+
Lookahead tokenAction
LPARENShift and go to state 272
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
OtherError
+ +

+
+ +

State 346

+ +

+ +
calc_value:LPAREN calc_sum RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift LPAREN start_document_query_pos FUNCTION CALC_SYM LPAREN
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM LPAREN NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM LPAREN numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM LPAREN calc_value
Reduce to calc_product by:
calc_product : calc_value
start_document_query_pos FUNCTION CALC_SYM LPAREN calc_product
Reduce to calc_sum by:
calc_sum : calc_product
start_document_query_pos FUNCTION CALC_SYM LPAREN calc_sum
Shift RPAREN start_document_query_pos FUNCTION CALC_SYM LPAREN calc_sum RPAREN
+

+ +

+ + From here, we reduce by calc_value : LPAREN calc_sum RPAREN regardless of what token + comes next.
+ + (This can take us to 270, 354 or 355) + + +

+
+ +

State 347

+ +

+ +
declaration_internal:property COLON S expr prio .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift COLON SUPPORTS_SYM LPAREN property COLON
Shift S SUPPORTS_SYM LPAREN property COLON S
Shift IDENT SUPPORTS_SYM LPAREN property COLON S IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property COLON S ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property COLON S term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property COLON S expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property COLON S expr prio
+

+ +

+ + From here, we reduce by declaration_internal : property COLON S expr prio regardless of what token + comes next.
+ + (This can take us to 111, 209 or 280) + + +

+
+ +

State 348

+ +

+ +
declaration_internal:property S COLON expr prio .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift S SUPPORTS_SYM LPAREN property S
Shift COLON SUPPORTS_SYM LPAREN property S COLON
Shift IDENT SUPPORTS_SYM LPAREN property S COLON IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property S COLON ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property S COLON term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property S COLON expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property S COLON expr prio
+

+ +

+ + From here, we reduce by declaration_internal : property S COLON expr prio regardless of what token + comes next.
+ + (This can take us to 111, 209 or 280) + + +

+
+ +

State 349

+ +

+ +
declaration_internal:property S COLON S expr . prio

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift S SUPPORTS_SYM LPAREN property S
Shift COLON SUPPORTS_SYM LPAREN property S COLON
Shift S SUPPORTS_SYM LPAREN property S COLON S
Shift IDENT SUPPORTS_SYM LPAREN property S COLON S IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property S COLON S ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property S COLON S term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property S COLON S expr
+

+ +

+ + Action table:
+
Lookahead tokenAction
IMPORTANT_SYMShift and go to state 319
OtherReduce by prio :
(This takes us to 356)
+ +

+
+ +

State 350

+ +

+ +
pseudo:COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift COLON COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON COLON MOZ_PSEUDO_ELEMENT optional_space
Reduce to any_number_of_idents by:
any_number_of_idents :
COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents
Reduce to optional_space by:
optional_space :
COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 357
OtherError
+ +

+
+ +

State 351

+ +

+ +
pseudo:COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON MOZ_PSEUDO_ELEMENT optional_space
Reduce to any_number_of_idents by:
any_number_of_idents :
COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents
Reduce to optional_space by:
optional_space :
COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space
Shift RPAREN COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN
+

+ +

+ + From here, we reduce by pseudo : COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN regardless of what token + comes next.
+ + (This takes us to 44) + + +

+
+ +

State 352

+ +

+ +
multiple_idents:IDENT COMMA multiple_idents .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON MOZ_PSEUDO_ELEMENT optional_space
Shift IDENT COLON MOZ_PSEUDO_ELEMENT optional_space IDENT
Shift COMMA COLON MOZ_PSEUDO_ELEMENT optional_space IDENT COMMA
Shift IDENT COLON MOZ_PSEUDO_ELEMENT optional_space IDENT COMMA IDENT
Reduce to multiple_idents by:
multiple_idents : IDENT
COLON MOZ_PSEUDO_ELEMENT optional_space IDENT COMMA multiple_idents
+

+ +

+ + From here, we reduce by multiple_idents : IDENT COMMA multiple_idents regardless of what token + comes next.
+ + (This can take us to 305 or 352) + + +

+
+ +

State 353

+ +

+ +
media_expr:LPAREN optional_space IDENT optional_space COLON optional_space . expr RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space
Shift IDENT MEDIA_SYM LPAREN optional_space IDENT
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space IDENT optional_space
Shift COLON MEDIA_SYM LPAREN optional_space IDENT optional_space COLON
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space
+

+ +

+ + Action table:
+
Lookahead tokenAction
STRINGShift and go to state 188
IDENTShift and go to state 59
HASHShift and go to state 187
FUNCTIONShift and go to state 83
PLUSShift and go to state 198
NUMBERShift and go to state 190
MINUSShift and go to state 197
LENGTHShift and go to state 192
PERCENTAGEShift and go to state 191
ANGLEShift and go to state 193
TIMEShift and go to state 194
FREQShift and go to state 195
URIShift and go to state 85
RESOLUTIONShift and go to state 170
VARIABLE_NAMEShift and go to state 181
CALC_SYMShift and go to state 186
UNICODE_RANGEShift and go to state 185
RATIOShift and go to state 196
OtherError
+ +

+
+ +

State 354

+ +

+ +
calc_product:calc_value optional_space STAR calc_value .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to optional_space by:
optional_space :
start_document_query_pos FUNCTION CALC_SYM calc_value optional_space
Shift STAR start_document_query_pos FUNCTION CALC_SYM calc_value optional_space STAR
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM calc_value optional_space STAR NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM calc_value optional_space STAR numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value optional_space STAR calc_value
+

+ +

+ + From here, we reduce by calc_product : calc_value optional_space STAR calc_value regardless of what token + comes next.
+ + (This takes us to 269) + + +

+
+ +

State 355

+ +

+ +
calc_product:calc_value optional_space SLASH calc_value .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift DOCUMENT_QUERY_SYM DOCUMENT_QUERY_SYM
Reduce to start_document_query_pos by:
start_document_query_pos : DOCUMENT_QUERY_SYM
start_document_query_pos
Shift FUNCTION start_document_query_pos FUNCTION
Shift CALC_SYM start_document_query_pos FUNCTION CALC_SYM
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value
Reduce to optional_space by:
optional_space :
start_document_query_pos FUNCTION CALC_SYM calc_value optional_space
Shift SLASH start_document_query_pos FUNCTION CALC_SYM calc_value optional_space SLASH
Shift NUMBER start_document_query_pos FUNCTION CALC_SYM calc_value optional_space SLASH NUMBER
Reduce to numeric by:
numeric : NUMBER
start_document_query_pos FUNCTION CALC_SYM calc_value optional_space SLASH numeric
Reduce to calc_value by:
calc_value : numeric
start_document_query_pos FUNCTION CALC_SYM calc_value optional_space SLASH calc_value
+

+ +

+ + From here, we reduce by calc_product : calc_value optional_space SLASH calc_value regardless of what token + comes next.
+ + (This takes us to 269) + + +

+
+ +

State 356

+ +

+ +
declaration_internal:property S COLON S expr prio .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift SUPPORTS_SYM SUPPORTS_SYM
Shift LPAREN SUPPORTS_SYM LPAREN
Shift IDENT SUPPORTS_SYM LPAREN IDENT
Reduce to property by:
property : IDENT
SUPPORTS_SYM LPAREN property
Shift S SUPPORTS_SYM LPAREN property S
Shift COLON SUPPORTS_SYM LPAREN property S COLON
Shift S SUPPORTS_SYM LPAREN property S COLON S
Shift IDENT SUPPORTS_SYM LPAREN property S COLON S IDENT
Reduce to ident by:
ident : IDENT
SUPPORTS_SYM LPAREN property S COLON S ident
Reduce to term by:
term : ident
SUPPORTS_SYM LPAREN property S COLON S term
Reduce to expr by:
expr : term
SUPPORTS_SYM LPAREN property S COLON S expr
Reduce to prio by:
prio :
SUPPORTS_SYM LPAREN property S COLON S expr prio
+

+ +

+ + From here, we reduce by declaration_internal : property S COLON S expr prio regardless of what token + comes next.
+ + (This can take us to 111, 209 or 280) + + +

+
+ +

State 357

+ +

+ +
pseudo:COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift COLON COLON
Shift COLON COLON COLON
Shift MOZ_PSEUDO_ELEMENT COLON COLON MOZ_PSEUDO_ELEMENT
Reduce to optional_space by:
optional_space :
COLON COLON MOZ_PSEUDO_ELEMENT optional_space
Reduce to any_number_of_idents by:
any_number_of_idents :
COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents
Reduce to optional_space by:
optional_space :
COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space
Shift RPAREN COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN
+

+ +

+ + From here, we reduce by pseudo : COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN regardless of what token + comes next.
+ + (This takes us to 44) + + +

+
+ +

State 358

+ +

+ +
media_expr:LPAREN optional_space IDENT optional_space COLON optional_space expr . RPAREN

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space
Shift IDENT MEDIA_SYM LPAREN optional_space IDENT
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space IDENT optional_space
Shift COLON MEDIA_SYM LPAREN optional_space IDENT optional_space COLON
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space
Shift IDENT MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space IDENT
Reduce to ident by:
ident : IDENT
MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space ident
Reduce to term by:
term : ident
MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space term
Reduce to expr by:
expr : term
MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space expr
+

+ +

+ + Action table:
+
Lookahead tokenAction
RPARENShift and go to state 359
OtherError
+ +

+
+ +

State 359

+ +

+ +
media_expr:LPAREN optional_space IDENT optional_space COLON optional_space expr RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Shift MEDIA_SYM MEDIA_SYM
Shift LPAREN MEDIA_SYM LPAREN
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space
Shift IDENT MEDIA_SYM LPAREN optional_space IDENT
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space IDENT optional_space
Shift COLON MEDIA_SYM LPAREN optional_space IDENT optional_space COLON
Reduce to optional_space by:
optional_space :
MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space
Shift IDENT MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space IDENT
Reduce to ident by:
ident : IDENT
MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space ident
Reduce to term by:
term : ident
MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space term
Reduce to expr by:
expr : term
MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space expr
Shift RPAREN MEDIA_SYM LPAREN optional_space IDENT optional_space COLON optional_space expr RPAREN
+

+ +

+ + From here, we reduce by media_expr : LPAREN optional_space IDENT optional_space COLON optional_space expr RPAREN regardless of what token + comes next.
+ + (This can take us to 72 or 308) + + +

+
+ + + + diff --git a/test/regress/csspool.out b/test/regress/csspool.out new file mode 100644 index 00000000..030723e3 --- /dev/null +++ b/test/regress/csspool.out @@ -0,0 +1,125 @@ +Parsing grammar file... +Generating and resolving LALR states... +Creating parser file... + +Warning: Reduce/reduce conflict on $end, after the following input: +charset + +It is possible to reduce by either of these rules: +csspool.y:31: stylesheet +... +csspool.y:35:  | charset +csspool.y:31: stylesheet +... +csspool.y:39:  | + +Warning: Reduce/reduce conflict on $end, after the following input: +import + +It is possible to reduce by either of these rules: +csspool.y:31: stylesheet +... +csspool.y:36:  | import +csspool.y:31: stylesheet +... +csspool.y:39:  | + +Warning: Reduce/reduce conflict on $end, after the following input: +namespace + +It is possible to reduce by either of these rules: +csspool.y:31: stylesheet +... +csspool.y:37:  | namespace +csspool.y:31: stylesheet +... +csspool.y:39:  | + +Warning: Shift/reduce conflict on SEMI, after the following input: +start_fontface_rule SEMI + +The following rules direct me to shift: +csspool.y:508: one_or_more_semis + : SEMI +csspool.y:508: one_or_more_semis +... +csspool.y:510:  | SEMI one_or_more_semis +The following rule directs me to reduce: +csspool.y:508: one_or_more_semis + : SEMI + +After shifting SEMI, one path to a successful parse would be: +(reduce to one_or_more_semis) (reduce to one_or_more_semis) (reduce to declarations) RBRACE (reduce to fontface_rule) (reduce to body) (reduce to stylesheet) (reduce to document) + +After reducing to one_or_more_semis, one path to a successful parse would be: +SEMI (reduce to one_or_more_semis) (reduce to declarations) (reduce to declarations) RBRACE (reduce to fontface_rule) (reduce to body) (reduce to stylesheet) (reduce to document) + +Warning: Shift/reduce conflict on S, after the following input: +COLON MOZ_PSEUDO_ELEMENT + +The following rule directs me to shift: +csspool.y:94: optional_space + : S { result = val[0] } +The following rule directs me to reduce: +csspool.y:94: optional_space +... +csspool.y:96:  | { result = nil } + +After shifting S, one path to a successful parse would be: +(reduce to optional_space) (reduce to any_number_of_idents) (reduce to optional_space) RPAREN (reduce to pseudo) (reduce to hcap) (reduce to simple_selector) (reduce to selector) (reduce to selectors) LBRACE (reduce to start_selector) RBRACE (reduce to ruleset) (reduce to body) (reduce to stylesheet) (reduce to document) + +After reducing to optional_space, one path to a successful parse would be: +S (reduce to optional_space) RPAREN (reduce to pseudo) (reduce to hcap) (reduce to simple_selector) (reduce to selector) (reduce to selectors) LBRACE (reduce to start_selector) RBRACE (reduce to ruleset) (reduce to body) (reduce to stylesheet) (reduce to document) + +Warning: Shift/reduce conflict on COMMA, after the following input: +start_document_query_pos FUNCTION UNICODE_RANGE + +The following rule directs me to shift: +csspool.y:590: uranges + : UNICODE_RANGE COMMA uranges +The following rule directs me to reduce: +csspool.y:590: uranges +... +csspool.y:592:  | UNICODE_RANGE + +After shifting COMMA, one path to a successful parse would be: +UNICODE_RANGE (reduce to uranges) (reduce to uranges) (reduce to term) (reduce to expr) RPAREN (reduce to function) (reduce to url_match_fn) (reduce to url_match_fns) LBRACE (reduce to start_document_query) RBRACE (reduce to document_query) (reduce to conditional_rule) (reduce to body) (reduce to stylesheet) (reduce to document) + +After reducing to uranges, one path to a successful parse would be: +COMMA (reduce to operator) IDENT (reduce to ident) (reduce to term) (reduce to expr) (reduce to expr) RPAREN (reduce to function) (reduce to url_match_fn) (reduce to url_match_fns) LBRACE (reduce to start_document_query) RBRACE (reduce to document_query) (reduce to conditional_rule) (reduce to body) (reduce to stylesheet) (reduce to document) + +Warning: Shift/reduce conflict on S, after the following input: +COLON COLON MOZ_PSEUDO_ELEMENT + +The following rule directs me to shift: +csspool.y:94: optional_space + : S { result = val[0] } +The following rule directs me to reduce: +csspool.y:94: optional_space +... +csspool.y:96:  | { result = nil } + +After shifting S, one path to a successful parse would be: +(reduce to optional_space) (reduce to any_number_of_idents) (reduce to optional_space) RPAREN (reduce to pseudo) (reduce to hcap) (reduce to simple_selector) (reduce to selector) (reduce to selectors) LBRACE (reduce to start_selector) RBRACE (reduce to ruleset) (reduce to body) (reduce to stylesheet) (reduce to document) + +After reducing to optional_space, one path to a successful parse would be: +S (reduce to optional_space) RPAREN (reduce to pseudo) (reduce to hcap) (reduce to simple_selector) (reduce to selector) (reduce to selectors) LBRACE (reduce to start_selector) RBRACE (reduce to ruleset) (reduce to body) (reduce to stylesheet) (reduce to document) + +Warning: Shift/reduce conflict on S, after the following input: +start_document_query_pos FUNCTION CALC_SYM function + +The following rule directs me to shift: +csspool.y:567: function + : function S { result = val.first } +The following rule directs me to reduce: +csspool.y:610: calc_value +... +csspool.y:612:  | function { result = val.join('') } # for var() variable references + +After shifting S, one path to a successful parse would be: +(reduce to function) (reduce to calc_value) (reduce to calc_product) (reduce to calc_sum) RPAREN (reduce to optional_space) (reduce to calc) (reduce to term) (reduce to expr) RPAREN (reduce to function) (reduce to url_match_fn) (reduce to url_match_fns) LBRACE (reduce to start_document_query) RBRACE (reduce to document_query) (reduce to conditional_rule) (reduce to body) (reduce to stylesheet) (reduce to document) + +After reducing to calc_value, one path to a successful parse would be: +S (reduce to optional_space) STAR NUMBER (reduce to numeric) (reduce to calc_value) (reduce to calc_product) (reduce to calc_sum) RPAREN (reduce to optional_space) (reduce to calc) (reduce to term) (reduce to expr) RPAREN (reduce to function) (reduce to url_match_fn) (reduce to url_match_fns) LBRACE (reduce to start_document_query) RBRACE (reduce to document_query) (reduce to conditional_rule) (reduce to body) (reduce to stylesheet) (reduce to document) + +5 shift/reduce conflicts, 3 reduce/reduce conflicts diff --git a/test/regress/csspool.rb b/test/regress/csspool.rb new file mode 100644 index 00000000..1ca09e0d --- /dev/null +++ b/test/regress/csspool.rb @@ -0,0 +1,2185 @@ +# +# DO NOT MODIFY!!!! +# This file was automatically generated by Racc 2.0.0.dev +# (codename: Mecha Oishii) from Racc grammar file "csspool.y". +# + +require 'racc/parser.rb' +module CSSPool + module CSS + class Parser < Racc::Parser + +module_eval(<<'...end csspool.y/module_eval...', 'csspool.y', 670) + +def numeric thing + thing = thing.gsub(/[^\d.]/, '') + Integer(thing) rescue Float(thing) +end + +def interpret_identifier s + interpret_escapes s +end + +def interpret_uri s + interpret_escapes s.match(/^url\((.*)\)$/mui)[1].strip.match(/^(['"]?)((?:\\.|.)*)\1$/mu)[2] +end + +def interpret_string_no_quote s + interpret_escapes s.match(/^(.*)\)$/mu)[1].strip.match(/^(['"]?)((?:\\.|.)*)\1$/mu)[2] +end + +def interpret_string s + interpret_escapes s.match(/^(['"])((?:\\.|.)*)\1$/mu)[2] +end + +def interpret_escapes s + token_exp = /\\(?:([0-9a-fA-F]{1,6}(?:\r\n|\s)?)|(.))/mu + return s.gsub(token_exp) do |escape_sequence| + if !$1.nil? + code = $1.chomp.to_i 16 + code = 0xFFFD if code > 0x10FFFF + next [code].pack('U') + end + next '' if $2 == "\n" + next $2 + end +end + +# override racc's on_error so we can have context in our error messages +def on_error(t, val, vstack) + errcontext = (@ss.pre_match[-10..-1] || @ss.pre_match) + + @ss.matched + @ss.post_match[0..9] + line_number = @ss.pre_match.lines.count + raise ParseError, sprintf("parse error on value %s (%s) " + + "on line %s around \"%s\"", + val.inspect, token_to_str(t) || '?', + line_number, errcontext) +end + +def before_pos(val) + # don't include leading whitespace + return current_pos - val.last.length + val.last[/\A\s*/].size +end + +def after_pos(val) + # don't include trailing whitespace + return current_pos - val.last[/\s*\z/].size +end + +# charpos will work with multibyte strings but is not available until ruby 2 +def current_pos + @ss.respond_to?('charpos') ? @ss.charpos : @ss.pos +end +...end csspool.y/module_eval... +##### State transition tables begin ### + +racc_action_table = [ +9, 10, 137, 129, 37, 31, 55, 139, 130, 39, 45, 47, 45, 47, 123, +9, 10, 103, 3, 37, 31, 98, 229, 103, 39, 45, 47, 230, 124, 125, +224, 20, 113, 56, 37, 31, 23, 114, 104, 39, 45, 47, 245, 27, 104, +11, 20, 126, 48, 25, 48, 23, 242, 29, 138, 244, 38, 46, 27, 46, +11, 108, 113, 48, 25, 9, 10, 114, 29, 37, 31, 38, 46, 223, 39, +45, 47, 49, 48, 115, 9, 10, 108, 113, 37, 31, 38, 46, 114, 39, +45, 47, 55, 339, 243, 155, 20, 108, 113, 37, 31, 23, 107, 114, 39, +45, 47, 231, 27, 115, 11, 20, 232, 48, 25, 55, 23, 59, 29, 56, +344, 38, 46, 27, 340, 11, 20, 53, 48, 25, 115, 23, 345, 29, 37, +31, 38, 46, 27, 39, 45, 47, 56, 48, 25, 115, - +28, 105, 29, 37, 31, 38, 46, 116, 39, 45, 47, 250, 75, 120, 251, +20, 108, 113, 37, 31, 23, 118, 114, 39, 45, 47, 121, 27, 74, 73, +20, 313, 48, 25, 314, 23, 128, 29, 108, 113, 38, 46, 27, 215, 114, +20, 131, 48, 25, 75, 23, 136, 29, 37, 64, 38, 46, 27, 39, 45, +47, 92, 48, 25, 115, 74, 73, 29, 37, 31, 38, 46, 77, 39, 45, +47, 148, 94, 103, 156, 20, - +89, 83, 37, 31, 23, 115, 87, 39, 45, 47, 160, 27, 85, 153, 20, +151, 48, 25, 104, 23, 84, 29, 157, 158, 38, 46, 27, 163, 252, 20, +151, 48, 25, 201, 23, 164, 29, 37, 31, 38, 46, 27, 39, 45, 47, +203, 48, 25, 188, 202, 59, 29, 37, 165, 38, 46, 187, 39, 45, 47, +201, 204, 166, 184, 83, 288, 198, 287, 190, 197, 192, 191, 193, 194, 195, +85, 202, 37, 45, 47, 37, 48, 39, 45, 47, 39, 45, 47, 167, 38, +46, 168, 83, 170, 113, 210, 48, 181, 186, 114, 185, 196, 37, 85, 38, +46, 92, 39, 45, 47, 203, 84, 150, 152, 151, 289, 48, 290, 292, 163, +291, 48, 94, -33, 48, 46, 204, 169, 199, 38, 46, 37, 38, 46, 200, - +33, 39, 45, 47, 92, 188, 115, 59, 294, 258, 293, 48, 296, 187, 295, +298, 260, 297, 212, 38, 46, 83, 216, 198, 259, 190, 197, 192, 191, 193, +194, 195, 85, 45, 47, 45, 47, 45, 47, 217, 48, 218, 219, 188, 108, +59, 285, 108, 38, 46, 170, 187, 225, 226, 181, 186, 233, 185, 196, 83, +129, 198, 234, 190, 197, 192, 191, 193, 194, 195, 85, 48, 163, 48, 255, +48, 256, 155, 263, 169, 46, 188, 46, 59, 46, 264, 168, 265, 170, 187, +266, 92, 181, 186, 92, 185, 196, 83, 92, 198, 92, 190, 197, 192, 191, +193, 194, 195, 85, 198, 278, 190, 197, 192, 191, 193, 194, 195, 279, 188, +281, 59, 241, 235, 236, 237, 170, 187, 286, 229, 181, 186, 231, 185, 196, +83, 163, 198, 300, 190, 197, 192, 191, 193, 194, 195, 85, 301, 302, 238, +239, 240, 303, 306, 307, 255, 141, 188, 75, 59, 322, 163, 185, 168, 170, +187, 312, 317, 181, 186, 143, 185, 196, 83, 319, 198, 323, 190, 197, 192, +191, 193, 194, 195, 85, 324, 325, 145, 326, 327, 328, 329, 330, 331, 144, +188, 146, 59, 147, 332, 142, 333, 170, 187, 334, 306, 181, 186, 163, 185, +196, 83, 338, 198, 163, 190, 197, 192, 191, 193, 194, 195, 85, 346, 319, +319, 163, 351, 306, 163, 319, 357, 359, 188, nil, 59, nil, nil, nil, nil, +170, 187, nil, nil, 181, 186, nil, 185, 196, 83, nil, 198, nil, 190, 197, +192, 191, 193, 194, 195, 85, 272, nil, 83, nil, 198, nil, 190, 197, 192, +191, 193, 194, 195, nil, nil, nil, nil, 170, nil, nil, nil, 181, 186, nil, +185, 196, 272, nil, 83, nil, 198, nil, 190, 197, 192, 191, 193, 194, 195, +272, nil, 83, nil, 198, nil, 190, 197, 192, 191, 193, 194, 195, 272, nil, +83, nil, 198, nil, 190, 197, 192, 191, 193, 194, 195, 272, nil, 83, nil, +198, nil, 190, 197, 192, 191, 193, 194, 195, 272, nil, 83, nil, 198, nil, +190, 197, 192, 191, 193, 194, 195] + +racc_action_check = [ +2, 2, 47, 38, 2, 2, 10, 47, 38, 2, 2, 2, 35, 35, 34, +5, 5, 26, 1, 5, 5, 26, 128, 217, 5, 5, 5, 128, 34, 34, +112, 2, 210, 10, 31, 31, 2, 210, 26, 31, 31, 31, 143, 2, 217, +2, 5, 34, 2, 2, 35, 5, 142, 2, 47, 143, 2, 2, 5, 35, +5, 110, 110, 5, 5, 6, 6, 110, 5, 6, 6, 5, 5, 112, 6, +6, 6, 3, 31, 210, 7, 7, 221, 221, 7, 7, 31, 31, 221, 7, +7, 7, 58, 309, 142, 58, 6, 28, 28, 12, 12, 6, 28, 28, 12, +12, 12, 131, 6, 110, 6, 7, 131, 6, 6, 11, 7, 11, 6, 58, +315, 6, 6, 7, 309, 7, 12, 9, 7, 7, 221, 12, 315, 7, 13, +13, 7, 7, 12, 13, 13, 13, 11, 12, 12, 28, 20, 27, 12, 14, +14, 12, 12, 29, 14, 14, 14, 149, 20, 32, 149, 13, 30, 30, 15, +15, 13, 30, 30, 15, 15, 15, 33, 13, 20, 20, 14, 269, 13, 13, +269, 14, 37, 13, 100, 100, 13, 13, 14, 100, 100, 15, 39, 14, 14, +157, 15, 46, 14, 19, 19, 14, 14, 15, 19, 19, 19, 25, 15, 15, +30, 157, 157, 15, 21, 21, 15, 15, 21, 21, 21, 21, 53, 25, 99, +67, 19, 99, 22, 24, 24, 19, 100, 24, 24, 24, 24, 71, 19, 22, +57, 21, 57, 19, 19, 99, 21, 22, 19, 70, 70, 19, 19, 21, 75, +154, 24, 154, 21, 21, 90, 24, 76, 21, 64, 64, 21, 21, 24, 64, +64, 64, 91, 24, 24, 83, 90, 83, 24, 121, 78, 24, 24, 83, 121, +121, 121, 206, 91, 79, 83, 83, 235, 83, 235, 83, 83, 83, 83, 83, +83, 83, 83, 206, 122, 41, 41, 144, 64, 122, 122, 122, 144, 144, 144, +80, 64, 64, 81, 166, 83, 92, 92, 121, 83, 83, 92, 83, 83, 146, +166, 121, 121, 92, 146, 146, 146, 207, 166, 54, 54, 54, 236, 41, 236, +237, 270, 237, 122, 92, 270, 144, 41, 207, 82, 86, 122, 122, 302, 144, +144, 88, 270, 302, 302, 302, 94, 171, 92, 171, 238, 171, 238, 146, 239, +171, 239, 240, 171, 240, 97, 146, 146, 171, 101, 171, 171, 171, 171, 171, +171, 171, 171, 171, 171, 42, 42, 43, 43, 44, 44, 102, 302, 105, 106, +223, 108, 223, 223, 109, 302, 302, 171, 223, 114, 117, 171, 171, 137, 171, +171, 223, 138, 223, 139, 223, 223, 223, 223, 223, 223, 223, 223, 42, 147, +43, 161, 44, 162, 172, 175, 176, 42, 261, 43, 261, 44, 177, 179, 183, +223, 261, 185, 201, 223, 223, 202, 223, 223, 261, 203, 261, 204, 261, 261, +261, 261, 261, 261, 261, 261, 189, 208, 189, 189, 189, 189, 189, 189, 189, +209, 285, 214, 285, 140, 140, 140, 140, 261, 285, 224, 233, 261, 261, 234, +261, 261, 285, 243, 285, 245, 285, 285, 285, 285, 285, 285, 285, 285, 246, +247, 140, 140, 140, 248, 249, 251, 254, 48, 286, 255, 286, 286, 256, 266, +267, 285, 286, 268, 280, 285, 285, 48, 285, 285, 286, 284, 286, 287, 286, +286, 286, 286, 286, 286, 286, 286, 288, 289, 48, 290, 291, 292, 293, 294, +295, 48, 322, 48, 322, 48, 296, 48, 297, 286, 322, 298, 299, 286, 286, +304, 286, 286, 322, 306, 322, 312, 322, 322, 322, 322, 322, 322, 322, 322, +316, 320, 321, 335, 337, 338, 340, 349, 350, 358, 353, nil, 353, nil, nil, +nil, nil, 322, 353, nil, nil, 322, 322, nil, 322, 322, 353, nil, 353, nil, +353, 353, 353, 353, 353, 353, 353, 353, 186, nil, 186, nil, 186, nil, 186, +186, 186, 186, 186, 186, 186, nil, nil, nil, nil, 353, nil, nil, nil, 353, +353, nil, 353, 353, 272, nil, 272, nil, 272, nil, 272, 272, 272, 272, 272, +272, 272, 313, nil, 313, nil, 313, nil, 313, 313, 313, 313, 313, 313, 313, +314, nil, 314, nil, 314, nil, 314, 314, 314, 314, 314, 314, 314, 344, nil, +344, nil, 344, nil, 344, 344, 344, 344, 344, 344, 344, 345, nil, 345, nil, +345, nil, 345, 345, 345, 345, 345, 345, 345] + +racc_action_pointer = [nil, 18, - +2, 77, nil, 13, 63, 78, nil, 123, 2, 111, 93, 128, 143, 158, nil, +nil, nil, 193, 140, 208, 208, nil, 223, 189, 11, 141, 92, 144, 157, 28, +150, 164, 7, 0, nil, 124, -3, 134, nil, 293, 383, 385, 387, nil, 191, - +4, 512, nil, nil, nil, nil, 217, 334, nil, nil, 235, 88, nil, nil, nil, +nil, nil, 258, nil, nil, 215, nil, nil, 241, 231, nil, nil, nil, 247, 252, +nil, 271, 281, 308, 311, 347, 271, nil, nil, 345, nil, 352, nil, 224, 236, +315, nil, 348, nil, nil, 370, nil, 218, 179, 375, 393, nil, nil, 394, 394, +nil, 401, 404, 56, nil, 23, nil, 408, nil, nil, 405, nil, nil, nil, 273, +298, nil, nil, nil, nil, nil, 16, nil, nil, 101, nil, nil, nil, nil, nil, +360, 416, 366, 470, nil, 46, 36, 301, nil, 323, 427, nil, 152, nil, nil, +nil, nil, 250, nil, nil, 177, nil, nil, nil, 400, 432, nil, nil, nil, 299, +nil, nil, nil, nil, 363, 432, nil, nil, 433, 434, 440, nil, 441, nil, nil, +nil, 430, nil, 444, 605, nil, nil, 449, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, 435, 438, 442, 444, nil, 251, 301, 453, 461, 26, nil, +nil, nil, 472, nil, nil, 17, nil, nil, nil, 77, nil, 401, 440, nil, nil, +nil, nil, nil, nil, nil, nil, 485, 488, 288, 338, 341, 366, 370, 373, nil, +nil, 491, nil, 481, 490, 502, 495, 509, nil, 510, nil, nil, 481, 502, 516, +nil, nil, nil, nil, 439, nil, nil, nil, nil, 468, 518, 509, 155, 339, nil, +631, nil, nil, nil, nil, nil, nil, nil, 510, nil, nil, nil, 504, 477, 515, +524, 533, 534, 536, 537, 538, 539, 540, 541, 547, 549, 552, 561, nil, nil, +352, nil, 563, nil, 566, nil, nil, 74, nil, nil, 569, 644, 657, 109, 566, +nil, nil, nil, 554, 555, 553, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, 581, nil, 570, 584, nil, 584, nil, nil, nil, 670, 683, nil, +nil, nil, 560, 574, nil, nil, 591, nil, nil, nil, nil, 575, nil] + +racc_action_default = [-1, -229, -10, -229, -2, -6, -7, -8, -9, -229, -229, -229, -41, -42, -43, -44, -45, -46, -47, -33, -23, -229, -229, -55, -229, -229, -89, -229, -229, -229, -229, -229, -229, -103, -105, -111, -112, -115, -229, -120, -119, -124, -125, -126, -127, -132, -229, -229, -229, 360, -3, -4, -5, -229, -229, -15, -16, -229, -229, -228, -37, -38, -39, -40, -32, -48, -49, -229, -99, -21, -229, -229, -35, -26, -27, -33, -229, -53, -229, -57, -58, -59, -60, -229, -198, -214, -229, -62, -229, -64, -65, -66, -229, -71, -229, -73, -74, -229, -82, -85, -229, -229, -91, -92, -93, -229, -229, -95, -160, -165, -166, -167, -229, -174, -229, -176, -96, -229, -98, -100, -101, -229, -229, -106, -107, -108, -109, -110, -229, -117, -121, -229, -128, -129, -130, -131, -133, -115, -229, -229, -229, -147, -229, -229, -229, -152, -229, -33, -11, -229, -13, -14, -20, -18, -229, -227, -50, -28, -51, -35, -29, -25, -229, -32, -52, -54, -229, -197, -194, -213, -36, -182, -183, -184, -185, -186, -187, -188, -189, -190, -191, -192, -193, -229, -196, -200, -229, -212, -216, -229, -218, -219, -220, -221, -222, -223, -224, -225, -226, -61, -63, -229, -229, -229, -229, -67, -68, -69, -229, -229, -229, -72, -81, -84, -229, -87, -88, -89, -83, -94, -161, -164, -163, -229, -229, -175, -97, -102, -104, -116, -123, -118, -122, -229, -229, -229, -229, -229, -229, -229, -229, -146, -148, -33, -149, -229, -229, -114, -229, -156, -12, -229, -17, -22, -24, -229, -33, -56, -177, -178, -179, -229, -181, -215, -211, -195, -229, -209, -229, -202, -205, -208, -229, -217, -76, -78, -75, -77, -70, -79, -229, -86, -90, -162, -173, -229, -229, -229, -229, -229, -229, -229, -229, -229, -229, -229, -229, -229, -229, -156, -150, -151, -229, -153, -33, -157, -158, -19, -34, -229, -180, -199, -33, -229, -229, -229, -229, -80, -168, -172, -173, -173, -229, -134, -135, -136, -137, -138, -139, -140, -141, -142, -143, -144, -145, -33, -113, -229, -229, -30, -33, -201, -203, -204, -229, -229, -210, -169, -170, -173, -229, -154, -159, -229, -206, -207, -171, -155, -229, -31] + +racc_goto_table = [ +81, 248, 183, 68, 106, 91, 117, 271, 78, 246, 273, 247, 82, 69, 209, +161, 97, 89, 268, 304, 90, 119, 54, 57, 220, 221, 318, 60, 61, 62, +63, 354, 355, 1, 65, 127, 76, 2, 149, 86, 58, 132, 133, 134, 135, +4, 70, 159, 50, 51, 52, 308, 67, 66, 119, 88, 208, 282, 227, 162, +228, 122, 347, 348, 140, 352, 261, 311, nil, 335, 154, nil, 207, nil, 211, +nil, 214, nil, nil, nil, nil, nil, nil, nil, 205, nil, 222, 206, nil, 213, +262, 356, nil, 271, nil, nil, nil, nil, nil, nil, nil, nil, 254, nil, 316, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 249, 280, nil, 271, +271, nil, nil, nil, nil, nil, nil, 284, nil, 81, 342, 343, nil, nil, nil, +253, nil, 257, nil, nil, nil, 82, 336, nil, nil, nil, nil, nil, nil, 267, +271, 271, 247, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +310, 274, 275, 276, 277, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, 283, nil, nil, nil, nil, nil, nil, 320, 321, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, 299, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +309, 349, nil, nil, nil, nil, nil, nil, nil, nil, 267, nil, nil, nil, 315, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, 358, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, 337, nil, nil, 267, 267, nil, nil, nil, 341, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, 350, nil, nil, 267, 267, 353] + +racc_goto_check = [ +35, 62, 18, 17, 51, 41, 51, 77, 32, 58, 77, 58, 36, 12, 46, +15, 48, 39, 82, 68, 40, 55, 8, 8, 70, 70, 73, 7, 7, 7, +7, 84, 84, 1, 7, 61, 7, 3, 9, 7, 10, 61, 61, 61, 61, +2, 11, 14, 2, 2, 2, 16, 27, 28, 55, 38, 42, 52, 56, 17, +57, 59, 73, 73, 63, 69, 74, 81, nil, 68, 8, nil, 41, nil, 41, +nil, 51, nil, nil, nil, nil, nil, nil, nil, 39, nil, 51, 40, nil, 48, +18, 73, nil, 77, nil, nil, nil, nil, nil, nil, nil, nil, 15, nil, 82, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 17, 46, nil, 77, +77, nil, nil, nil, nil, nil, nil, 18, nil, 35, 82, 82, nil, nil, nil, +12, nil, 32, nil, nil, nil, 36, 62, nil, nil, nil, nil, nil, nil, 35, +77, 77, 58, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +18, 41, 41, 41, 41, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, 51, nil, nil, nil, nil, nil, nil, 18, 18, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, 17, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +17, 18, nil, nil, nil, nil, nil, nil, nil, nil, 35, nil, nil, nil, 17, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, 18, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, 17, nil, nil, 35, 35, nil, nil, nil, 17, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, 17, nil, nil, 35, 35, 17] + +racc_goto_pointer = [nil, 33, 43, 37, nil, nil, nil, 15, 12, -16, 29, 26, -7, nil, -24, -57, -204, -16, -81, nil, nil, nil, nil, nil, nil, nil, nil, 33, 34, nil, nil, nil, -14, nil, nil, -22, -10, nil, 30, -8, -5, -20, -36, nil, nil, nil, -78, nil, -10, nil, nil, -24, -160, nil, nil, -10, -63, -62, -135, 27, nil, 0, -145, 17, nil, nil, nil, nil, -230, -273, -84, nil, nil, -258, -105, nil, nil, -179, nil, nil, nil, -199, -168, nil, -313, nil] + +racc_goto_default = [ +nil, nil, nil, nil, 5, 6, 7, 8, nil, nil, 172, nil, nil, 71, nil, +nil, 72, nil, nil, 180, 12, 13, 14, 15, 16, 17, 18, nil, nil, 19, +21, 22, nil, 79, 80, 179, 176, 24, nil, nil, nil, nil, nil, 93, 95, +96, 111, 26, nil, 99, 100, nil, 101, 102, 28, 30, 32, 33, 34, nil, +35, 36, nil, 40, 41, 42, 43, 44, nil, 305, 110, 109, 112, nil, nil, +171, 173, 174, 175, 177, 178, 182, nil, 269, 270, 189] + +racc_reduce_table = [ + 0, 0, :racc_error, + 0, 63, :_reduce_1, + 2, 61, :_reduce_2, + 2, 62, :_reduce_none, + 2, 62, :_reduce_none, + 2, 62, :_reduce_none, + 1, 62, :_reduce_none, + 1, 62, :_reduce_none, + 1, 62, :_reduce_none, + 1, 62, :_reduce_none, + 0, 62, :_reduce_none, + 3, 64, :_reduce_11, + 4, 65, :_reduce_12, + 3, 65, :_reduce_13, + 2, 68, :_reduce_none, + 1, 68, :_reduce_15, + 1, 68, :_reduce_16, + 4, 66, :_reduce_17, + 3, 66, :_reduce_18, + 3, 69, :_reduce_19, + 1, 69, :_reduce_20, + 1, 71, :_reduce_21, + 3, 71, :_reduce_22, + 0, 71, :_reduce_23, + 3, 72, :_reduce_24, + 2, 72, :_reduce_25, + 1, 73, :_reduce_26, + 1, 73, :_reduce_27, + 0, 73, :_reduce_28, + 1, 74, :_reduce_29, + 5, 76, :_reduce_30, + 8, 76, :_reduce_31, + 1, 77, :_reduce_32, + 0, 77, :_reduce_33, + 3, 75, :_reduce_34, + 0, 75, :_reduce_35, + 1, 79, :_reduce_36, + 2, 67, :_reduce_none, + 2, 67, :_reduce_none, + 2, 67, :_reduce_none, + 2, 67, :_reduce_none, + 1, 67, :_reduce_none, + 1, 67, :_reduce_none, + 1, 67, :_reduce_none, + 1, 67, :_reduce_none, + 1, 81, :_reduce_none, + 1, 81, :_reduce_none, + 1, 81, :_reduce_none, + 1, 87, :_reduce_none, + 1, 87, :_reduce_none, + 3, 84, :_reduce_50, + 3, 89, :_reduce_51, + 3, 85, :_reduce_52, + 2, 85, :_reduce_53, + 3, 90, :_reduce_54, + 1, 91, :_reduce_55, + 3, 92, :_reduce_56, + 1, 92, :_reduce_57, + 1, 93, :_reduce_none, + 1, 93, :_reduce_none, + 1, 93, :_reduce_none, + 3, 86, :_reduce_61, + 2, 86, :_reduce_62, + 3, 97, :_reduce_63, + 1, 98, :_reduce_64, + 1, 98, :_reduce_65, + 1, 98, :_reduce_66, + 1, 102, :_reduce_67, + 1, 102, :_reduce_68, + 1, 102, :_reduce_69, + 3, 101, :_reduce_70, + 1, 101, :_reduce_71, + 2, 99, :_reduce_72, + 1, 100, :_reduce_none, + 1, 100, :_reduce_none, + 3, 104, :_reduce_75, + 3, 104, :_reduce_76, + 3, 105, :_reduce_77, + 3, 105, :_reduce_78, + 3, 103, :_reduce_79, + 4, 103, :_reduce_80, + 3, 82, :_reduce_none, + 2, 82, :_reduce_none, + 3, 107, :_reduce_83, + 2, 108, :_reduce_none, + 1, 108, :_reduce_none, + 3, 109, :_reduce_86, + 2, 109, :_reduce_87, + 2, 110, :_reduce_88, + 0, 112, :_reduce_none, + 3, 112, :_reduce_90, + 1, 112, :_reduce_none, + 1, 113, :_reduce_none, + 1, 113, :_reduce_93, + 3, 83, :_reduce_94, + 2, 83, :_reduce_95, + 2, 114, :_reduce_96, + 3, 80, :_reduce_97, + 2, 80, :_reduce_98, + 1, 88, :_reduce_99, + 2, 115, :_reduce_100, + 2, 115, :_reduce_101, + 3, 116, :_reduce_102, + 1, 116, :_reduce_103, + 3, 117, :_reduce_104, + 1, 117, :_reduce_none, + 1, 119, :_reduce_106, + 1, 119, :_reduce_107, + 1, 119, :_reduce_108, + 1, 119, :_reduce_109, + 2, 118, :_reduce_110, + 1, 118, :_reduce_111, + 1, 118, :_reduce_112, + 3, 122, :_reduce_113, + 1, 122, :_reduce_none, + 1, 123, :_reduce_115, + 3, 123, :_reduce_116, + 2, 123, :_reduce_117, + 3, 123, :_reduce_118, + 1, 120, :_reduce_119, + 1, 120, :_reduce_120, + 2, 120, :_reduce_121, + 3, 120, :_reduce_122, + 3, 120, :_reduce_123, + 1, 121, :_reduce_124, + 1, 121, :_reduce_125, + 1, 121, :_reduce_126, + 1, 121, :_reduce_127, + 2, 121, :_reduce_128, + 2, 121, :_reduce_129, + 2, 121, :_reduce_130, + 2, 121, :_reduce_131, + 1, 124, :_reduce_132, + 2, 125, :_reduce_133, + 5, 126, :_reduce_134, + 5, 126, :_reduce_135, + 5, 126, :_reduce_136, + 5, 126, :_reduce_137, + 5, 126, :_reduce_138, + 5, 126, :_reduce_139, + 5, 126, :_reduce_140, + 5, 126, :_reduce_141, + 5, 126, :_reduce_142, + 5, 126, :_reduce_143, + 5, 126, :_reduce_144, + 5, 126, :_reduce_145, + 3, 126, :_reduce_146, + 2, 127, :_reduce_147, + 3, 127, :_reduce_148, + 3, 127, :_reduce_149, + 4, 127, :_reduce_150, + 4, 127, :_reduce_151, + 2, 127, :_reduce_152, + 4, 127, :_reduce_153, + 6, 127, :_reduce_154, + 7, 127, :_reduce_155, + 0, 128, :_reduce_none, + 1, 128, :_reduce_none, + 1, 129, :_reduce_none, + 3, 129, :_reduce_none, + 1, 130, :_reduce_none, + 2, 130, :_reduce_none, + 3, 111, :_reduce_none, + 2, 111, :_reduce_none, + 2, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 131, :_reduce_167, + 4, 106, :_reduce_168, + 5, 106, :_reduce_169, + 5, 106, :_reduce_170, + 6, 106, :_reduce_171, + 1, 133, :_reduce_172, + 0, 133, :_reduce_173, + 1, 132, :_reduce_174, + 2, 132, :_reduce_175, + 1, 132, :_reduce_176, + 1, 134, :_reduce_none, + 1, 134, :_reduce_none, + 1, 134, :_reduce_none, + 3, 78, :_reduce_180, + 2, 78, :_reduce_181, + 1, 78, :_reduce_182, + 1, 135, :_reduce_none, + 1, 135, :_reduce_none, + 1, 135, :_reduce_none, + 1, 135, :_reduce_none, + 1, 135, :_reduce_none, + 1, 135, :_reduce_none, + 1, 135, :_reduce_none, + 1, 135, :_reduce_none, + 1, 135, :_reduce_none, + 1, 135, :_reduce_none, + 1, 135, :_reduce_none, + 2, 95, :_reduce_194, + 3, 95, :_reduce_195, + 2, 95, :_reduce_196, + 2, 94, :_reduce_197, + 1, 94, :_reduce_198, + 3, 141, :_reduce_none, + 1, 141, :_reduce_none, + 4, 140, :_reduce_201, + 1, 142, :_reduce_none, + 3, 142, :_reduce_203, + 3, 142, :_reduce_204, + 1, 143, :_reduce_none, + 4, 143, :_reduce_206, + 4, 143, :_reduce_207, + 1, 144, :_reduce_208, + 1, 144, :_reduce_209, + 3, 144, :_reduce_210, + 2, 139, :_reduce_211, + 1, 139, :_reduce_212, + 2, 96, :_reduce_213, + 1, 96, :_reduce_214, + 2, 138, :_reduce_215, + 1, 138, :_reduce_216, + 2, 137, :_reduce_217, + 1, 137, :_reduce_218, + 1, 137, :_reduce_219, + 1, 137, :_reduce_220, + 1, 137, :_reduce_221, + 1, 137, :_reduce_222, + 1, 137, :_reduce_223, + 1, 136, :_reduce_224, + 1, 145, :_reduce_225, + 1, 145, :_reduce_226, + 2, 70, :_reduce_227, + 1, 70, :_reduce_228 ] + +racc_reduce_n = 229 + +racc_shift_n = 360 + +racc_token_table = { + false => 0, + :error => 1, + :CHARSET_SYM => 2, + :IMPORT_SYM => 3, + :STRING => 4, + :SEMI => 5, + :IDENT => 6, + :S => 7, + :COMMA => 8, + :LBRACE => 9, + :RBRACE => 10, + :STAR => 11, + :HASH => 12, + :LSQUARE => 13, + :RSQUARE => 14, + :EQUAL => 15, + :INCLUDES => 16, + :DASHMATCH => 17, + :LPAREN => 18, + :RPAREN => 19, + :FUNCTION => 20, + :GREATER => 21, + :PLUS => 22, + :SLASH => 23, + :NUMBER => 24, + :MINUS => 25, + :LENGTH => 26, + :PERCENTAGE => 27, + :ANGLE => 28, + :TIME => 29, + :FREQ => 30, + :URI => 31, + :IMPORTANT_SYM => 32, + :MEDIA_SYM => 33, + :NOT => 34, + :ONLY => 35, + :AND => 36, + :NTH_PSEUDO_CLASS => 37, + :DOCUMENT_QUERY_SYM => 38, + :FUNCTION_NO_QUOTE => 39, + :TILDE => 40, + :PREFIXMATCH => 41, + :SUFFIXMATCH => 42, + :SUBSTRINGMATCH => 43, + :NOT_PSEUDO_CLASS => 44, + :KEYFRAMES_SYM => 45, + :MATCHES_PSEUDO_CLASS => 46, + :NAMESPACE_SYM => 47, + :MOZ_PSEUDO_ELEMENT => 48, + :RESOLUTION => 49, + :COLON => 50, + :SUPPORTS_SYM => 51, + :OR => 52, + :VARIABLE_NAME => 53, + :CALC_SYM => 54, + :FONTFACE_SYM => 55, + :UNICODE_RANGE => 56, + :RATIO => 57, + "|" => 58, + "." => 59 } + +racc_nt_base = 60 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ + "$end", + "error", + "CHARSET_SYM", + "IMPORT_SYM", + "STRING", + "SEMI", + "IDENT", + "S", + "COMMA", + "LBRACE", + "RBRACE", + "STAR", + "HASH", + "LSQUARE", + "RSQUARE", + "EQUAL", + "INCLUDES", + "DASHMATCH", + "LPAREN", + "RPAREN", + "FUNCTION", + "GREATER", + "PLUS", + "SLASH", + "NUMBER", + "MINUS", + "LENGTH", + "PERCENTAGE", + "ANGLE", + "TIME", + "FREQ", + "URI", + "IMPORTANT_SYM", + "MEDIA_SYM", + "NOT", + "ONLY", + "AND", + "NTH_PSEUDO_CLASS", + "DOCUMENT_QUERY_SYM", + "FUNCTION_NO_QUOTE", + "TILDE", + "PREFIXMATCH", + "SUFFIXMATCH", + "SUBSTRINGMATCH", + "NOT_PSEUDO_CLASS", + "KEYFRAMES_SYM", + "MATCHES_PSEUDO_CLASS", + "NAMESPACE_SYM", + "MOZ_PSEUDO_ELEMENT", + "RESOLUTION", + "COLON", + "SUPPORTS_SYM", + "OR", + "VARIABLE_NAME", + "CALC_SYM", + "FONTFACE_SYM", + "UNICODE_RANGE", + "RATIO", + "\"|\"", + "\".\"", + "$start", + "document", + "stylesheet", + "@action1", + "charset", + "import", + "namespace", + "body", + "import_location", + "medium", + "ident", + "media_query_list", + "media_query", + "optional_only_or_not", + "media_type", + "optional_and_exprs", + "media_expr", + "optional_space", + "expr", + "resolution", + "ruleset", + "conditional_rule", + "keyframes_rule", + "fontface_rule", + "media", + "document_query", + "supports", + "body_in_media", + "empty_ruleset", + "start_media", + "start_document_query", + "start_document_query_pos", + "url_match_fns", + "url_match_fn", + "function_no_quote", + "function", + "uri", + "start_supports", + "supports_condition_root", + "supports_negation", + "supports_conjunction_or_disjunction", + "supports_condition_in_parens", + "supports_condition", + "supports_declaration_condition", + "supports_conjunction", + "supports_disjunction", + "declaration_internal", + "start_keyframes_rule", + "keyframes_blocks", + "keyframes_block", + "start_keyframes_block", + "declarations", + "keyframes_selectors", + "keyframes_selector", + "start_fontface_rule", + "start_selector", + "selectors", + "selector", + "simple_selector", + "combinator", + "element_name", + "hcap", + "simple_selectors", + "ident_with_namespace", + "hash", + "class", + "attrib", + "pseudo", + "any_number_of_idents", + "multiple_idents", + "one_or_more_semis", + "declaration", + "property", + "prio", + "operator", + "term", + "ratio", + "numeric", + "string", + "hexcolor", + "calc", + "uranges", + "calc_sum", + "calc_product", + "calc_value", + "unary_operator" ] + +Racc_debug_parser = false + +##### State transition tables end ##### + +# reduce 0 omitted + +module_eval(<<'.,.,', 'csspool.y', 26) + def _reduce_1(val, _values, result) + @handler.start_document + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 28) + def _reduce_2(val, _values, result) + @handler.end_document + result + end +.,., + +# reduce 3 omitted + +# reduce 4 omitted + +# reduce 5 omitted + +# reduce 6 omitted + +# reduce 7 omitted + +# reduce 8 omitted + +# reduce 9 omitted + +# reduce 10 omitted + +module_eval(<<'.,.,', 'csspool.y', 41) + def _reduce_11(val, _values, result) + @handler.charset interpret_string(val[1]), {} + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 45) + def _reduce_12(val, _values, result) + @handler.import_style val[2], val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 48) + def _reduce_13(val, _values, result) + @handler.import_style [], val[1] + + result + end +.,., + +# reduce 14 omitted + +module_eval(<<'.,.,', 'csspool.y', 53) + def _reduce_15(val, _values, result) + result = Terms::String.new interpret_string val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 54) + def _reduce_16(val, _values, result) + result = Terms::URI.new interpret_uri val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 58) + def _reduce_17(val, _values, result) + @handler.namespace val[1], val[2] + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 61) + def _reduce_18(val, _values, result) + @handler.namespace nil, val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 66) + def _reduce_19(val, _values, result) + result = val[0] << MediaType.new(val[2]) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 69) + def _reduce_20(val, _values, result) + result = [MediaType.new(val[0])] + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 73) + def _reduce_21(val, _values, result) + result = MediaQueryList.new([ val[0] ]) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 74) + def _reduce_22(val, _values, result) + result = val[0] << val[2] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 75) + def _reduce_23(val, _values, result) + result = MediaQueryList.new + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 78) + def _reduce_24(val, _values, result) + result = MediaQuery.new(val[0], val[1], val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 79) + def _reduce_25(val, _values, result) + result = MediaQuery.new(nil, val[0], val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 82) + def _reduce_26(val, _values, result) + result = :only + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 83) + def _reduce_27(val, _values, result) + result = :not + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 84) + def _reduce_28(val, _values, result) + result = nil + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 87) + def _reduce_29(val, _values, result) + result = MediaType.new(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 90) + def _reduce_30(val, _values, result) + result = MediaType.new(val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 91) + def _reduce_31(val, _values, result) + result = MediaFeature.new(val[2], val[6][0]) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 94) + def _reduce_32(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 95) + def _reduce_33(val, _values, result) + result = nil + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 98) + def _reduce_34(val, _values, result) + result = val[0] << val[2] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 99) + def _reduce_35(val, _values, result) + result = [] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 103) + def _reduce_36(val, _values, result) + unit = val.first.gsub(/[\s\d.]/, '') + number = numeric(val.first) + result = Terms::Resolution.new(number, unit) + + result + end +.,., + +# reduce 37 omitted + +# reduce 38 omitted + +# reduce 39 omitted + +# reduce 40 omitted + +# reduce 41 omitted + +# reduce 42 omitted + +# reduce 43 omitted + +# reduce 44 omitted + +# reduce 45 omitted + +# reduce 46 omitted + +# reduce 47 omitted + +# reduce 48 omitted + +# reduce 49 omitted + +module_eval(<<'.,.,', 'csspool.y', 128) + def _reduce_50(val, _values, result) + @handler.end_media val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 132) + def _reduce_51(val, _values, result) + result = val[1] + @handler.start_media result + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 137) + def _reduce_52(val, _values, result) + @handler.end_document_query(before_pos(val), after_pos(val)) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 138) + def _reduce_53(val, _values, result) + @handler.end_document_query(before_pos(val), after_pos(val)) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 142) + def _reduce_54(val, _values, result) + @handler.start_document_query(val[1], after_pos(val)) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 147) + def _reduce_55(val, _values, result) + @handler.node_start_pos = before_pos(val) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 152) + def _reduce_56(val, _values, result) + result = [val[0], val[2]].flatten + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 155) + def _reduce_57(val, _values, result) + result = val + + result + end +.,., + +# reduce 58 omitted + +# reduce 59 omitted + +# reduce 60 omitted + +module_eval(<<'.,.,', 'csspool.y', 164) + def _reduce_61(val, _values, result) + @handler.end_supports + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 165) + def _reduce_62(val, _values, result) + @handler.end_supports + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 169) + def _reduce_63(val, _values, result) + @handler.start_supports val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 173) + def _reduce_64(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 174) + def _reduce_65(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 175) + def _reduce_66(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 178) + def _reduce_67(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 179) + def _reduce_68(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 180) + def _reduce_69(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 183) + def _reduce_70(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 184) + def _reduce_71(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 187) + def _reduce_72(val, _values, result) + result = val.join('') + result + end +.,., + +# reduce 73 omitted + +# reduce 74 omitted + +module_eval(<<'.,.,', 'csspool.y', 194) + def _reduce_75(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 195) + def _reduce_76(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 198) + def _reduce_77(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 199) + def _reduce_78(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 202) + def _reduce_79(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 203) + def _reduce_80(val, _values, result) + result = val.join('') + result + end +.,., + +# reduce 81 omitted + +# reduce 82 omitted + +module_eval(<<'.,.,', 'csspool.y', 211) + def _reduce_83(val, _values, result) + @handler.start_keyframes_rule val[1] + + result + end +.,., + +# reduce 84 omitted + +# reduce 85 omitted + +module_eval(<<'.,.,', 'csspool.y', 219) + def _reduce_86(val, _values, result) + @handler.end_keyframes_block + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 220) + def _reduce_87(val, _values, result) + @handler.end_keyframes_block + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 224) + def _reduce_88(val, _values, result) + @handler.start_keyframes_block val[0] + + result + end +.,., + +# reduce 89 omitted + +module_eval(<<'.,.,', 'csspool.y', 229) + def _reduce_90(val, _values, result) + result = val[0] + ', ' + val[2] + + result + end +.,., + +# reduce 91 omitted + +# reduce 92 omitted + +module_eval(<<'.,.,', 'csspool.y', 235) + def _reduce_93(val, _values, result) + result = val[0].strip + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 238) + def _reduce_94(val, _values, result) + @handler.end_fontface_rule + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 239) + def _reduce_95(val, _values, result) + @handler.end_fontface_rule + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 243) + def _reduce_96(val, _values, result) + @handler.start_fontface_rule + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 248) + def _reduce_97(val, _values, result) + @handler.end_selector val.first + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 251) + def _reduce_98(val, _values, result) + @handler.end_selector val.first + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 256) + def _reduce_99(val, _values, result) + start = @handler.start_selector([]) + @handler.end_selector(start) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 261) + def _reduce_100(val, _values, result) + result = val.last + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 263) + def _reduce_101(val, _values, result) + @handler.start_selector val.first + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 269) + def _reduce_102(val, _values, result) + sel = Selector.new(val.first, {}) + result = [sel].concat(val[2]) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 274) + def _reduce_103(val, _values, result) + result = [Selector.new(val.first, {})] + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 280) + def _reduce_104(val, _values, result) + val.flatten! + val[2].combinator = val.delete_at 1 + result = val + + result + end +.,., + +# reduce 105 omitted + +module_eval(<<'.,.,', 'csspool.y', 287) + def _reduce_106(val, _values, result) + result = :s + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 288) + def _reduce_107(val, _values, result) + result = :> + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 289) + def _reduce_108(val, _values, result) + result = :+ + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 290) + def _reduce_109(val, _values, result) + result = :~ + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 294) + def _reduce_110(val, _values, result) + selector = val.first + selector.additional_selectors = val.last + result = [selector] + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 298) + def _reduce_111(val, _values, result) + result = val + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 301) + def _reduce_112(val, _values, result) + ss = Selectors::Simple.new nil, nil + ss.additional_selectors = val.flatten + result = [ss] + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 307) + def _reduce_113(val, _values, result) + result = [val[0], val[2]].flatten + result + end +.,., + +# reduce 114 omitted + +module_eval(<<'.,.,', 'csspool.y', 311) + def _reduce_115(val, _values, result) + result = [interpret_identifier(val[0]), nil] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 312) + def _reduce_116(val, _values, result) + result = [interpret_identifier(val[2]), interpret_identifier(val[0])] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 313) + def _reduce_117(val, _values, result) + result = [interpret_identifier(val[1]), nil] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 314) + def _reduce_118(val, _values, result) + result = [interpret_identifier(val[2]), '*'] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 317) + def _reduce_119(val, _values, result) + result = Selectors::Type.new val.first[0], nil, val.first[1] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 318) + def _reduce_120(val, _values, result) + result = Selectors::Universal.new val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 319) + def _reduce_121(val, _values, result) + result = Selectors::Universal.new val[1] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 320) + def _reduce_122(val, _values, result) + result = Selectors::Universal.new val[2], nil, val[0] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 321) + def _reduce_123(val, _values, result) + result = Selectors::Universal.new val[2], nil, interpret_identifier(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 324) + def _reduce_124(val, _values, result) + result = val + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 325) + def _reduce_125(val, _values, result) + result = val + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 326) + def _reduce_126(val, _values, result) + result = val + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 327) + def _reduce_127(val, _values, result) + result = val + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 328) + def _reduce_128(val, _values, result) + result = val.flatten + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 329) + def _reduce_129(val, _values, result) + result = val.flatten + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 330) + def _reduce_130(val, _values, result) + result = val.flatten + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 331) + def _reduce_131(val, _values, result) + result = val.flatten + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 335) + def _reduce_132(val, _values, result) + result = Selectors::Id.new interpret_identifier val.first.sub(/^#/, '') + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 339) + def _reduce_133(val, _values, result) + result = Selectors::Class.new interpret_identifier val.last + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 344) + def _reduce_134(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::EQUALS, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 352) + def _reduce_135(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::EQUALS, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 360) + def _reduce_136(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::INCLUDES, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 368) + def _reduce_137(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::INCLUDES, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 376) + def _reduce_138(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::DASHMATCH, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 384) + def _reduce_139(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::DASHMATCH, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 392) + def _reduce_140(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::PREFIXMATCH, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 400) + def _reduce_141(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::PREFIXMATCH, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 408) + def _reduce_142(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::SUFFIXMATCH, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 416) + def _reduce_143(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::SUFFIXMATCH, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 424) + def _reduce_144(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_identifier(val[3]), + Selectors::Attribute::SUBSTRINGMATCH, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 432) + def _reduce_145(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + interpret_string(val[3]), + Selectors::Attribute::SUBSTRINGMATCH, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 440) + def _reduce_146(val, _values, result) + result = Selectors::Attribute.new( + val[1][0], + nil, + Selectors::Attribute::SET, + val[1][1] + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 450) + def _reduce_147(val, _values, result) + result = Selectors::pseudo interpret_identifier(val[1]) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 453) + def _reduce_148(val, _values, result) + result = Selectors::PseudoElement.new( + interpret_identifier(val[2]) + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 458) + def _reduce_149(val, _values, result) + result = Selectors::PseudoClass.new( + interpret_identifier(val[1].sub(/\($/, '')), + '' + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 464) + def _reduce_150(val, _values, result) + result = Selectors::PseudoClass.new( + interpret_identifier(val[1].sub(/\($/, '')), + interpret_identifier(val[2]) + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 470) + def _reduce_151(val, _values, result) + result = Selectors::PseudoClass.new( + 'not', + val[2].first.to_s + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 476) + def _reduce_152(val, _values, result) + result = Selectors::PseudoClass.new( + interpret_identifier(val[1].sub(/\(.*/, '')), + interpret_identifier(val[1].sub(/.*\(/, '').sub(/\).*/, '')) + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 482) + def _reduce_153(val, _values, result) + result = Selectors::PseudoClass.new( + val[1].split('(').first.strip, + val[2].join(', ') + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 488) + def _reduce_154(val, _values, result) + result = Selectors::PseudoElement.new( + interpret_identifier(val[1].sub(/\($/, '')) + ) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 493) + def _reduce_155(val, _values, result) + result = Selectors::PseudoElement.new( + interpret_identifier(val[2].sub(/\($/, '')) + ) + + result + end +.,., + +# reduce 156 omitted + +# reduce 157 omitted + +# reduce 158 omitted + +# reduce 159 omitted + +# reduce 160 omitted + +# reduce 161 omitted + +# reduce 162 omitted + +# reduce 163 omitted + +# reduce 164 omitted + +# reduce 165 omitted + +# reduce 166 omitted + +module_eval(<<'.,.,', 'csspool.y', 519) + def _reduce_167(val, _values, result) + @handler.property val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 523) + def _reduce_168(val, _values, result) + result = Declaration.new(val.first, val[2], val[3]) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 525) + def _reduce_169(val, _values, result) + result = Declaration.new(val.first, val[3], val[4]) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 527) + def _reduce_170(val, _values, result) + result = Declaration.new(val.first, val[3], val[4]) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 529) + def _reduce_171(val, _values, result) + result = Declaration.new(val.first, val[4], val[5]) + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 532) + def _reduce_172(val, _values, result) + result = true + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 533) + def _reduce_173(val, _values, result) + result = false + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 536) + def _reduce_174(val, _values, result) + result = interpret_identifier val[0] + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 537) + def _reduce_175(val, _values, result) + result = interpret_identifier val.join + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 538) + def _reduce_176(val, _values, result) + result = interpret_identifier val[0] + result + end +.,., + +# reduce 177 omitted + +# reduce 178 omitted + +# reduce 179 omitted + +module_eval(<<'.,.,', 'csspool.y', 547) + def _reduce_180(val, _values, result) + result = [val.first, val.last].flatten + val.last.first.operator = val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 550) + def _reduce_181(val, _values, result) + result = val.flatten + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 551) + def _reduce_182(val, _values, result) + result = val + result + end +.,., + +# reduce 183 omitted + +# reduce 184 omitted + +# reduce 185 omitted + +# reduce 186 omitted + +# reduce 187 omitted + +# reduce 188 omitted + +# reduce 189 omitted + +# reduce 190 omitted + +# reduce 191 omitted + +# reduce 192 omitted + +# reduce 193 omitted + +module_eval(<<'.,.,', 'csspool.y', 567) + def _reduce_194(val, _values, result) + result = val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 569) + def _reduce_195(val, _values, result) + name = interpret_identifier val.first.sub(/\($/, '') + if name == 'rgb' + result = Terms::Rgb.new(*val[1]) + else + result = Terms::Function.new name, val[1] + end + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 577) + def _reduce_196(val, _values, result) + name = interpret_identifier val.first.sub(/\($/, '') + result = Terms::Function.new name + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 582) + def _reduce_197(val, _values, result) + result = val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 584) + def _reduce_198(val, _values, result) + parts = val.first.split('(') + name = interpret_identifier parts.first + result = Terms::Function.new(name, [Terms::String.new(interpret_string_no_quote(parts.last))]) + + result + end +.,., + +# reduce 199 omitted + +# reduce 200 omitted + +module_eval(<<'.,.,', 'csspool.y', 595) + def _reduce_201(val, _values, result) + result = Terms::Math.new(val.first.split('(').first, val[1]) + + result + end +.,., + +# reduce 202 omitted + +module_eval(<<'.,.,', 'csspool.y', 601) + def _reduce_203(val, _values, result) + val.insert(1, ' '); result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 602) + def _reduce_204(val, _values, result) + val.insert(1, ' '); result = val.join('') + result + end +.,., + +# reduce 205 omitted + +module_eval(<<'.,.,', 'csspool.y', 606) + def _reduce_206(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 607) + def _reduce_207(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 610) + def _reduce_208(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 611) + def _reduce_209(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 612) + def _reduce_210(val, _values, result) + result = val.join('') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 615) + def _reduce_211(val, _values, result) + result = val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 616) + def _reduce_212(val, _values, result) + result = Terms::Hash.new val.first.sub(/^#/, '') + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 619) + def _reduce_213(val, _values, result) + result = val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 620) + def _reduce_214(val, _values, result) + result = Terms::URI.new interpret_uri val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 623) + def _reduce_215(val, _values, result) + result = val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 624) + def _reduce_216(val, _values, result) + result = Terms::String.new interpret_string val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 628) + def _reduce_217(val, _values, result) + result = val[1] + val[1].unary_operator = val.first + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 632) + def _reduce_218(val, _values, result) + result = Terms::Number.new numeric val.first + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 635) + def _reduce_219(val, _values, result) + result = Terms::Number.new numeric(val.first), nil, '%' + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 638) + def _reduce_220(val, _values, result) + unit = val.first.gsub(/[\s\d.]/, '') + result = Terms::Number.new numeric(val.first), nil, unit + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 642) + def _reduce_221(val, _values, result) + unit = val.first.gsub(/[\s\d.]/, '') + result = Terms::Number.new numeric(val.first), nil, unit + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 646) + def _reduce_222(val, _values, result) + unit = val.first.gsub(/[\s\d.]/, '') + result = Terms::Number.new numeric(val.first), nil, unit + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 650) + def _reduce_223(val, _values, result) + unit = val.first.gsub(/[\s\d.]/, '') + result = Terms::Number.new numeric(val.first), nil, unit + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 656) + def _reduce_224(val, _values, result) + result = Terms::Ratio.new(val[0], val[1]) + + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 660) + def _reduce_225(val, _values, result) + result = :minus + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 661) + def _reduce_226(val, _values, result) + result = :plus + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 664) + def _reduce_227(val, _values, result) + result = val.first + result + end +.,., + +module_eval(<<'.,.,', 'csspool.y', 665) + def _reduce_228(val, _values, result) + result = Terms::Ident.new interpret_identifier val.first + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] +end + + end # class Parser + end # module CSS + end # module CSSPool diff --git a/test/regress/duplicate.out b/test/regress/duplicate.out new file mode 100644 index 00000000..0d31e966 --- /dev/null +++ b/test/regress/duplicate.out @@ -0,0 +1,4 @@ +Error: test/assets/duplicate.y: The following rules are duplicates: +duplicate.y:6: c: A + +duplicate.y:7: c: A diff --git a/test/regress/edtf.out b/test/regress/edtf.out new file mode 100644 index 00000000..af5dc078 --- /dev/null +++ b/test/regress/edtf.out @@ -0,0 +1,9 @@ +Parsing grammar file... +Generating and resolving LALR states... +Creating parser file... + +Warning: Useless terminal UNMATCHED does not appear on the right side of any rule + +Warning: Useless terminal PUA does not appear on the right side of any rule + +2 useless terminals diff --git a/test/regress/edtf.rb b/test/regress/edtf.rb new file mode 100644 index 00000000..22f29d3c --- /dev/null +++ b/test/regress/edtf.rb @@ -0,0 +1,1664 @@ +# +# DO NOT MODIFY!!!! +# This file was automatically generated by Racc 2.0.0.dev +# (codename: Mecha Oishii) from Racc grammar file "edtf.y". +# + +require 'racc/parser.rb' + +Object.module_eval(<<'...end edtf.y/module_eval...', 'edtf.y', 465) +require 'strscan' + +...end edtf.y/module_eval... +module EDTF + class Parser < Racc::Parser + +module_eval(<<'...end edtf.y/module_eval...2', 'edtf.y', 468) + + @defaults = { + :level => 2, + :debug => false + }.freeze + + class << self; attr_reader :defaults; end + + attr_reader :options + + def initialize(options = {}) + @options = Parser.defaults.merge(options) + end + + def debug? + !!(options[:debug] || ENV['DEBUG']) + end + + def parse(input) + parse!(input) + rescue => e + warn e.message if debug? + nil + end + + def parse!(input) + @yydebug = debug? + @src = StringScanner.new(input) + do_parse + end + + def on_error(tid, value, stack) + raise ArgumentError, + "failed to parse date: unexpected '#{value}' at #{stack.inspect}" + end + + def apply_uncertainty(date, uncertainty, scope = nil) + uncertainty.each do |u| + scope.nil? ? date.send(u) : date.send(u, scope) + end + date + end + + alias uoa apply_uncertainty + + def next_token + case + when @src.eos? + nil + # when @src.scan(/\s+/) + # ignore whitespace + when @src.scan(/\(/) + ['(', @src.matched] + # when @src.scan(/\)\?~-/) + # [:PUA, [:uncertain!, :approximate!]] + # when @src.scan(/\)\?-/) + # [:PUA, [:uncertain!]] + # when @src.scan(/\)~-/) + # [:PUA, [:approximate!]] + when @src.scan(/\)/) + [')', @src.matched] + when @src.scan(/\[/) + ['[', @src.matched] + when @src.scan(/\]/) + [']', @src.matched] + when @src.scan(/\{/) + ['{', @src.matched] + when @src.scan(/\}/) + ['}', @src.matched] + when @src.scan(/T/) + [:T, @src.matched] + when @src.scan(/Z/) + [:Z, @src.matched] + when @src.scan(/\?~/) + [:UA, [:uncertain!, :approximate!]] + when @src.scan(/\?/) + [:UA, [:uncertain!]] + when @src.scan(/~/) + [:UA, [:approximate!]] + when @src.scan(/open/i) + [:OPEN, :open] + when @src.scan(/unkn?own/i) # matches 'unkown' typo too + [:UNKNOWN, :unknown] + when @src.scan(/u/) + [:U, @src.matched] + when @src.scan(/x/i) + [:X, @src.matched] + when @src.scan(/y/) + [:LONGYEAR, @src.matched] + when @src.scan(/e/) + [:E, @src.matched] + when @src.scan(/\+/) + ['+', @src.matched] + when @src.scan(/-\(/) + ['-(', @src.matched] + when @src.scan(/-/) + ['-', @src.matched] + when @src.scan(/:/) + [':', @src.matched] + when @src.scan(/\//) + ['/', @src.matched] + when @src.scan(/\s*\.\.\s*/) + [:DOTS, '..'] + when @src.scan(/\s*,\s*/) + [',', ','] + when @src.scan(/\^\w+/) + ['^', @src.matched[1..-1]] + when @src.scan(/\d/) + [@src.matched, @src.matched.to_i] + else @src.scan(/./) + [:UNMATCHED, @src.rest] + end + end + + +# -*- racc -*- +...end edtf.y/module_eval...2 +##### State transition tables begin ### + +racc_action_table = [129, 128, 52, 111, 51, 112, 149, 208, 207, 57, -50, 43, 45, 40, 55, 42, 54, 44, 43, 45, 40, - +48, 42, 53, 44, 64, 58, 46, 47, 48, 49, 50, 128, 56, 46, 47, +48, 49, 50, 207, 57, 65, 43, 45, 40, 55, 42, 157, 44, 43, 45, +40, 55, 42, 214, 44, 92, 58, 46, 47, 48, 49, 50, 66, 56, 46, +47, 48, 49, 50, 25, 56, 26, 93, 94, 67, 108, 12, -65, 43, 45, 40, - +66, 42, 159, 44, 110, 33, 111, 34, 112, 95, 36, 25, 141, 46, 47, +48, 49, 50, 12, 58, 43, 45, 40, 101, 42, 103, 44, 104, 96, 148, +55, 133, 147, 36, 124, 125, 46, 47, 48, 49, 50, 87, 165, 111, 12, +112, 43, 45, 40, 56, 42, 146, 44, 166, 111, 150, 112, 218, 167, 36, +152, 153, 46, 47, 48, 49, 50, 87, 108, 111, 12, 112, 43, 45, 40, +188, 42, 186, 44, 187, 111, 190, 112, 154, 111, 36, 112, 156, 46, 47, +48, 49, 50, 69, 158, 43, 45, 189, 191, 42, 12, 44, 43, 45, 40, +200, 42, 201, 44, 168, 177, 46, 47, 48, 49, 50, 233, 178, 46, 47, +48, 49, 50, 12, 180, 43, 45, 40, 111, 42, 112, 44, 232, 234, 111, +240, 112, 239, 36, 192, 193, 46, 47, 48, 49, 50, 12, 202, 43, 45, +40, 118, 42, 117, 44, 104, 118, 121, 117, 209, 104, 36, 121, 210, 46, +47, 48, 49, 50, 12, 212, 43, 45, 40, 244, 42, 239, 44, 213, 43, +45, 40, 215, 42, 36, 44, 229, 46, 47, 48, 49, 50, 180, 180, 236, +46, 47, 48, 49, 50, 43, 45, 40, 253, 42, 254, 44, 43, 45, 40, +255, 42, 258, 44, 261, 264, 46, 47, 48, 49, 50, 124, 125, 46, 47, +48, 49, 50, 43, 45, 40, 265, 42, 192, 44, 43, 45, 266, 269, 42, +270, 44, 275, 280, 46, 47, 48, 49, 50, 284, 285, 46, 47, 48, 49, +50, 43, 45, 40, 286, 42, 290, 44, 43, 45, 292, 293, 42, 295, 44, +296, 297, 46, 47, 48, 49, 50, 300, 301, 46, 47, 48, 49, 50, 43, +45, 40, 180, 42, 303, 44, 43, 45, 40, 304, 42, 305, 44, 281, 306, +46, 47, 48, 49, 50, 307, 308, 46, 47, 48, 49, 50, 43, 45, 175, +311, 42, 312, 44, 43, 45, 40, 313, 42, 314, 44, 316, 317, 46, 47, +48, 49, 50, 318, 319, 46, 47, 48, 49, 50, 43, 45, nil, nil, 42, +nil, 44, 43, 45, nil, nil, 42, nil, 44, nil, nil, 46, 47, 48, 49, +50, nil, nil, 46, 47, 48, 49, 50, 172, 194, 170, nil, 171, nil, 173, +43, 45, 40, nil, 42, nil, 44, nil, nil, 195, 196, 197, 198, 199, nil, +nil, 46, 47, 48, 49, 50, 43, 45, 40, nil, 42, nil, 44, 43, 45, +40, nil, 42, nil, 44, nil, nil, 46, 47, 48, 49, 50, nil, nil, 46, +47, 48, 49, 50, 43, 45, 40, nil, 42, nil, 44, 43, 45, nil, nil, +42, nil, 44, nil, nil, 46, 47, 48, 49, 50, nil, nil, 46, 47, 48, +49, 50, 43, 45, 40, nil, 42, nil, 44, 43, 45, 40, nil, 42, nil, +44, nil, nil, 46, 47, 48, 49, 50, nil, nil, 46, 47, 48, 49, 50, +43, 45, 40, nil, 42, nil, 44, 43, 45, 40, nil, 42, nil, 44, nil, +nil, 46, 47, 48, 49, 50, nil, nil, 46, 47, 48, 49, 50, 43, 45, +nil, nil, 42, nil, 44, 43, 45, 40, nil, 42, nil, 44, nil, nil, 46, +47, 48, 49, 50, nil, nil, 46, 47, 48, 49, 50, 43, 45, 40, nil, +42, nil, 44, 43, 45, 273, nil, 42, nil, 44, nil, nil, 46, 47, 48, +49, 50, nil, nil, 46, 47, 48, 49, 50, 43, 45, 274, nil, 42, nil, +44, 43, 45, 276, nil, 42, nil, 44, nil, nil, 46, 47, 48, 49, 50, +nil, nil, 46, 47, 48, 49, 50, 43, 45, 40, nil, 42, nil, 44, 43, +45, 40, nil, 42, nil, 44, nil, nil, 46, 47, 48, 49, 50, nil, nil, +46, 47, 48, 49, 50, 43, 45, 40, nil, 42, nil, 44, 43, 45, 40, +nil, 42, nil, 44, nil, nil, 46, 47, 48, 49, 50, nil, nil, 46, 47, +48, 49, 50, 43, 45, 40, nil, 42, nil, 44, 43, 45, 315, nil, 42, +nil, 44, nil, nil, 46, 47, 48, 49, 50, 116, nil, 46, 47, 48, 49, +50, 118, 250, 247, 118, 104, 117, 249, 104, 260, 121, nil, 281, nil, nil, +nil, nil, 251, nil, 118, 288, 117, 118, 104, 117, 121, 104, 118, 121, 117, +118, 104, 117, 121, 104, nil, 121, 118, 250, 247, nil, 104, nil, 249, 118, +250, 247, nil, 104, nil, 249, nil, nil, 251, nil, 118, 250, 117, nil, 104, +251, 249, 118, 250, 310, nil, 104, nil, 249, nil, nil, 251, nil, 172, 169, +170, nil, 171, 251, 173, 182, 184, nil, 118, 181, 117, 183, 104, 118, 121, +117, 118, 104, 117, 121, 104, 118, 121, 117, 118, 104, 117, 121, 104, 118, +121, 117, nil, 104, nil, 121, 188, 271, 186, 118, 187, 117, 272, 104, nil, +121] + +racc_action_check = [ +63, 63, 5, 56, 1, 56, 73, 127, 127, 73, 14, 63, 63, 63, 9, +63, 9, 63, 127, 127, 127, 5, 127, 5, 127, 16, 73, 63, 63, 63, +63, 63, 151, 9, 127, 127, 127, 127, 127, 224, 10, 17, 151, 151, 151, +89, 151, 89, 151, 224, 224, 224, 134, 224, 134, 224, 37, 10, 151, 151, +151, 151, 151, 18, 89, 224, 224, 224, 224, 224, 0, 134, 0, 37, 38, +22, 54, 0, 23, 0, 0, 0, 24, 0, 91, 0, 54, 0, 54, 0, +54, 38, 0, 67, 67, 0, 0, 0, 0, 0, 67, 91, 67, 67, 67, +52, 67, 52, 67, 52, 51, 72, 72, 66, 72, 67, 59, 60, 67, 67, +67, 67, 67, 33, 98, 66, 33, 66, 33, 33, 33, 72, 33, 71, 33, +98, 92, 74, 92, 147, 98, 33, 77, 78, 33, 33, 33, 33, 33, 34, +214, 147, 34, 147, 34, 34, 34, 112, 34, 112, 34, 112, 214, 113, 214, +79, 93, 34, 93, 88, 34, 34, 34, 34, 34, 26, 90, 26, 26, 113, +113, 26, 87, 26, 87, 87, 87, 121, 87, 121, 87, 99, 107, 26, 26, +26, 26, 26, 161, 108, 87, 87, 87, 87, 87, 153, 109, 153, 153, 153, +124, 153, 124, 153, 161, 161, 157, 166, 157, 166, 153, 115, 116, 153, 153, +153, 153, 153, 154, 123, 154, 154, 154, 58, 154, 58, 154, 58, 94, 58, +94, 128, 94, 154, 94, 129, 154, 154, 154, 154, 154, 265, 132, 265, 265, +265, 167, 265, 167, 265, 133, 12, 12, 12, 144, 12, 265, 12, 158, 265, +265, 265, 265, 265, 160, 162, 163, 12, 12, 12, 12, 12, 13, 13, 13, +169, 13, 178, 13, 36, 36, 36, 189, 36, 202, 36, 213, 218, 13, 13, +13, 13, 13, 220, 222, 36, 36, 36, 36, 36, 62, 62, 62, 225, 62, +230, 62, 64, 64, 232, 236, 64, 238, 64, 245, 253, 62, 62, 62, 62, +62, 256, 257, 64, 64, 64, 64, 64, 68, 68, 68, 260, 68, 264, 68, +69, 69, 267, 268, 69, 271, 69, 273, 274, 68, 68, 68, 68, 68, 280, +281, 69, 69, 69, 69, 69, 70, 70, 70, 283, 70, 284, 70, 75, 75, +75, 285, 75, 288, 75, 290, 292, 70, 70, 70, 70, 70, 293, 295, 75, +75, 75, 75, 75, 103, 103, 103, 300, 103, 304, 103, 104, 104, 104, 307, +104, 308, 104, 311, 312, 103, 103, 103, 103, 103, 313, 316, 104, 104, 104, +104, 104, 111, 111, nil, nil, 111, nil, 111, 117, 117, nil, nil, 117, nil, +117, nil, nil, 111, 111, 111, 111, 111, nil, nil, 117, 117, 117, 117, 117, +118, 118, 118, nil, 118, nil, 118, 126, 126, 126, nil, 126, nil, 126, nil, +nil, 118, 118, 118, 118, 118, nil, nil, 126, 126, 126, 126, 126, 130, 130, +130, nil, 130, nil, 130, 143, 143, 143, nil, 143, nil, 143, nil, nil, 130, +130, 130, 130, 130, nil, nil, 143, 143, 143, 143, 143, 145, 145, 145, nil, +145, nil, 145, 146, 146, nil, nil, 146, nil, 146, nil, nil, 145, 145, 145, +145, 145, nil, nil, 146, 146, 146, 146, 146, 148, 148, 148, nil, 148, nil, +148, 149, 149, 149, nil, 149, nil, 149, nil, nil, 148, 148, 148, 148, 148, +nil, nil, 149, 149, 149, 149, 149, 150, 150, 150, nil, 150, nil, 150, 205, +205, 205, nil, 205, nil, 205, nil, nil, 150, 150, 150, 150, 150, nil, nil, +205, 205, 205, 205, 205, 215, 215, nil, nil, 215, nil, 215, 216, 216, 216, +nil, 216, nil, 216, nil, nil, 215, 215, 215, 215, 215, nil, nil, 216, 216, +216, 216, 216, 217, 217, 217, nil, 217, nil, 217, 240, 240, 240, nil, 240, +nil, 240, nil, nil, 217, 217, 217, 217, 217, nil, nil, 240, 240, 240, 240, +240, 244, 244, 244, nil, 244, nil, 244, 247, 247, 247, nil, 247, nil, 247, +nil, nil, 244, 244, 244, 244, 244, nil, nil, 247, 247, 247, 247, 247, 249, +249, 249, nil, 249, nil, 249, 250, 250, 250, nil, 250, nil, 250, nil, nil, +249, 249, 249, 249, 249, nil, nil, 250, 250, 250, 250, 250, 251, 251, 251, +nil, 251, nil, 251, 262, 262, 262, nil, 262, nil, 262, nil, nil, 251, 251, +251, 251, 251, nil, nil, 262, 262, 262, 262, 262, 263, 263, 263, nil, 263, +nil, 263, 310, 310, 310, nil, 310, nil, 310, nil, nil, 263, 263, 263, 263, +263, 57, nil, 310, 310, 310, 310, 310, 168, 168, 168, 57, 168, 57, 168, +57, 212, 57, nil, 254, nil, nil, nil, nil, 168, nil, 212, 261, 212, 254, +212, 254, 212, 254, 95, 254, 95, 261, 95, 261, 95, 261, nil, 261, 270, +270, 270, nil, 270, nil, 270, 275, 275, 275, nil, 275, nil, 275, nil, nil, +270, nil, 296, 296, 296, nil, 296, 275, 296, 297, 297, 297, nil, 297, nil, +297, nil, nil, 296, nil, 101, 101, 101, nil, 101, 297, 101, 110, 110, nil, +125, 110, 125, 110, 125, 159, 125, 159, 190, 159, 190, 159, 190, 191, 190, +191, 233, 191, 233, 191, 233, 234, 233, 234, nil, 234, nil, 234, 239, 239, +239, 255, 239, 255, 239, 255, nil, 255] + +racc_action_pointer = [63, 4, nil, nil, nil, 0, nil, nil, nil, 2, 26, nil, 245, 266, - +11, nil, 21, 18, 49, nil, nil, nil, 54, 78, 82, nil, 161, nil, nil, +nil, nil, nil, nil, 112, 138, nil, 273, 42, 60, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, 110, 89, nil, 70, nil, -15, 745, 217, 102, 103, nil, 294, -5, 301, nil, 107, 86, 322, 329, 350, 129, 100, - +5, 126, 357, nil, 117, 115, 137, nil, nil, nil, nil, nil, nil, nil, 168, +142, 33, 146, 70, 118, 148, 222, 768, nil, nil, 121, 176, nil, 814, nil, +378, 385, nil, nil, 180, 193, 194, 821, 406, 141, 149, nil, 209, 216, 413, +434, nil, nil, 169, nil, 199, 192, 824, 441, 2, 235, 240, 462, nil, 238, +254, 40, nil, nil, nil, nil, nil, nil, nil, nil, 469, 260, 490, 497, 133, +518, 525, 546, 26, nil, 191, 214, nil, nil, 198, 256, 829, 262, 184, 263, +246, nil, nil, 199, 238, 742, 270, nil, nil, nil, nil, nil, nil, nil, nil, +273, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 280, 832, 837, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, 282, nil, nil, 553, nil, nil, +nil, nil, nil, nil, 760, 282, 144, 574, 581, 602, 291, nil, 289, nil, 290, +nil, 33, 285, nil, nil, nil, nil, 303, nil, 307, 840, 845, nil, 308, nil, +307, 852, 609, nil, nil, nil, 630, 309, nil, 637, nil, 658, 665, 686, nil, +307, 763, 855, 301, 302, nil, nil, 335, 771, 693, 714, 329, 237, nil, 317, +318, nil, 778, 335, nil, 337, 338, 785, nil, nil, nil, nil, 341, 354, nil, +357, 359, 364, nil, nil, 372, nil, 374, nil, 369, 375, nil, 370, 796, 803, +nil, nil, 382, nil, nil, nil, 369, nil, nil, 374, 388, nil, 721, 390, 397, +403, nil, nil, 398, nil, nil, nil] + +racc_action_default = [-176, -176, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -176, -176, -34, -35, -36, -37, -38, -39, -40, -41, -176, -49, -51, -52, -176, -64, -67, -68, -69, -70, -71, -176, -176, -107, -176, -109, -110, -111, -128, -129, -130, -131, -132, -133, -134, -135, -136, -137, -138, -176, -176, -76, -176, -112, -176, -176, -176, -8, -9, -11, -176, -176, -176, -72, -176, -176, -55, -176, -170, -176, -8, -9, -10, -176, -38, -176, -81, -86, -87, -88, -90, -91, -92, -93, -94, -176, -176, -176, -176, -176, -176, -176, -176, -176, 320, -12, -13, -176, -16, -176, -31, -176, -176, -152, -27, -29, -176, -126, -176, -176, -176, -176, -28, -30, -176, -176, -176, -153, -160, -176, -162, -176, -176, -176, -176, -176, -176, -176, -73, -174, -176, -176, -8, -47, -48, -49, -50, -51, -53, -54, -58, -56, -176, -171, -176, -176, -98, -97, -96, -176, -79, -176, -176, -95, -80, -176, -176, -176, -126, -176, -126, -176, -14, -18, -176, -176, -176, -176, -147, -148, -149, -150, -145, -151, -146, -114, -44, -59, -127, -60, -61, -62, -63, -139, -140, -141, -142, -176, -176, -176, -120, -45, -154, -155, -156, -157, -158, -159, -161, -163, -176, -29, -30, -176, -26, -42, -77, -43, -78, -175, -176, -176, -176, -176, -172, -74, -176, -101, -176, -100, -176, -99, -176, -83, -84, -85, -89, -108, -176, -113, -176, -176, -176, -117, -176, -19, -176, -176, -176, -143, -20, -21, -176, -176, -32, -176, -164, -176, -176, -176, -169, -176, -176, -115, -176, -176, -121, -102, -176, -176, -75, -173, -44, -176, -116, -176, -176, -118, -176, -176, -144, -176, -176, -176, -168, -165, -166, -167, -176, -176, -106, -126, -176, -176, -105, -103, -176, -57, -176, -82, -176, -176, -23, -176, -176, -176, -15, -33, -176, -46, -119, -122, -176, -104, -124, -176, -176, -25, -176, -176, -176, -176, -24, -22, -176, -123, -125, -17] + +racc_goto_table = [ +70, 179, 130, 13, 228, 11, 248, 115, 123, 226, 227, 113, 245, 5, 14, +9, 63, 11, 68, 10, 18, 132, 22, 23, 71, 1, 24, 59, 237, 243, +2, 60, 309, 309, 241, 241, 75, 75, 131, 77, 88, 3, 4, 70, 162, +163, 6, 160, 161, 61, 97, 89, 231, 98, 235, 91, 164, 99, 298, 100, +242, 143, 102, 299, 15, 126, 127, 144, 16, 17, 75, 142, 11, 145, 135, +204, 109, 174, 151, 203, 136, 138, 134, 27, 217, 185, 10, 18, 28, 140, +137, 174, 11, 139, 29, 30, 31, 32, 225, 90, 155, 105, 59, nil, nil, +nil, 60, 176, 248, 230, nil, nil, nil, 248, 294, 228, nil, nil, nil, nil, +131, 291, nil, nil, nil, nil, nil, nil, nil, 205, 206, nil, nil, 211, 248, +248, nil, nil, nil, nil, 256, 257, nil, nil, nil, nil, 142, nil, 216, nil, +nil, nil, nil, 262, 224, 223, 75, 75, nil, nil, nil, nil, 259, 219, 220, +220, nil, nil, 221, 222, nil, nil, nil, nil, nil, 302, nil, nil, nil, nil, +nil, nil, nil, 267, 268, nil, nil, nil, nil, 131, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, 282, 283, nil, nil, 206, nil, +nil, 287, nil, nil, 185, nil, nil, nil, 185, 263, 211, 174, nil, nil, nil, +nil, nil, 206, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 277, 278, 279, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 211, 289, nil, 75, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 174] + +racc_goto_check = [ +43, 45, 52, 23, 58, 11, 66, 26, 26, 57, 57, 24, 16, 5, 30, +9, 23, 11, 42, 10, 34, 24, 38, 40, 53, 1, 41, 9, 19, 19, +2, 10, 22, 22, 25, 25, 23, 23, 43, 54, 54, 3, 4, 43, 26, +26, 6, 24, 24, 7, 12, 9, 45, 13, 45, 10, 14, 15, 17, 18, +20, 42, 28, 29, 31, 23, 23, 53, 32, 33, 23, 23, 11, 23, 39, +26, 44, 43, 23, 24, 5, 30, 9, 46, 52, 43, 10, 34, 47, 38, +40, 43, 11, 41, 48, 49, 50, 51, 56, 61, 5, 65, 9, nil, nil, +nil, 10, 23, 66, 26, nil, nil, nil, 66, 16, 58, nil, nil, nil, nil, +43, 57, nil, nil, nil, nil, nil, nil, nil, 23, 23, nil, nil, 23, 66, +66, nil, nil, nil, nil, 26, 26, nil, nil, nil, nil, 23, nil, 23, nil, +nil, nil, nil, 52, 23, 11, 23, 23, nil, nil, nil, nil, 26, 9, 9, +9, nil, nil, 10, 10, nil, nil, nil, nil, nil, 45, nil, nil, nil, nil, +nil, nil, nil, 26, 26, nil, nil, nil, nil, 43, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, 26, 26, nil, nil, 23, nil, +nil, 26, nil, nil, 43, nil, nil, nil, 43, 23, 23, 43, nil, nil, nil, +nil, nil, 23, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 23, 23, 23, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 23, 23, nil, 23, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 43] + +racc_goto_pointer = [nil, 25, 30, 41, 42, 13, 46, 37, nil, 15, 19, 5, -2, 1, -42, 5, -156, -217, 7, -138, -107, nil, -264, 3, -45, -132, -50, nil, 10, -212, 14, 64, 68, 69, 20, nil, nil, nil, 22, 7, 23, 26, -8, -26, 22, -108, 83, 88, 94, 95, 96, 97, -62, -2, 6, nil, -55, -144, -150, nil, nil, 63, nil, nil, nil, 49, -162, nil] + +racc_goto_default = [ +nil, nil, nil, nil, nil, 84, nil, 7, 8, 72, 73, 74, nil, nil, nil, +nil, nil, nil, nil, nil, nil, 238, 252, 62, 107, 106, nil, 114, nil, 246, +86, nil, nil, nil, 76, 19, 20, 21, nil, nil, 85, nil, nil, 41, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 78, 79, 80, 81, 82, +83, 35, 37, 38, 39, 119, 120, 122] + +racc_reduce_table = [ + 0, 0, :racc_error, + 1, 38, :_reduce_none, + 1, 38, :_reduce_none, + 1, 38, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 42, :_reduce_none, + 1, 42, :_reduce_none, + 1, 44, :_reduce_8, + 1, 44, :_reduce_9, + 1, 44, :_reduce_10, + 2, 45, :_reduce_11, + 3, 43, :_reduce_12, + 1, 49, :_reduce_none, + 2, 49, :_reduce_14, + 5, 50, :_reduce_15, + 1, 50, :_reduce_none, + 8, 55, :_reduce_17, + 1, 51, :_reduce_18, + 2, 51, :_reduce_19, + 2, 51, :_reduce_20, + 1, 57, :_reduce_none, + 5, 57, :_reduce_22, + 3, 56, :_reduce_23, + 5, 56, :_reduce_24, + 4, 56, :_reduce_25, + 4, 46, :_reduce_26, + 1, 61, :_reduce_none, + 1, 63, :_reduce_none, + 3, 47, :_reduce_29, + 3, 48, :_reduce_30, + 1, 52, :_reduce_none, + 1, 53, :_reduce_none, + 1, 54, :_reduce_none, + 1, 40, :_reduce_none, + 1, 40, :_reduce_none, + 1, 40, :_reduce_none, + 1, 40, :_reduce_none, + 1, 67, :_reduce_38, + 1, 67, :_reduce_none, + 1, 67, :_reduce_none, + 1, 67, :_reduce_none, + 4, 71, :_reduce_42, + 4, 71, :_reduce_43, + 4, 72, :_reduce_44, + 4, 73, :_reduce_45, + 7, 74, :_reduce_46, + 3, 68, :_reduce_47, + 1, 75, :_reduce_none, + 1, 75, :_reduce_none, + 1, 75, :_reduce_none, + 1, 75, :_reduce_none, + 1, 75, :_reduce_none, + 1, 76, :_reduce_none, + 1, 76, :_reduce_none, + 2, 69, :_reduce_55, + 3, 69, :_reduce_56, + 5, 79, :_reduce_57, + 2, 79, :_reduce_58, + 4, 70, :_reduce_59, + 2, 81, :_reduce_60, + 2, 81, :_reduce_61, + 2, 81, :_reduce_62, + 2, 81, :_reduce_63, + 1, 41, :_reduce_none, + 1, 41, :_reduce_none, + 1, 41, :_reduce_none, + 1, 41, :_reduce_none, + 1, 41, :_reduce_none, + 1, 41, :_reduce_none, + 1, 41, :_reduce_none, + 1, 41, :_reduce_none, + 2, 83, :_reduce_72, + 3, 88, :_reduce_73, + 4, 88, :_reduce_74, + 5, 88, :_reduce_75, + 2, 87, :_reduce_76, + 4, 86, :_reduce_77, + 4, 86, :_reduce_78, + 3, 84, :_reduce_79, + 3, 85, :_reduce_80, + 1, 91, :_reduce_81, + 5, 91, :_reduce_82, + 3, 91, :_reduce_83, + 3, 91, :_reduce_84, + 3, 91, :_reduce_85, + 1, 91, :_reduce_86, + 1, 91, :_reduce_87, + 1, 93, :_reduce_88, + 3, 93, :_reduce_89, + 1, 95, :_reduce_none, + 1, 95, :_reduce_none, + 1, 96, :_reduce_none, + 1, 96, :_reduce_none, + 1, 96, :_reduce_none, + 2, 92, :_reduce_95, + 2, 94, :_reduce_96, + 2, 94, :_reduce_97, + 2, 94, :_reduce_98, + 3, 97, :_reduce_99, + 3, 97, :_reduce_100, + 3, 97, :_reduce_101, + 5, 78, :_reduce_102, + 6, 78, :_reduce_103, + 7, 78, :_reduce_104, + 6, 78, :_reduce_105, + 6, 78, :_reduce_106, + 1, 77, :_reduce_none, + 4, 77, :_reduce_108, + 1, 98, :_reduce_109, + 1, 98, :_reduce_110, + 1, 98, :_reduce_111, + 2, 99, :_reduce_112, + 4, 100, :_reduce_113, + 4, 100, :_reduce_114, + 5, 100, :_reduce_115, + 5, 100, :_reduce_116, + 4, 101, :_reduce_117, + 5, 101, :_reduce_118, + 7, 101, :_reduce_119, + 4, 101, :_reduce_120, + 5, 101, :_reduce_121, + 7, 101, :_reduce_122, + 9, 101, :_reduce_123, + 7, 101, :_reduce_124, + 9, 101, :_reduce_125, + 0, 82, :_reduce_126, + 1, 82, :_reduce_none, + 1, 60, :_reduce_128, + 1, 60, :_reduce_none, + 1, 80, :_reduce_none, + 1, 80, :_reduce_none, + 1, 80, :_reduce_none, + 1, 80, :_reduce_none, + 1, 80, :_reduce_none, + 1, 80, :_reduce_none, + 1, 80, :_reduce_none, + 1, 80, :_reduce_none, + 1, 80, :_reduce_none, + 2, 62, :_reduce_139, + 2, 62, :_reduce_140, + 2, 62, :_reduce_141, + 2, 62, :_reduce_142, + 1, 58, :_reduce_none, + 2, 58, :_reduce_144, + 2, 102, :_reduce_145, + 2, 102, :_reduce_146, + 2, 102, :_reduce_147, + 2, 102, :_reduce_148, + 2, 102, :_reduce_149, + 2, 102, :_reduce_150, + 2, 65, :_reduce_none, + 1, 65, :_reduce_none, + 1, 103, :_reduce_none, + 2, 103, :_reduce_154, + 2, 103, :_reduce_155, + 2, 103, :_reduce_156, + 2, 103, :_reduce_157, + 2, 103, :_reduce_158, + 2, 103, :_reduce_159, + 1, 104, :_reduce_none, + 2, 104, :_reduce_161, + 1, 64, :_reduce_none, + 2, 64, :_reduce_163, + 1, 59, :_reduce_none, + 2, 59, :_reduce_165, + 2, 59, :_reduce_166, + 2, 59, :_reduce_167, + 2, 66, :_reduce_none, + 1, 66, :_reduce_none, + 1, 90, :_reduce_170, + 2, 90, :_reduce_171, + 3, 90, :_reduce_172, + 4, 90, :_reduce_173, + 1, 89, :_reduce_174, + 2, 89, :_reduce_175 ] + +racc_reduce_n = 176 + +racc_shift_n = 320 + +racc_token_table = { + false => 0, + :error => 1, + :T => 2, + :Z => 3, + :E => 4, + :X => 5, + :U => 6, + :UNKNOWN => 7, + :OPEN => 8, + :LONGYEAR => 9, + :UNMATCHED => 10, + :DOTS => 11, + :UA => 12, + :PUA => 13, + "-" => 14, + ":" => 15, + "2" => 16, + "4" => 17, + "0" => 18, + "+" => 19, + "1" => 20, + "/" => 21, + "3" => 22, + "^" => 23, + "[" => 24, + "]" => 25, + "{" => 26, + "}" => 27, + "," => 28, + "(" => 29, + ")" => 30, + "-(" => 31, + "5" => 32, + "6" => 33, + "7" => 34, + "8" => 35, + "9" => 36 } + +racc_nt_base = 37 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ + "$end", + "error", + "T", + "Z", + "E", + "X", + "U", + "UNKNOWN", + "OPEN", + "LONGYEAR", + "UNMATCHED", + "DOTS", + "UA", + "PUA", + "\"-\"", + "\":\"", + "\"2\"", + "\"4\"", + "\"0\"", + "\"+\"", + "\"1\"", + "\"/\"", + "\"3\"", + "\"^\"", + "\"[\"", + "\"]\"", + "\"{\"", + "\"}\"", + "\",\"", + "\"(\"", + "\")\"", + "\"-(\"", + "\"5\"", + "\"6\"", + "\"7\"", + "\"8\"", + "\"9\"", + "$start", + "edtf", + "level_0_expression", + "level_1_expression", + "level_2_expression", + "date", + "date_time", + "positive_date", + "negative_date", + "year", + "year_month", + "year_month_day", + "time", + "base_time", + "zone_offset", + "hour", + "minute", + "second", + "midnight", + "zone_offset_hour", + "positive_zone_offset", + "d01_13", + "d01_59", + "digit", + "month", + "d01_12", + "day", + "d01_31", + "d00_23", + "d00_59", + "unspecified", + "level_1_interval", + "long_year_simple", + "season", + "unspecified_year", + "unspecified_month", + "unspecified_day", + "unspecified_day_and_month", + "level_1_start", + "level_1_end", + "partial_uncertain_or_approximate", + "partial_unspecified", + "long_year", + "positive_digit", + "season_number", + "ua", + "season_qualified", + "choice_list", + "inclusive_list", + "masked_precision", + "date_and_calendar", + "long_year_scientific", + "integer", + "int1_4", + "list", + "earlier", + "list_elements", + "later", + "list_element", + "atomic", + "consecutives", + "pua_base", + "pua_year", + "pua_year_month", + "pua_year_month_day", + "d01_23", + "d01_29", + "d01_30" ] + +Racc_debug_parser = false + +##### State transition tables end ##### + +# reduce 0 omitted + +# reduce 1 omitted + +# reduce 2 omitted + +# reduce 3 omitted + +# reduce 4 omitted + +# reduce 5 omitted + +# reduce 6 omitted + +# reduce 7 omitted + +module_eval(<<'.,.,', 'edtf.y', 54) + def _reduce_8(val, _values, result) + result = Date.new(val[0]).year_precision! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 55) + def _reduce_9(val, _values, result) + result = Date.new(*val.flatten).month_precision! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 56) + def _reduce_10(val, _values, result) + result = Date.new(*val.flatten).day_precision! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 59) + def _reduce_11(val, _values, result) + result = -val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 63) + def _reduce_12(val, _values, result) + result = DateTime.new(val[0].year, val[0].month, val[0].day, *val[2]) + result.skip_timezone = (val[2].length == 3) + + result + end +.,., + +# reduce 13 omitted + +module_eval(<<'.,.,', 'edtf.y', 68) + def _reduce_14(val, _values, result) + result = val.flatten + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 70) + def _reduce_15(val, _values, result) + result = val.values_at(0, 2, 4) + result + end +.,., + +# reduce 16 omitted + +module_eval(<<'.,.,', 'edtf.y', 73) + def _reduce_17(val, _values, result) + result = [24, 0, 0] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 75) + def _reduce_18(val, _values, result) + result = 0 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 76) + def _reduce_19(val, _values, result) + result = -1 * val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 77) + def _reduce_20(val, _values, result) + result = val[1] + result + end +.,., + +# reduce 21 omitted + +module_eval(<<'.,.,', 'edtf.y', 81) + def _reduce_22(val, _values, result) + result = 0 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 85) + def _reduce_23(val, _values, result) + result = Rational(val[0] * 60 + val[2], 1440) + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 86) + def _reduce_24(val, _values, result) + result = Rational(840, 1440) + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 87) + def _reduce_25(val, _values, result) + result = Rational(val[3], 1440) + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 91) + def _reduce_26(val, _values, result) + result = val.zip([1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b } + + result + end +.,., + +# reduce 27 omitted + +# reduce 28 omitted + +module_eval(<<'.,.,', 'edtf.y', 97) + def _reduce_29(val, _values, result) + result = [val[0], val[2]] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 104) + def _reduce_30(val, _values, result) + result = val[0] << val[2] + if result[2] > 31 || (result[2] > 30 && [2,4,6,9,11].include?(result[1])) || (result[2] > 29 && result[1] == 2) + raise ArgumentError, "invalid date (invalid days #{result[2]} for month #{result[1]})" + end + + result + end +.,., + +# reduce 31 omitted + +# reduce 32 omitted + +# reduce 33 omitted + +# reduce 34 omitted + +# reduce 35 omitted + +# reduce 36 omitted + +# reduce 37 omitted + +module_eval(<<'.,.,', 'edtf.y', 127) + def _reduce_38(val, _values, result) + result = Date.new(val[0][0]).year_precision! + result.unspecified.year[2,2] = val[0][1] + + result + end +.,., + +# reduce 39 omitted + +# reduce 40 omitted + +# reduce 41 omitted + +module_eval(<<'.,.,', 'edtf.y', 138) + def _reduce_42(val, _values, result) + result = [val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }, [false,true]] + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 142) + def _reduce_43(val, _values, result) + result = [val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }, [true, true]] + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 146) + def _reduce_44(val, _values, result) + result = Date.new(val[0]).unspecified!(:month) + result.precision = :month + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 151) + def _reduce_45(val, _values, result) + result = Date.new(*val[0]).unspecified!(:day) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 155) + def _reduce_46(val, _values, result) + result = Date.new(val[0]).unspecified!([:day,:month]) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 160) + def _reduce_47(val, _values, result) + result = Interval.new(val[0], val[2]) + + result + end +.,., + +# reduce 48 omitted + +# reduce 49 omitted + +# reduce 50 omitted + +# reduce 51 omitted + +# reduce 52 omitted + +# reduce 53 omitted + +# reduce 54 omitted + +module_eval(<<'.,.,', 'edtf.y', 171) + def _reduce_55(val, _values, result) + result = Date.new(val[1]) + result.precision = :year + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 176) + def _reduce_56(val, _values, result) + result = Date.new(-1 * val[2]) + result.precision = :year + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 183) + def _reduce_57(val, _values, result) + result = val.zip([10000,1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b } + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 185) + def _reduce_58(val, _values, result) + result = 10 * val[0] + val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 190) + def _reduce_59(val, _values, result) + result = Season.new(val[0], val[2]) + val[3].each { |ua| result.send(ua) } + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 194) + def _reduce_60(val, _values, result) + result = 21 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 195) + def _reduce_61(val, _values, result) + result = 22 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 196) + def _reduce_62(val, _values, result) + result = 23 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 197) + def _reduce_63(val, _values, result) + result = 24 + result + end +.,., + +# reduce 64 omitted + +# reduce 65 omitted + +# reduce 66 omitted + +# reduce 67 omitted + +# reduce 68 omitted + +# reduce 69 omitted + +# reduce 70 omitted + +# reduce 71 omitted + +module_eval(<<'.,.,', 'edtf.y', 215) + def _reduce_72(val, _values, result) + result = val[0]; result.qualifier = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 221) + def _reduce_73(val, _values, result) + result = Date.new(val[0].year * 10 ** val[2]).year_precision! + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 225) + def _reduce_74(val, _values, result) + result = Date.new(val[1] * 10 ** val[3]).year_precision! + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 229) + def _reduce_75(val, _values, result) + result = Date.new(-1 * val[2] * 10 ** val[4]).year_precision! + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 234) + def _reduce_76(val, _values, result) + result = val[0]; result.calendar = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 240) + def _reduce_77(val, _values, result) + d = val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b } + result = EDTF::Decade.new(d) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 245) + def _reduce_78(val, _values, result) + d = val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b } + result = EDTF::Century.new(d) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 251) + def _reduce_79(val, _values, result) + result = val[1].choice! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 253) + def _reduce_80(val, _values, result) + result = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 255) + def _reduce_81(val, _values, result) + result = EDTF::Set.new(val[0]).earlier! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 256) + def _reduce_82(val, _values, result) + result = EDTF::Set.new([val[0]] + val[2] + [val[4]]).earlier!.later! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 257) + def _reduce_83(val, _values, result) + result = EDTF::Set.new([val[0]] + val[2]).earlier! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 258) + def _reduce_84(val, _values, result) + result = EDTF::Set.new([val[0]] + [val[2]]).earlier!.later! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 259) + def _reduce_85(val, _values, result) + result = EDTF::Set.new(val[0] + [val[2]]).later! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 260) + def _reduce_86(val, _values, result) + result = EDTF::Set.new(*val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 261) + def _reduce_87(val, _values, result) + result = EDTF::Set.new(val[0]).later! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 264) + def _reduce_88(val, _values, result) + result = [val[0]].flatten + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 265) + def _reduce_89(val, _values, result) + result = val[0] + [val[2]].flatten + result + end +.,., + +# reduce 90 omitted + +# reduce 91 omitted + +# reduce 92 omitted + +# reduce 93 omitted + +# reduce 94 omitted + +module_eval(<<'.,.,', 'edtf.y', 277) + def _reduce_95(val, _values, result) + result = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 279) + def _reduce_96(val, _values, result) + result = Date.new(*val[0]).year_precision! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 280) + def _reduce_97(val, _values, result) + result = Date.new(*val[0]).month_precision! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 281) + def _reduce_98(val, _values, result) + result = Date.new(val[0]).year_precision! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 284) + def _reduce_99(val, _values, result) + result = (Date.new(val[0]).day_precision! .. Date.new(val[2]).day_precision!) + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 285) + def _reduce_100(val, _values, result) + result = (Date.new(val[0]).month_precision! .. Date.new(val[2]).month_precision!) + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 286) + def _reduce_101(val, _values, result) + result = (Date.new(val[0]).year_precision! .. Date.new(val[2]).year_precision!) + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 292) + def _reduce_102(val, _values, result) + result = Date.new(val[0][0], val[2], val[4]) + result.unspecified.year[2,2] = val[0][1] + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 297) + def _reduce_103(val, _values, result) + result = Date.new(val[0][0], 1, val[5]) + result.unspecified.year[2,2] = val[0][1] + result.unspecified!(:month) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 303) + def _reduce_104(val, _values, result) + result = Date.new(val[0][0], 1, 1) + result.unspecified.year[2,2] = val[0][1] + result.unspecified!([:month, :day]) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 309) + def _reduce_105(val, _values, result) + result = Date.new(val[0][0], val[2], 1) + result.unspecified.year[2,2] = val[0][1] + result.unspecified!(:day) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 315) + def _reduce_106(val, _values, result) + result = Date.new(val[0], 1, val[5]) + result.unspecified!(:month) + + result + end +.,., + +# reduce 107 omitted + +module_eval(<<'.,.,', 'edtf.y', 322) + def _reduce_108(val, _values, result) + result = uoa(val[1], val[3]) + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 325) + def _reduce_109(val, _values, result) + result = val[0].year_precision! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 326) + def _reduce_110(val, _values, result) + result = val[0][0].month_precision! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 327) + def _reduce_111(val, _values, result) + result = val[0].day_precision! + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 329) + def _reduce_112(val, _values, result) + result = uoa(Date.new(val[0]), val[1], :year) + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 333) + def _reduce_113(val, _values, result) + result = [uoa(val[0].change(:month => val[2]), val[3], [:month, :year])] + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 336) + def _reduce_114(val, _values, result) + result = [uoa(Date.new(val[0], val[2]), val[3], [:year, :month])] + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 339) + def _reduce_115(val, _values, result) + result = [uoa(Date.new(val[0], val[2]), val[4], [:month]), true] + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 342) + def _reduce_116(val, _values, result) + result = [uoa(val[0].change(:month => val[2]), val[4], [:month]), true] + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 348) + def _reduce_117(val, _values, result) + result = uoa(val[0][0].change(:day => val[2]), val[3], val[0][1] ? [:day] : nil) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 351) + def _reduce_118(val, _values, result) + result = uoa(val[0][0].change(:day => val[2]), val[4], [:day]) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 354) + def _reduce_119(val, _values, result) + result = uoa(uoa(Date.new(val[0], val[2], val[5]), val[4], :month), val[6], :day) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 357) + def _reduce_120(val, _values, result) + result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[3]) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 360) + def _reduce_121(val, _values, result) + result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[4], [:day]) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 363) + def _reduce_122(val, _values, result) + result = uoa(Date.new(val[0], val[2], val[4]), val[6], [:month, :day]) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 366) + def _reduce_123(val, _values, result) + result = Date.new(val[0], val[2], val[4]) + result = uoa(result, val[6], [:day]) + result = uoa(result, val[8], [:month, :day]) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 371) + def _reduce_124(val, _values, result) + result = val[0].change(:month => val[2], :day => val[4]) + result = uoa(result, val[6], [:month, :day]) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 375) + def _reduce_125(val, _values, result) + result = val[0].change(:month => val[2], :day => val[4]) + result = uoa(result, val[6], [:day]) + result = uoa(result, val[8], [:month, :day]) + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 386) + def _reduce_126(val, _values, result) + result = [] + result + end +.,., + +# reduce 127 omitted + +module_eval(<<'.,.,', 'edtf.y', 390) + def _reduce_128(val, _values, result) + result = 0 + result + end +.,., + +# reduce 129 omitted + +# reduce 130 omitted + +# reduce 131 omitted + +# reduce 132 omitted + +# reduce 133 omitted + +# reduce 134 omitted + +# reduce 135 omitted + +# reduce 136 omitted + +# reduce 137 omitted + +# reduce 138 omitted + +module_eval(<<'.,.,', 'edtf.y', 396) + def _reduce_139(val, _values, result) + result = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 397) + def _reduce_140(val, _values, result) + result = 10 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 398) + def _reduce_141(val, _values, result) + result = 11 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 399) + def _reduce_142(val, _values, result) + result = 12 + result + end +.,., + +# reduce 143 omitted + +module_eval(<<'.,.,', 'edtf.y', 403) + def _reduce_144(val, _values, result) + result = 13 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 406) + def _reduce_145(val, _values, result) + result = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 407) + def _reduce_146(val, _values, result) + result = 10 + val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 408) + def _reduce_147(val, _values, result) + result = 20 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 409) + def _reduce_148(val, _values, result) + result = 21 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 410) + def _reduce_149(val, _values, result) + result = 22 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 411) + def _reduce_150(val, _values, result) + result = 23 + result + end +.,., + +# reduce 151 omitted + +# reduce 152 omitted + +# reduce 153 omitted + +module_eval(<<'.,.,', 'edtf.y', 419) + def _reduce_154(val, _values, result) + result = 24 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 420) + def _reduce_155(val, _values, result) + result = 25 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 421) + def _reduce_156(val, _values, result) + result = 26 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 422) + def _reduce_157(val, _values, result) + result = 27 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 423) + def _reduce_158(val, _values, result) + result = 28 + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 424) + def _reduce_159(val, _values, result) + result = 29 + result + end +.,., + +# reduce 160 omitted + +module_eval(<<'.,.,', 'edtf.y', 428) + def _reduce_161(val, _values, result) + result = 30 + result + end +.,., + +# reduce 162 omitted + +module_eval(<<'.,.,', 'edtf.y', 432) + def _reduce_163(val, _values, result) + result = 31 + result + end +.,., + +# reduce 164 omitted + +module_eval(<<'.,.,', 'edtf.y', 436) + def _reduce_165(val, _values, result) + result = 30 + val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 437) + def _reduce_166(val, _values, result) + result = 40 + val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 438) + def _reduce_167(val, _values, result) + result = 50 + val[1] + result + end +.,., + +# reduce 168 omitted + +# reduce 169 omitted + +module_eval(<<'.,.,', 'edtf.y', 445) + def _reduce_170(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 446) + def _reduce_171(val, _values, result) + result = 10 * val[0] + val[1] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 449) + def _reduce_172(val, _values, result) + result = val.zip([100,10,1]).reduce(0) { |s,(a,b)| s += a * b } + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 453) + def _reduce_173(val, _values, result) + result = val.zip([1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b } + + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 457) + def _reduce_174(val, _values, result) + result = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'edtf.y', 458) + def _reduce_175(val, _values, result) + result = 10 * val[0] + val[1] + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] +end + + end # class Parser + end # module EDTF diff --git a/test/regress/empty.out b/test/regress/empty.out new file mode 100644 index 00000000..a76c7320 --- /dev/null +++ b/test/regress/empty.out @@ -0,0 +1 @@ +Error: test/assets/empty.y: no rules in input diff --git a/test/regress/eye-of-newt.rb b/test/regress/eye-of-newt.rb new file mode 100644 index 00000000..01547515 --- /dev/null +++ b/test/regress/eye-of-newt.rb @@ -0,0 +1,419 @@ +# +# DO NOT MODIFY!!!! +# This file was automatically generated by Racc 2.0.0.dev +# (codename: Mecha Oishii) from Racc grammar file "eye-of-newt.y". +# + +require 'racc/parser.rb' +module EyeOfNewt + class Parser < Racc::Parser + +module_eval(<<'...end eye-of-newt.y/module_eval...', 'eye-of-newt.y', 74) + + def initialize(tokenizer, units:, ingredient: nil) + @tokenizer = tokenizer + @units = units + @ingredient = ingredient || default_ingredient + super() + end + + def next_token + @tokenizer.next_token + end + + def parse + do_parse + @ingredient + rescue Racc::ParseError + raise InvalidIngredient, @tokenizer.string + end + + def to_unit(u) + @units[u] + end + + def default_ingredient + EyeOfNewt::Ingredient.new(amount: 1, unit: @units.default) + end +...end eye-of-newt.y/module_eval... +##### State transition tables begin ### + +racc_action_table = [-47, 22, 19, 21, 12, 32, 20, -47, 11, -47, 13, - +47, 14, 19, 12, 12, 35, 20, 38, 24, 36, 25, 14, 19, 19, 39, +40, 20, 20, 24, 24, 25, 25, 29, - +35, 30, 31, 12, 42, 58, 46, 47, 30, 31, 30, 31, 44, 48, 31, +42, 42, 59, 60, 21, 21, 63, 46, 64, 65, 31, 31, 68, 69] + +racc_action_check = [ +11, 1, 0, 0, 0, 4, 0, 11, 0, 11, 0, 11, 0, 2, 6, +7, 6, 2, 8, 2, 6, 2, 6, 18, 32, 9, 9, 18, 32, 18, +32, 18, 32, 3, 13, 3, 3, 33, 14, 33, 21, 21, 23, 23, 26, +26, 15, 22, 27, 30, 31, 34, 37, 39, 40, 41, 44, 46, 47, 49, +51, 55, 57] + +racc_action_pointer = [0, 1, 11, 24, - +2, nil, 10, 11, 12, 11, nil, 0, nil, 30, 33, 43, nil, nil, 21, +nil, nil, 24, 47, 31, nil, nil, 33, 36, nil, nil, 44, 45, 22, 33, +45, nil, nil, 46, nil, 50, 51, 42, nil, nil, 40, nil, 54, 55, nil, +47, nil, 48, nil, nil, nil, 48, nil, 56, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil] + +racc_action_default = [-53, -53, -53, -12, -14, -15, -23, -53, -27, -28, -29, -30, -31, -49, -53, -39, -41, -42, -44, -46, -48, -50, -53, -8, -47, -49, -10, -11, -6, -32, -53, -53, -53, -21, -19, -22, -35, -25, -26, -53, -53, -53, -45, -40, -53, -43, -53, -53, 70, -7, -2, -9, -4, -5, -33, -53, -13, -17, -20, -18, -24, -37, -38, -36, -51, -52, -1, -3, -34, -16] + +racc_goto_table = [ +28, 9, 8, 1, 3, 27, 23, 7, 34, 37, 41, 2, 26, 33, 45, +6, 10, 43, nil, nil, 50, nil, nil, 52, 53, 49, 54, 55, 51, nil, +nil, nil, nil, nil, nil, 57, 56, nil, nil, nil, 61, 62, nil, nil, nil, +nil, 66, nil, 67] + +racc_goto_check = [ +5, 12, 11, 1, 3, 4, 3, 10, 11, 11, 14, 2, 6, 10, 8, +9, 13, 16, nil, nil, 5, nil, nil, 5, 5, 4, 14, 14, 4, nil, +nil, nil, nil, nil, nil, 11, 3, nil, nil, nil, 12, 12, nil, nil, nil, +nil, 5, nil, 5] + +racc_goto_pointer = [nil, 3, 11, 4, 2, -3, 9, nil, -4, 15, 7, 2, 1, 16, -4, nil, 2, nil, nil] + +racc_goto_default = [ +nil, nil, nil, nil, nil, nil, nil, 4, 5, nil, nil, nil, nil, nil, nil, +15, 16, 17, 18] + +racc_reduce_table = [ + 0, 0, :racc_error, + 4, 19, :_reduce_none, + 3, 19, :_reduce_none, + 4, 19, :_reduce_none, + 3, 19, :_reduce_none, + 3, 19, :_reduce_none, + 2, 19, :_reduce_none, + 3, 19, :_reduce_none, + 2, 19, :_reduce_none, + 3, 19, :_reduce_none, + 2, 19, :_reduce_none, + 2, 19, :_reduce_none, + 1, 19, :_reduce_none, + 3, 21, :_reduce_none, + 1, 21, :_reduce_none, + 1, 25, :_reduce_15, + 4, 20, :_reduce_none, + 3, 20, :_reduce_none, + 3, 20, :_reduce_none, + 2, 20, :_reduce_none, + 3, 20, :_reduce_none, + 2, 20, :_reduce_none, + 2, 20, :_reduce_none, + 1, 20, :_reduce_none, + 3, 20, :_reduce_none, + 2, 20, :_reduce_none, + 2, 20, :_reduce_none, + 1, 20, :_reduce_none, + 1, 27, :_reduce_28, + 1, 27, :_reduce_29, + 1, 27, :_reduce_30, + 1, 29, :_reduce_31, + 1, 24, :_reduce_32, + 2, 22, :_reduce_33, + 3, 23, :_reduce_34, + 1, 28, :_reduce_35, + 3, 28, :_reduce_36, + 3, 31, :_reduce_37, + 3, 31, :_reduce_38, + 1, 30, :_reduce_none, + 2, 30, :_reduce_40, + 1, 30, :_reduce_none, + 1, 30, :_reduce_none, + 2, 26, :_reduce_43, + 1, 26, :_reduce_none, + 1, 32, :_reduce_none, + 1, 36, :_reduce_none, + 1, 36, :_reduce_none, + 1, 36, :_reduce_none, + 1, 36, :_reduce_none, + 1, 33, :_reduce_50, + 3, 34, :_reduce_51, + 3, 35, :_reduce_52 ] + +racc_reduce_n = 53 + +racc_shift_n = 70 + +racc_token_table = { + false => 0, + :error => 1, + :WORD => 2, + :NUMBER => 3, + :UNIT => 4, + :TEXT => 5, + :OF => 6, + :OR => 7, + :A => 8, + :TO_TASTE => 9, + :UNIT_MODIFIER => 10, + "," => 11, + "(" => 12, + ")" => 13, + "-" => 14, + "\xE2\x80\x93" => 15, + "/" => 16, + "." => 17 } + +racc_nt_base = 18 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ + "$end", + "error", + "WORD", + "NUMBER", + "UNIT", + "TEXT", + "OF", + "OR", + "A", + "TO_TASTE", + "UNIT_MODIFIER", + "\",\"", + "\"(\"", + "\")\"", + "\"-\"", + "\"\\xE2\\x80\\x93\"", + "\"/\"", + "\".\"", + "$start", + "ingredient", + "quantity", + "ingredient_names", + "style", + "note", + "to_taste", + "ingredient_name", + "ingredient_words", + "amount", + "unit_modifier", + "unit", + "numerical_amount", + "numerical_range", + "text", + "number", + "fraction", + "decimal", + "ingredient_word" ] + +Racc_debug_parser = false + +##### State transition tables end ##### + +# reduce 0 omitted + +# reduce 1 omitted + +# reduce 2 omitted + +# reduce 3 omitted + +# reduce 4 omitted + +# reduce 5 omitted + +# reduce 6 omitted + +# reduce 7 omitted + +# reduce 8 omitted + +# reduce 9 omitted + +# reduce 10 omitted + +# reduce 11 omitted + +# reduce 12 omitted + +# reduce 13 omitted + +# reduce 14 omitted + +module_eval(<<'.,.,', 'eye-of-newt.y', 22) + def _reduce_15(val, _values, result) + @ingredient.names << result + result + end +.,., + +# reduce 16 omitted + +# reduce 17 omitted + +# reduce 18 omitted + +# reduce 19 omitted + +# reduce 20 omitted + +# reduce 21 omitted + +# reduce 22 omitted + +# reduce 23 omitted + +# reduce 24 omitted + +# reduce 25 omitted + +# reduce 26 omitted + +# reduce 27 omitted + +module_eval(<<'.,.,', 'eye-of-newt.y', 39) + def _reduce_28(val, _values, result) + @ingredient.amount = result + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 40) + def _reduce_29(val, _values, result) + @ingredient.amount = result + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 41) + def _reduce_30(val, _values, result) + @ingredient.amount = 1 + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 43) + def _reduce_31(val, _values, result) + @ingredient.unit = to_unit(result) + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 44) + def _reduce_32(val, _values, result) + @ingredient.unit = to_unit(result) + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 45) + def _reduce_33(val, _values, result) + @ingredient.style = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 46) + def _reduce_34(val, _values, result) + @ingredient.note = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 48) + def _reduce_35(val, _values, result) + @ingredient.unit_modifier = val[0] + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 49) + def _reduce_36(val, _values, result) + @ingredient.unit_modifier = val[1] + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 52) + def _reduce_37(val, _values, result) + result = [val[0], val[2]] + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 53) + def _reduce_38(val, _values, result) + result = [val[0], val[2]] + result + end +.,., + +# reduce 39 omitted + +module_eval(<<'.,.,', 'eye-of-newt.y', 57) + def _reduce_40(val, _values, result) + result = val[0] + val[1] + result + end +.,., + +# reduce 41 omitted + +# reduce 42 omitted + +module_eval(<<'.,.,', 'eye-of-newt.y', 62) + def _reduce_43(val, _values, result) + result = val.join(' ') + result + end +.,., + +# reduce 44 omitted + +# reduce 45 omitted + +# reduce 46 omitted + +# reduce 47 omitted + +# reduce 48 omitted + +# reduce 49 omitted + +module_eval(<<'.,.,', 'eye-of-newt.y', 67) + def _reduce_50(val, _values, result) + result = val[0].to_i + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 68) + def _reduce_51(val, _values, result) + result = val[0].to_f / val[2].to_f + result + end +.,., + +module_eval(<<'.,.,', 'eye-of-newt.y', 69) + def _reduce_52(val, _values, result) + result = val.join.to_f + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] +end + + end # class Parser + end # module EyeOfNewt diff --git a/test/regress/huia.rb b/test/regress/huia.rb new file mode 100644 index 00000000..0590cbca --- /dev/null +++ b/test/regress/huia.rb @@ -0,0 +1,1489 @@ +# +# DO NOT MODIFY!!!! +# This file was automatically generated by Racc 2.0.0.dev +# (codename: Mecha Oishii) from Racc grammar file "huia.y". +# + +require 'racc/parser.rb' +module Huia + class Parser < Racc::Parser + +module_eval(<<'...end huia.y/module_eval...', 'huia.y', 211) + +attr_accessor :lexer, :scopes, :state + +def initialize lexer + @lexer = lexer + @state = [] + @scopes = [] + push_scope +end + +def ast + @ast ||= do_parse + @scopes.first +end + +def on_error t, val, vstack + line = lexer.line + col = lexer.column + message = "Unexpected #{token_to_str t} at #{lexer.filename} line #{line}:#{col}:\n\n" + + start = line - 5 > 0 ? line - 5 : 0 + i_size = line.to_s.size + (start..(start + 5)).each do |i| + message << sprintf("\t%#{i_size}d: %s\n", i, lexer.get_line(i)) + message << "\t#{' ' * i_size} #{'-' * (col - 1)}^\n" if i == line + end + + raise SyntaxError, message +end + +def next_token + nt = lexer.next_computed_token + # just use a state stack for now, we'll have to do something + # more sophisticated soon. + if nt && nt.first == :state + if nt.last + state.push << nt.last + else + state.pop + end + next_token + else + nt + end +end + +def push_scope + new_scope = Huia::AST::Scope.new scope + new_scope.file = lexer.filename + new_scope.line = lexer.line + new_scope.column = lexer.column + scopes.push new_scope + new_scope +end + +def pop_scope + scopes.pop +end + +def scope + scopes.last +end + +def binary left, right, method + node(:MethodCall, left, node(:CallSignature, method, [right])) +end + +def unary left, method + node(:MethodCall, left, node(:CallSignature, method)) +end + +def node type, *args + Huia::AST.const_get(type).new(*args).tap do |n| + n.file = lexer.filename + n.line = lexer.line + n.column = lexer.column + end +end +alias n node + +def allocate_local name + node(:Variable, name).tap do |n| + scope.allocate_local n + end +end + +def allocate_local_assignment name, value + node(:Assignment, name, value).tap do |n| + scope.allocate_local n + end +end + +def this_closure + allocate_local('@') +end + +def scope_instance + node(:ScopeInstance, scope) +end + +def constant name + return scope_instance if name == 'self' + node(:Constant, name) +end + +def to_string expr + node(:MethodCall, expr, node(:CallSignature, 'toString')) +end +...end huia.y/module_eval... +##### State transition tables begin ### + +racc_action_table = [ +81, 106, 40, 37, 61, 62, 123, 153, 135, 71, 72, 77, 155, 178, 179, +39, 164, 37, 37, 5, 6, 137, 152, 73, 74, 75, 36, 36, 76, 28, +154, 80, 166, 172, 180, 22, 23, 37, 26, 27, 182, 60, 63, 19, 164, +40, 36, 61, 62, 186, nil, 33, 71, 72, 77, nil, nil, 134, 39, 133, +129, 37, 5, 6, nil, nil, 73, 74, 75, nil, 36, 76, 28, 134, 80, +169, 129, nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, +61, 62, nil, nil, 33, 71, 72, 77, nil, nil, nil, 39, nil, nil, 37, +nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, nil, nil, +nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, 61, 62, +nil, nil, 33, 71, 72, 77, nil, nil, nil, 39, nil, nil, 37, nil, nil, +nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, +23, nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, nil, +33, 71, 72, 77, nil, nil, nil, 39, nil, nil, 37, nil, nil, nil, nil, +73, 74, 75, nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, 23, nil, +26, 27, nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, nil, 33, 71, +72, 77, nil, 114, nil, 39, nil, nil, 37, nil, nil, 113, nil, 73, 74, +75, nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, +nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, 77, +nil, nil, nil, 39, nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, nil, +36, 76, 28, nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, +63, 19, nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, nil, +nil, 39, nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, +28, nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, +nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, nil, nil, 39, +nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, +80, nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, nil, 40, +nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, nil, nil, 39, nil, nil, +37, nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, nil, +nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, 61, +62, nil, nil, 33, 71, 72, 77, nil, nil, nil, 39, nil, nil, 37, nil, +nil, nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, nil, nil, nil, +22, 23, nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, +nil, 33, 71, 72, 77, nil, nil, nil, 39, nil, nil, 37, nil, nil, nil, +nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, 23, +nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, nil, 33, +71, 72, 77, nil, nil, nil, 39, nil, nil, 37, nil, nil, nil, nil, 73, +74, 75, nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, 23, nil, 26, +27, nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, +77, nil, nil, nil, 39, nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, +nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, nil, +60, 63, 19, nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, +nil, nil, 39, nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, nil, 36, +76, 28, nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, +19, nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, nil, nil, +39, nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, 28, +nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, nil, +40, nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, nil, nil, 39, nil, +nil, 37, nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, +nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, +61, 62, nil, nil, 33, 71, 72, 77, nil, nil, nil, 39, nil, nil, 37, +nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, nil, nil, +nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, 61, 62, +nil, nil, 33, 71, 72, 77, nil, nil, nil, 39, nil, nil, 37, nil, nil, +nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, +23, nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, nil, +33, 71, 72, 77, nil, nil, nil, 39, nil, nil, 37, nil, nil, nil, nil, +73, 74, 75, nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, 23, nil, +26, 27, nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, nil, 33, 71, +72, 77, nil, nil, nil, 39, nil, nil, 37, nil, nil, nil, nil, 73, 74, +75, nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, +nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, 77, +nil, nil, nil, 39, nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, nil, +36, 76, 28, nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, +63, 19, nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, nil, +nil, 39, nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, +28, nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, +nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, nil, nil, 39, +nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, +80, nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, nil, 40, +nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, nil, nil, 39, nil, nil, +37, nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, nil, +nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, 61, +62, nil, nil, 33, 71, 72, 77, nil, nil, 160, 39, nil, nil, 37, 5, +6, nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, nil, nil, nil, +22, 23, nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, +nil, 33, 71, 72, 77, nil, nil, nil, 39, nil, nil, 37, nil, nil, nil, +nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, 23, +nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, nil, 33, +71, 72, 77, nil, nil, nil, 39, nil, nil, 37, nil, nil, nil, nil, 73, +74, 75, nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, 23, nil, 26, +27, nil, 60, 63, 19, nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, +77, nil, nil, nil, 39, nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, +nil, 36, 76, 28, nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, nil, +60, 63, 19, nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, +nil, nil, 39, nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, nil, 36, +76, 28, nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, +19, nil, 40, nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, nil, nil, +39, nil, nil, 37, nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, 28, +nil, 80, nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, nil, +40, nil, 61, 62, nil, nil, 33, 71, 72, 77, nil, nil, 160, 39, nil, +nil, 37, 5, 6, nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, +nil, nil, nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, nil, 40, nil, +61, 62, nil, nil, 33, 71, 72, 77, nil, nil, nil, 39, nil, nil, 37, +nil, nil, nil, nil, 73, 74, 75, nil, 36, 76, 28, nil, 80, nil, nil, +nil, 22, 23, nil, 26, 27, nil, 60, 63, 19, 85, 86, 87, 88, nil, +84, nil, 33, 89, nil, nil, nil, nil, 84, 91, 5, 6, 85, 86, 87, +88, nil, 91, nil, nil, 89, nil, nil, nil, nil, 84, nil, 92, 93, 94, +95, 96, 97, 98, 91, 92, 93, 94, 95, 96, 97, 98, nil, 90, nil, +nil, nil, nil, nil, nil, nil, nil, 92, 93, 94, 95, 96, 97, 98, nil, +90, 85, 86, 87, 88, nil, nil, nil, nil, 89, nil, nil, nil, nil, 84, +nil, 85, 86, 87, 88, 156, nil, nil, 91, 89, nil, nil, nil, nil, 84, +nil, nil, nil, nil, nil, nil, nil, nil, 91, nil, nil, 92, 93, 94, 95, +96, 97, 98, nil, 90, nil, nil, nil, nil, nil, nil, 92, 93, 94, 95, +96, 97, 98, nil, 90, 85, 86, 87, 88, nil, nil, nil, nil, 89, nil, +nil, nil, nil, 84, nil, 165, 85, 86, 87, 88, nil, nil, 91, nil, 89, +nil, nil, nil, 167, 84, nil, nil, nil, nil, nil, nil, nil, nil, 91, nil, +92, 93, 94, 95, 96, 97, 98, nil, 90, nil, nil, nil, nil, nil, nil, +nil, 92, 93, 94, 95, 96, 97, 98, nil, 90, 85, 86, 87, 88, nil, +nil, nil, nil, 89, nil, nil, nil, nil, 84, nil, 85, 86, 87, 88, nil, +nil, nil, 91, 89, nil, nil, nil, nil, 84, nil, nil, nil, nil, nil, nil, +nil, nil, 91, nil, nil, 92, 93, 94, 95, 96, 97, 98, nil, 90, nil, +nil, nil, nil, nil, nil, 92, 93, 94, 95, 96, 97, 98, nil, 90, 85, +86, 87, 88, nil, nil, nil, nil, 89, nil, nil, nil, nil, 84, nil, 85, +86, 87, 88, nil, nil, nil, 91, 89, nil, nil, nil, nil, 84, nil, nil, +nil, nil, nil, nil, nil, nil, 91, nil, nil, 92, 93, 94, 95, 96, 97, +98, nil, 90, nil, nil, nil, nil, nil, nil, 92, 93, 94, 95, 96, 97, +98, nil, 90, 85, 86, 87, 88, nil, nil, nil, nil, 89, nil, nil, nil, +nil, 84, nil, 85, 86, 87, 88, nil, nil, nil, 91, 89, nil, nil, nil, +nil, 84, nil, nil, nil, nil, nil, nil, nil, nil, 91, nil, nil, 92, 93, +94, 95, 96, 97, 98, nil, 90, nil, nil, nil, nil, nil, nil, 92, 93, +94, 95, 96, 97, 98, nil, 90, 85, 86, 87, 88, nil, nil, nil, nil, +89, nil, nil, nil, nil, 84, nil, 85, 86, 87, 88, nil, nil, nil, 91, +89, nil, nil, nil, nil, 84, nil, nil, nil, nil, nil, nil, nil, nil, 91, +nil, nil, 92, 93, 94, 95, 96, 97, 98, nil, 90, nil, nil, nil, nil, +nil, nil, 92, 93, 94, 95, 96, 97, 98, nil, 90, 85, 86, 87, 88, +nil, nil, nil, nil, 89, nil, 160, nil, nil, 84, nil, 5, 6, 85, 86, +87, 88, nil, 91, nil, nil, 89, nil, nil, nil, nil, 84, nil, nil, nil, +nil, nil, nil, nil, nil, 91, 92, 93, 94, 95, 96, 97, 98, nil, 90, +nil, nil, nil, nil, nil, nil, nil, nil, 92, 93, 94, 95, 96, 97, 98, +nil, 90, 85, 86, 87, 88, nil, nil, nil, nil, 89, nil, nil, nil, nil, +84, nil, 85, 86, 87, 88, nil, nil, nil, 91, 89, nil, nil, nil, nil, +84, nil, 181, nil, nil, nil, nil, nil, nil, 91, nil, nil, 92, 93, 94, +95, 96, 97, 98, nil, 90, nil, nil, nil, nil, nil, nil, 92, 93, 94, +95, 96, 97, 98, nil, 90, 85, 86, 87, 88, nil, nil, nil, nil, 89, +nil, nil, nil, nil, 84, nil, 85, 86, 87, 88, nil, nil, nil, 91, 89, +nil, nil, nil, nil, 84, nil, nil, nil, nil, nil, nil, nil, nil, 91, nil, +nil, 92, 93, 94, 95, 96, 97, 98, nil, 90, nil, nil, nil, nil, nil, +nil, 92, 93, 94, 95, 96, 97, 98, nil, 90, 87, 88, nil, nil, nil, +nil, 89, nil, nil, nil, nil, 84, 87, 88, nil, nil, nil, nil, 89, nil, +91, nil, nil, 84, nil, 87, 88, nil, nil, nil, nil, 89, 91, nil, nil, +nil, 84, nil, 92, 93, 94, 95, 96, 97, 98, 91, 90, nil, nil, nil, +92, 93, 94, 95, 96, 97, 98, nil, 90, nil, nil, nil, nil, 92, 93, +94, 95, 96, 97, 98, 89, 90, 87, 88, nil, 84, nil, nil, 89, nil, +nil, nil, nil, 84, 91, nil, nil, nil, nil, nil, nil, nil, 91, nil, nil, +89, nil, nil, nil, nil, 84, nil, 92, 93, 94, 95, 96, 97, 98, 91, +92, 93, 94, 95, 96, 97, 98, nil, 90, nil, 89, nil, nil, nil, nil, +84, nil, 92, 93, 94, 95, 96, 97, 98, 91, 89, nil, nil, nil, nil, +84, nil, nil, nil, nil, 89, nil, nil, nil, 91, 84, nil, 92, 93, 94, +95, 96, 97, 98, 91, nil, nil, nil, nil, nil, nil, nil, 92, 93, 94, +95, 96, 97, 98, nil, nil, nil, 92, 93, 94, 95, 96, 97, 98] + +racc_action_check = [ +1, 33, 1, 34, 1, 1, 40, 100, 81, 1, 1, 1, 102, 161, 161, +1, 112, 33, 1, 1, 1, 84, 100, 1, 1, 1, 33, 1, 1, 1, +102, 1, 121, 131, 163, 1, 1, 84, 1, 1, 178, 1, 1, 1, 179, +0, 84, 0, 0, 183, nil, 1, 0, 0, 0, nil, nil, 80, 0, 80, +80, 0, 0, 0, nil, nil, 0, 0, 0, nil, 0, 0, 0, 128, 0, +128, 128, nil, 0, 0, nil, 0, 0, nil, 0, 0, 0, nil, 19, nil, +19, 19, nil, nil, 0, 19, 19, 19, nil, nil, nil, 19, nil, nil, 19, +nil, nil, nil, nil, 19, 19, 19, nil, 19, 19, 19, nil, 19, nil, nil, +nil, 19, 19, nil, 19, 19, nil, 19, 19, 19, nil, 23, nil, 23, 23, +nil, nil, 19, 23, 23, 23, nil, nil, nil, 23, nil, nil, 23, nil, nil, +nil, nil, 23, 23, 23, nil, 23, 23, 23, nil, 23, nil, nil, nil, 23, +23, nil, 23, 23, nil, 23, 23, 23, nil, 27, nil, 27, 27, nil, nil, +23, 27, 27, 27, nil, nil, nil, 27, nil, nil, 27, nil, nil, nil, nil, +27, 27, 27, nil, 27, 27, 27, nil, 27, nil, nil, nil, 27, 27, nil, +27, 27, nil, 27, 27, 27, nil, 37, nil, 37, 37, nil, nil, 27, 37, +37, 37, nil, 37, nil, 37, nil, nil, 37, nil, nil, 37, nil, 37, 37, +37, nil, 37, 37, 37, nil, 37, nil, nil, nil, 37, 37, nil, 37, 37, +nil, 37, 37, 37, nil, 39, nil, 39, 39, nil, nil, 37, 39, 39, 39, +nil, nil, nil, 39, nil, nil, 39, nil, nil, nil, nil, 39, 39, 39, nil, +39, 39, 39, nil, 39, nil, nil, nil, 39, 39, nil, 39, 39, nil, 39, +39, 39, nil, 60, nil, 60, 60, nil, nil, 39, 60, 60, 60, nil, nil, +nil, 60, nil, nil, 60, nil, nil, nil, nil, 60, 60, 60, nil, 60, 60, +60, nil, 60, nil, nil, nil, 60, 60, nil, 60, 60, nil, 60, 60, 60, +nil, 61, nil, 61, 61, nil, nil, 60, 61, 61, 61, nil, nil, nil, 61, +nil, nil, 61, nil, nil, nil, nil, 61, 61, 61, nil, 61, 61, 61, nil, +61, nil, nil, nil, 61, 61, nil, 61, 61, nil, 61, 61, 61, nil, 62, +nil, 62, 62, nil, nil, 61, 62, 62, 62, nil, nil, nil, 62, nil, nil, +62, nil, nil, nil, nil, 62, 62, 62, nil, 62, 62, 62, nil, 62, nil, +nil, nil, 62, 62, nil, 62, 62, nil, 62, 62, 62, nil, 63, nil, 63, +63, nil, nil, 62, 63, 63, 63, nil, nil, nil, 63, nil, nil, 63, nil, +nil, nil, nil, 63, 63, 63, nil, 63, 63, 63, nil, 63, nil, nil, nil, +63, 63, nil, 63, 63, nil, 63, 63, 63, nil, 85, nil, 85, 85, nil, +nil, 63, 85, 85, 85, nil, nil, nil, 85, nil, nil, 85, nil, nil, nil, +nil, 85, 85, 85, nil, 85, 85, 85, nil, 85, nil, nil, nil, 85, 85, +nil, 85, 85, nil, 85, 85, 85, nil, 86, nil, 86, 86, nil, nil, 85, +86, 86, 86, nil, nil, nil, 86, nil, nil, 86, nil, nil, nil, nil, 86, +86, 86, nil, 86, 86, 86, nil, 86, nil, nil, nil, 86, 86, nil, 86, +86, nil, 86, 86, 86, nil, 87, nil, 87, 87, nil, nil, 86, 87, 87, +87, nil, nil, nil, 87, nil, nil, 87, nil, nil, nil, nil, 87, 87, 87, +nil, 87, 87, 87, nil, 87, nil, nil, nil, 87, 87, nil, 87, 87, nil, +87, 87, 87, nil, 88, nil, 88, 88, nil, nil, 87, 88, 88, 88, nil, +nil, nil, 88, nil, nil, 88, nil, nil, nil, nil, 88, 88, 88, nil, 88, +88, 88, nil, 88, nil, nil, nil, 88, 88, nil, 88, 88, nil, 88, 88, +88, nil, 89, nil, 89, 89, nil, nil, 88, 89, 89, 89, nil, nil, nil, +89, nil, nil, 89, nil, nil, nil, nil, 89, 89, 89, nil, 89, 89, 89, +nil, 89, nil, nil, nil, 89, 89, nil, 89, 89, nil, 89, 89, 89, nil, +90, nil, 90, 90, nil, nil, 89, 90, 90, 90, nil, nil, nil, 90, nil, +nil, 90, nil, nil, nil, nil, 90, 90, 90, nil, 90, 90, 90, nil, 90, +nil, nil, nil, 90, 90, nil, 90, 90, nil, 90, 90, 90, nil, 91, nil, +91, 91, nil, nil, 90, 91, 91, 91, nil, nil, nil, 91, nil, nil, 91, +nil, nil, nil, nil, 91, 91, 91, nil, 91, 91, 91, nil, 91, nil, nil, +nil, 91, 91, nil, 91, 91, nil, 91, 91, 91, nil, 92, nil, 92, 92, +nil, nil, 91, 92, 92, 92, nil, nil, nil, 92, nil, nil, 92, nil, nil, +nil, nil, 92, 92, 92, nil, 92, 92, 92, nil, 92, nil, nil, nil, 92, +92, nil, 92, 92, nil, 92, 92, 92, nil, 93, nil, 93, 93, nil, nil, +92, 93, 93, 93, nil, nil, nil, 93, nil, nil, 93, nil, nil, nil, nil, +93, 93, 93, nil, 93, 93, 93, nil, 93, nil, nil, nil, 93, 93, nil, +93, 93, nil, 93, 93, 93, nil, 94, nil, 94, 94, nil, nil, 93, 94, +94, 94, nil, nil, nil, 94, nil, nil, 94, nil, nil, nil, nil, 94, 94, +94, nil, 94, 94, 94, nil, 94, nil, nil, nil, 94, 94, nil, 94, 94, +nil, 94, 94, 94, nil, 95, nil, 95, 95, nil, nil, 94, 95, 95, 95, +nil, nil, nil, 95, nil, nil, 95, nil, nil, nil, nil, 95, 95, 95, nil, +95, 95, 95, nil, 95, nil, nil, nil, 95, 95, nil, 95, 95, nil, 95, +95, 95, nil, 96, nil, 96, 96, nil, nil, 95, 96, 96, 96, nil, nil, +nil, 96, nil, nil, 96, nil, nil, nil, nil, 96, 96, 96, nil, 96, 96, +96, nil, 96, nil, nil, nil, 96, 96, nil, 96, 96, nil, 96, 96, 96, +nil, 97, nil, 97, 97, nil, nil, 96, 97, 97, 97, nil, nil, nil, 97, +nil, nil, 97, nil, nil, nil, nil, 97, 97, 97, nil, 97, 97, 97, nil, +97, nil, nil, nil, 97, 97, nil, 97, 97, nil, 97, 97, 97, nil, 98, +nil, 98, 98, nil, nil, 97, 98, 98, 98, nil, nil, nil, 98, nil, nil, +98, nil, nil, nil, nil, 98, 98, 98, nil, 98, 98, 98, nil, 98, nil, +nil, nil, 98, 98, nil, 98, 98, nil, 98, 98, 98, nil, 111, nil, 111, +111, nil, nil, 98, 111, 111, 111, nil, nil, 111, 111, nil, nil, 111, 111, +111, nil, nil, 111, 111, 111, nil, 111, 111, 111, nil, 111, nil, nil, nil, +111, 111, nil, 111, 111, nil, 111, 111, 111, nil, 123, nil, 123, 123, nil, +nil, 111, 123, 123, 123, nil, nil, nil, 123, nil, nil, 123, nil, nil, nil, +nil, 123, 123, 123, nil, 123, 123, 123, nil, 123, nil, nil, nil, 123, 123, +nil, 123, 123, nil, 123, 123, 123, nil, 129, nil, 129, 129, nil, nil, 123, +129, 129, 129, nil, nil, nil, 129, nil, nil, 129, nil, nil, nil, nil, 129, +129, 129, nil, 129, 129, 129, nil, 129, nil, nil, nil, 129, 129, nil, 129, +129, nil, 129, 129, 129, nil, 153, nil, 153, 153, nil, nil, 129, 153, 153, +153, nil, nil, nil, 153, nil, nil, 153, nil, nil, nil, nil, 153, 153, 153, +nil, 153, 153, 153, nil, 153, nil, nil, nil, 153, 153, nil, 153, 153, nil, +153, 153, 153, nil, 155, nil, 155, 155, nil, nil, 153, 155, 155, 155, nil, +nil, nil, 155, nil, nil, 155, nil, nil, nil, nil, 155, 155, 155, nil, 155, +155, 155, nil, 155, nil, nil, nil, 155, 155, nil, 155, 155, nil, 155, 155, +155, nil, 156, nil, 156, 156, nil, nil, 155, 156, 156, 156, nil, nil, nil, +156, nil, nil, 156, nil, nil, nil, nil, 156, 156, 156, nil, 156, 156, 156, +nil, 156, nil, nil, nil, 156, 156, nil, 156, 156, nil, 156, 156, 156, nil, +157, nil, 157, 157, nil, nil, 156, 157, 157, 157, nil, nil, 157, 157, nil, +nil, 157, 157, 157, nil, nil, 157, 157, 157, nil, 157, 157, 157, nil, 157, +nil, nil, nil, 157, 157, nil, 157, 157, nil, 157, 157, 157, nil, 180, nil, +180, 180, nil, nil, 157, 180, 180, 180, nil, nil, nil, 180, nil, nil, 180, +nil, nil, nil, nil, 180, 180, 180, nil, 180, 180, 180, nil, 180, nil, nil, +nil, 180, 180, nil, 180, 180, nil, 180, 180, 180, 3, 3, 3, 3, nil, +142, nil, 180, 3, nil, nil, nil, nil, 3, 142, 3, 3, 99, 99, 99, +99, nil, 3, nil, nil, 99, nil, nil, nil, nil, 99, nil, 142, 142, 142, +142, 142, 142, 142, 99, 3, 3, 3, 3, 3, 3, 3, nil, 3, nil, +nil, nil, nil, nil, nil, nil, nil, 99, 99, 99, 99, 99, 99, 99, nil, +99, 101, 101, 101, 101, nil, nil, nil, nil, 101, nil, nil, nil, nil, 101, +nil, 104, 104, 104, 104, 104, nil, nil, 101, 104, nil, nil, nil, nil, 104, +nil, nil, nil, nil, nil, nil, nil, nil, 104, nil, nil, 101, 101, 101, 101, +101, 101, 101, nil, 101, nil, nil, nil, nil, nil, nil, 104, 104, 104, 104, +104, 104, 104, nil, 104, 117, 117, 117, 117, nil, nil, nil, nil, 117, nil, +nil, nil, nil, 117, nil, 117, 122, 122, 122, 122, nil, nil, 117, nil, 122, +nil, nil, nil, 122, 122, nil, nil, nil, nil, nil, nil, nil, nil, 122, nil, +117, 117, 117, 117, 117, 117, 117, nil, 117, nil, nil, nil, nil, nil, nil, +nil, 122, 122, 122, 122, 122, 122, 122, nil, 122, 144, 144, 144, 144, nil, +nil, nil, nil, 144, nil, nil, nil, nil, 144, nil, 145, 145, 145, 145, nil, +nil, nil, 144, 145, nil, nil, nil, nil, 145, nil, nil, nil, nil, nil, nil, +nil, nil, 145, nil, nil, 144, 144, 144, 144, 144, 144, 144, nil, 144, nil, +nil, nil, nil, nil, nil, 145, 145, 145, 145, 145, 145, 145, nil, 145, 146, +146, 146, 146, nil, nil, nil, nil, 146, nil, nil, nil, nil, 146, nil, 147, +147, 147, 147, nil, nil, nil, 146, 147, nil, nil, nil, nil, 147, nil, nil, +nil, nil, nil, nil, nil, nil, 147, nil, nil, 146, 146, 146, 146, 146, 146, +146, nil, 146, nil, nil, nil, nil, nil, nil, 147, 147, 147, 147, 147, 147, +147, nil, 147, 148, 148, 148, 148, nil, nil, nil, nil, 148, nil, nil, nil, +nil, 148, nil, 149, 149, 149, 149, nil, nil, nil, 148, 149, nil, nil, nil, +nil, 149, nil, nil, nil, nil, nil, nil, nil, nil, 149, nil, nil, 148, 148, +148, 148, 148, 148, 148, nil, 148, nil, nil, nil, nil, nil, nil, 149, 149, +149, 149, 149, 149, 149, nil, 149, 150, 150, 150, 150, nil, nil, nil, nil, +150, nil, nil, nil, nil, 150, nil, 151, 151, 151, 151, nil, nil, nil, 150, +151, nil, nil, nil, nil, 151, nil, nil, nil, nil, nil, nil, nil, nil, 151, +nil, nil, 150, 150, 150, 150, 150, 150, 150, nil, 150, nil, nil, nil, nil, +nil, nil, 151, 151, 151, 151, 151, 151, 151, nil, 151, 158, 158, 158, 158, +nil, nil, nil, nil, 158, nil, 158, nil, nil, 158, nil, 158, 158, 168, 168, +168, 168, nil, 158, nil, nil, 168, nil, nil, nil, nil, 168, nil, nil, nil, +nil, nil, nil, nil, nil, 168, 158, 158, 158, 158, 158, 158, 158, nil, 158, +nil, nil, nil, nil, nil, nil, nil, nil, 168, 168, 168, 168, 168, 168, 168, +nil, 168, 171, 171, 171, 171, nil, nil, nil, nil, 171, nil, nil, nil, nil, +171, nil, 173, 173, 173, 173, nil, nil, nil, 171, 173, nil, nil, nil, nil, +173, nil, 171, nil, nil, nil, nil, nil, nil, 173, nil, nil, 171, 171, 171, +171, 171, 171, 171, nil, 171, nil, nil, nil, nil, nil, nil, 173, 173, 173, +173, 173, 173, 173, nil, 173, 175, 175, 175, 175, nil, nil, nil, nil, 175, +nil, nil, nil, nil, 175, nil, 185, 185, 185, 185, nil, nil, nil, 175, 185, +nil, nil, nil, nil, 185, nil, nil, nil, nil, nil, nil, nil, nil, 185, nil, +nil, 175, 175, 175, 175, 175, 175, 175, nil, 175, nil, nil, nil, nil, nil, +nil, 185, 185, 185, 185, 185, 185, 185, nil, 185, 125, 125, nil, nil, nil, +nil, 125, nil, nil, nil, nil, 125, 126, 126, nil, nil, nil, nil, 126, nil, +125, nil, nil, 126, nil, 138, 138, nil, nil, nil, nil, 138, 126, nil, nil, +nil, 138, nil, 125, 125, 125, 125, 125, 125, 125, 138, 125, nil, nil, nil, +126, 126, 126, 126, 126, 126, 126, nil, 126, nil, nil, nil, nil, 138, 138, +138, 138, 138, 138, 138, 124, 138, 139, 139, nil, 124, nil, nil, 139, nil, +nil, nil, nil, 139, 124, nil, nil, nil, nil, nil, nil, nil, 139, nil, nil, +127, nil, nil, nil, nil, 127, nil, 124, 124, 124, 124, 124, 124, 124, 127, +139, 139, 139, 139, 139, 139, 139, nil, 139, nil, 140, nil, nil, nil, nil, +140, nil, 127, 127, 127, 127, 127, 127, 127, 140, 141, nil, nil, nil, nil, +141, nil, nil, nil, nil, 143, nil, nil, nil, 141, 143, nil, 140, 140, 140, +140, 140, 140, 140, 143, nil, nil, nil, nil, nil, nil, nil, 141, 141, 141, +141, 141, 141, 141, nil, nil, nil, 143, 143, 143, 143, 143, 143, 143] + +racc_action_pointer = [ +43, 0, nil, 1416, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, 86, nil, nil, nil, 129, nil, nil, nil, 172, nil, nil, +nil, nil, nil, -1, - +15, nil, nil, 215, nil, 258, 3, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 301, 344, 387, 430, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, 27, 8, nil, nil, 19, 473, 516, 559, 602, 645, 688, 731, 774, 817, +860, 903, 946, 989, 1032, 1433, -15, 1482, - +10, nil, 1497, nil, nil, nil, nil, nil, nil, 1075, 14, nil, nil, nil, nil, +1546, nil, nil, nil, 13, 1562, 1118, 2123, 2059, 2071, 2148, 43, 1161, nil, 3, +nil, nil, nil, nil, nil, nil, 2084, 2131, 2173, 2188, 1408, 2198, 1611, 1626, 1675, +1690, 1739, 1754, 1803, 1818, nil, 1204, nil, 1247, 1290, 1333, 1867, nil, nil, - +8, nil, 31, nil, nil, nil, nil, 1884, nil, nil, 1933, nil, 1948, nil, 1997, +nil, nil, 21, 42, 1376, nil, nil, 36, nil, 2012, nil] + +racc_action_default = [-140, -140, -1, -4, -5, -6, -7, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, -23, -24, -25, -26, -140, -30, -31, -32, -140, -37, -55, -56, -57, -60, -140, -63, -64, -65, -140, -73, -140, -76, -77, -78, -79, -80, -81, -82, -83, -84, -85, -86, -87, -88, -89, -90, -91, -107, -108, -109, -110, -140, -140, -140, -140, -115, -116, -117, -118, -119, -120, -121, -122, -123, -124, -125, -126, -127, -128, -129, -130, -140, -140, -2, -3, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, -22, -140, -28, -140, -34, -140, -61, -62, -74, -38, -39, -40, -140, -140, -46, -47, -48, -49, -69, -66, -67, -68, -71, -140, -140, -111, -112, -113, -114, -140, -140, -133, -135, -136, -137, -138, 187, -58, -59, -93, -94, -95, -96, -97, -98, -99, -100, -101, -102, -103, -104, -105, -106, -27, -140, -33, -140, -140, -140, -4, -43, -44, -140, -50, -52, -54, -70, -72, -75, -92, -131, -134, -140, -139, -29, -35, -36, -41, -42, -9, -140, -140, -132, -8, -140, -51, -53, -45] + +racc_goto_table = [ +99, 82, 103, 83, 101, 1, 105, 130, 104, 183, 100, 102, 159, 162, 121, +108, 109, 110, 117, 111, 122, 115, 112, 161, 116, 107, 118, 119, 120, 128, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 124, 125, 126, 127, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 170, nil, 136, 176, 177, +nil, nil, nil, nil, nil, nil, 138, 139, 140, 141, 142, 143, 144, 145, 146, +147, 148, 149, 150, 151, 184, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, 158, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 168, +nil, nil, nil, nil, nil, 171, nil, nil, nil, nil, nil, 157, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 174, nil, nil, nil, 173, +nil, 104, 175, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, 82, 83, nil, nil, 185] + +racc_goto_check = [ +3, 2, 24, 4, 3, 1, 40, 77, 3, 5, 20, 23, 30, 35, 25, +26, 27, 28, 3, 29, 3, 31, 32, 33, 34, 43, 44, 45, 46, 75, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 3, 3, 3, 3, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 77, nil, 40, 30, 30, +nil, nil, nil, nil, nil, nil, 3, 3, 3, 3, 3, 3, 3, 3, 3, +3, 3, 3, 3, 3, 35, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, 3, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 3, +nil, nil, nil, nil, nil, 3, nil, nil, nil, nil, nil, 1, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 24, nil, nil, nil, 3, +nil, 3, 3, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, 2, 4, nil, nil, 3] + +racc_goto_pointer = [nil, 5, 0, -19, 0, - +169, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +-13, nil, nil, -16, -25, -23, -22, -21, -20, -18, -99, -16, -15, -89, -13, -99, nil, nil, nil, nil, -27, nil, nil, -9, -11, -10, - +9, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, -51, nil, -73, nil] + +racc_goto_default = [ +nil, nil, 2, 3, 4, nil, 7, 8, 9, 10, 11, 12, 13, 14, 15, +16, 17, 18, 20, 21, nil, 24, 25, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, 163, 29, 30, 31, 32, 34, 35, 38, nil, +nil, nil, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +54, 55, 56, 57, 58, 59, 64, 65, 66, 67, 68, 69, 70, 78, 79, +nil, 132, nil, 131] + +racc_reduce_table = [ + 0, 0, :racc_error, + 1, 54, :_reduce_none, + 2, 54, :_reduce_2, + 2, 55, :_reduce_3, + 1, 55, :_reduce_4, + 1, 55, :_reduce_5, + 1, 57, :_reduce_none, + 1, 57, :_reduce_none, + 1, 58, :_reduce_none, + 0, 58, :_reduce_none, + 1, 56, :_reduce_none, + 1, 56, :_reduce_none, + 1, 56, :_reduce_none, + 1, 56, :_reduce_none, + 1, 56, :_reduce_none, + 1, 56, :_reduce_none, + 1, 56, :_reduce_none, + 1, 56, :_reduce_none, + 1, 56, :_reduce_none, + 1, 56, :_reduce_none, + 1, 68, :_reduce_none, + 1, 68, :_reduce_none, + 2, 69, :_reduce_22, + 1, 70, :_reduce_23, + 1, 66, :_reduce_none, + 1, 66, :_reduce_none, + 1, 71, :_reduce_26, + 3, 72, :_reduce_27, + 1, 73, :_reduce_28, + 3, 73, :_reduce_29, + 1, 67, :_reduce_none, + 1, 67, :_reduce_none, + 1, 74, :_reduce_32, + 3, 75, :_reduce_33, + 1, 76, :_reduce_34, + 3, 76, :_reduce_35, + 3, 77, :_reduce_36, + 1, 64, :_reduce_37, + 1, 78, :_reduce_none, + 1, 78, :_reduce_none, + 1, 78, :_reduce_none, + 3, 79, :_reduce_41, + 3, 80, :_reduce_42, + 2, 81, :_reduce_43, + 1, 83, :_reduce_44, + 5, 84, :_reduce_45, + 1, 85, :_reduce_46, + 1, 87, :_reduce_47, + 1, 82, :_reduce_none, + 1, 82, :_reduce_none, + 1, 86, :_reduce_none, + 3, 86, :_reduce_none, + 1, 88, :_reduce_52, + 3, 88, :_reduce_53, + 1, 89, :_reduce_54, + 1, 63, :_reduce_none, + 1, 63, :_reduce_none, + 1, 63, :_reduce_none, + 3, 90, :_reduce_58, + 3, 90, :_reduce_59, + 1, 91, :_reduce_60, + 2, 92, :_reduce_61, + 2, 92, :_reduce_62, + 1, 93, :_reduce_none, + 1, 93, :_reduce_none, + 1, 95, :_reduce_65, + 2, 96, :_reduce_66, + 1, 97, :_reduce_none, + 1, 97, :_reduce_none, + 1, 98, :_reduce_none, + 2, 98, :_reduce_none, + 1, 99, :_reduce_none, + 2, 99, :_reduce_none, + 1, 94, :_reduce_73, + 2, 94, :_reduce_74, + 3, 60, :_reduce_75, + 1, 65, :_reduce_76, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 3, 100, :_reduce_92, + 3, 101, :_reduce_93, + 3, 102, :_reduce_94, + 3, 103, :_reduce_95, + 3, 104, :_reduce_96, + 3, 105, :_reduce_97, + 3, 106, :_reduce_98, + 3, 107, :_reduce_99, + 3, 108, :_reduce_100, + 3, 109, :_reduce_101, + 3, 110, :_reduce_102, + 3, 111, :_reduce_103, + 3, 112, :_reduce_104, + 3, 113, :_reduce_105, + 3, 114, :_reduce_106, + 1, 62, :_reduce_none, + 1, 62, :_reduce_none, + 1, 62, :_reduce_none, + 1, 62, :_reduce_none, + 2, 115, :_reduce_111, + 2, 116, :_reduce_112, + 2, 117, :_reduce_113, + 2, 118, :_reduce_114, + 1, 59, :_reduce_none, + 1, 59, :_reduce_none, + 1, 59, :_reduce_none, + 1, 59, :_reduce_none, + 1, 59, :_reduce_none, + 1, 59, :_reduce_none, + 1, 59, :_reduce_none, + 1, 120, :_reduce_122, + 1, 119, :_reduce_123, + 1, 122, :_reduce_124, + 1, 123, :_reduce_125, + 1, 124, :_reduce_126, + 1, 125, :_reduce_127, + 1, 121, :_reduce_128, + 1, 121, :_reduce_none, + 1, 121, :_reduce_none, + 3, 126, :_reduce_131, + 3, 129, :_reduce_132, + 1, 128, :_reduce_133, + 2, 128, :_reduce_134, + 1, 130, :_reduce_135, + 1, 130, :_reduce_136, + 2, 127, :_reduce_137, + 1, 131, :_reduce_138, + 2, 131, :_reduce_139 ] + +racc_reduce_n = 140 + +racc_shift_n = 187 + +racc_token_table = { + false => 0, + :error => 1, + :IDENTIFIER => 2, + :EQUAL => 3, + :PLUS => 4, + :MINUS => 5, + :ASTERISK => 6, + :FWD_SLASH => 7, + :COLON => 8, + :FLOAT => 9, + :INTEGER => 10, + :STRING => 11, + :EXPO => 12, + :INDENT => 13, + :OUTDENT => 14, + :OPAREN => 15, + :CPAREN => 16, + :DOT => 17, + :SIGNATURE => 18, + :NL => 19, + :EOF => 20, + :PIPE => 21, + :COMMA => 22, + :NIL => 23, + :TRUE => 24, + :FALSE => 25, + :EQUALITY => 26, + :CALL => 27, + :SELF => 28, + :CONSTANT => 29, + :CHAR => 30, + :DOUBLE_TICK_STRING => 31, + :DOUBLE_TICK_STRING_END => 32, + :INTERPOLATE_START => 33, + :INTERPOLATE_END => 34, + :BOX => 35, + :LSQUARE => 36, + :RSQUARE => 37, + :FACES => 38, + :LFACE => 39, + :RFACE => 40, + :BANG => 41, + :TILDE => 42, + :RETURN => 43, + :NOT_EQUALITY => 44, + :OR => 45, + :AND => 46, + :GT => 47, + :LT => 48, + :GTE => 49, + :LTE => 50, + :AT => 51, + :PERCENT => 52 } + +racc_nt_base = 53 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ + "$end", + "error", + "IDENTIFIER", + "EQUAL", + "PLUS", + "MINUS", + "ASTERISK", + "FWD_SLASH", + "COLON", + "FLOAT", + "INTEGER", + "STRING", + "EXPO", + "INDENT", + "OUTDENT", + "OPAREN", + "CPAREN", + "DOT", + "SIGNATURE", + "NL", + "EOF", + "PIPE", + "COMMA", + "NIL", + "TRUE", + "FALSE", + "EQUALITY", + "CALL", + "SELF", + "CONSTANT", + "CHAR", + "DOUBLE_TICK_STRING", + "DOUBLE_TICK_STRING_END", + "INTERPOLATE_START", + "INTERPOLATE_END", + "BOX", + "LSQUARE", + "RSQUARE", + "FACES", + "LFACE", + "RFACE", + "BANG", + "TILDE", + "RETURN", + "NOT_EQUALITY", + "OR", + "AND", + "GT", + "LT", + "GTE", + "LTE", + "AT", + "PERCENT", + "$start", + "statements", + "statement", + "expr", + "eol", + "nlq", + "literal", + "grouped_expr", + "binary_op", + "unary_op", + "method_call", + "constant", + "variable", + "array", + "hash", + "return", + "return_expr", + "return_nil", + "empty_array", + "array_list", + "array_items", + "empty_hash", + "hash_list", + "hash_items", + "hash_item", + "indented", + "indented_w_stmts", + "indented_w_expr", + "indented_wo_stmts", + "indent", + "outdent", + "indent_w_args", + "indent_pipe", + "indent_args", + "indent_wo_args", + "indent_arg", + "arg_var", + "method_call_on_object", + "method_call_on_self", + "method_call_on_closure", + "call_signature", + "call_arguments", + "call_simple_name", + "call_argument", + "call_passed_arg", + "call_passed_simple", + "call_passed_indented", + "assignment", + "addition", + "subtraction", + "multiplication", + "division", + "exponentiation", + "modulo", + "equality", + "not_equality", + "logical_or", + "logical_and", + "greater_than", + "less_than", + "greater_or_eq", + "less_or_eq", + "unary_not", + "unary_plus", + "unary_minus", + "unary_complement", + "integer", + "float", + "string", + "nil", + "true", + "false", + "self", + "interpolated_string", + "empty_string", + "interpolated_string_contents", + "interpolation", + "interpolated_string_chunk", + "chars" ] + +Racc_debug_parser = false + +##### State transition tables end ##### + +# reduce 0 omitted + +# reduce 1 omitted + +module_eval(<<'.,.,', 'huia.y', 44) + def _reduce_2(val, _values, result) + return scope + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 46) + def _reduce_3(val, _values, result) + return scope.append val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 47) + def _reduce_4(val, _values, result) + return scope.append val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 48) + def _reduce_5(val, _values, result) + return scope + result + end +.,., + +# reduce 6 omitted + +# reduce 7 omitted + +# reduce 8 omitted + +# reduce 9 omitted + +# reduce 10 omitted + +# reduce 11 omitted + +# reduce 12 omitted + +# reduce 13 omitted + +# reduce 14 omitted + +# reduce 15 omitted + +# reduce 16 omitted + +# reduce 17 omitted + +# reduce 18 omitted + +# reduce 19 omitted + +# reduce 20 omitted + +# reduce 21 omitted + +module_eval(<<'.,.,', 'huia.y', 66) + def _reduce_22(val, _values, result) + return n(:Return, val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 67) + def _reduce_23(val, _values, result) + return n(:Return, n(:Nil)) + result + end +.,., + +# reduce 24 omitted + +# reduce 25 omitted + +module_eval(<<'.,.,', 'huia.y', 72) + def _reduce_26(val, _values, result) + return n :Array + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 74) + def _reduce_27(val, _values, result) + return val[1] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 75) + def _reduce_28(val, _values, result) + return n :Array, [val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 76) + def _reduce_29(val, _values, result) + val[0].append(val[2]); return val[0] + result + end +.,., + +# reduce 30 omitted + +# reduce 31 omitted + +module_eval(<<'.,.,', 'huia.y', 80) + def _reduce_32(val, _values, result) + return n :Hash + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 81) + def _reduce_33(val, _values, result) + return val[1] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 82) + def _reduce_34(val, _values, result) + return n :Hash, val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 83) + def _reduce_35(val, _values, result) + val[0].append(val[2]); return val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 84) + def _reduce_36(val, _values, result) + return n :HashItem, val[0], val[2] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 86) + def _reduce_37(val, _values, result) + return constant val[0] + result + end +.,., + +# reduce 38 omitted + +# reduce 39 omitted + +# reduce 40 omitted + +module_eval(<<'.,.,', 'huia.y', 91) + def _reduce_41(val, _values, result) + return val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 92) + def _reduce_42(val, _values, result) + return val[0].append(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 93) + def _reduce_43(val, _values, result) + return val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 94) + def _reduce_44(val, _values, result) + return pop_scope + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 97) + def _reduce_45(val, _values, result) + return val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 98) + def _reduce_46(val, _values, result) + return push_scope + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 99) + def _reduce_47(val, _values, result) + return push_scope + result + end +.,., + +# reduce 48 omitted + +# reduce 49 omitted + +# reduce 50 omitted + +# reduce 51 omitted + +module_eval(<<'.,.,', 'huia.y', 105) + def _reduce_52(val, _values, result) + return scope.add_argument val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 106) + def _reduce_53(val, _values, result) + return n :Assignment, val[0], val[2] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 107) + def _reduce_54(val, _values, result) + return n :Variable, val[0] + result + end +.,., + +# reduce 55 omitted + +# reduce 56 omitted + +# reduce 57 omitted + +module_eval(<<'.,.,', 'huia.y', 112) + def _reduce_58(val, _values, result) + return n :MethodCall, val[0], val[2] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 113) + def _reduce_59(val, _values, result) + return n :MethodCall, val[0], n(:CallSignature, val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 114) + def _reduce_60(val, _values, result) + return n :MethodCall, scope_instance, val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 116) + def _reduce_61(val, _values, result) + return n :MethodCall, this_closure, val[1] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 117) + def _reduce_62(val, _values, result) + return n :MethodCall, this_closure, n(:CallSignature, val[1]) + result + end +.,., + +# reduce 63 omitted + +# reduce 64 omitted + +module_eval(<<'.,.,', 'huia.y', 121) + def _reduce_65(val, _values, result) + return n :CallSignature, val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 122) + def _reduce_66(val, _values, result) + return n :CallSignature, val[0], [val[1]] + result + end +.,., + +# reduce 67 omitted + +# reduce 68 omitted + +# reduce 69 omitted + +# reduce 70 omitted + +# reduce 71 omitted + +# reduce 72 omitted + +module_eval(<<'.,.,', 'huia.y', 129) + def _reduce_73(val, _values, result) + return val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 130) + def _reduce_74(val, _values, result) + return val[0].concat_signature val[1] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 132) + def _reduce_75(val, _values, result) + return n :Expression, val[1] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 134) + def _reduce_76(val, _values, result) + return allocate_local val[0] + result + end +.,., + +# reduce 77 omitted + +# reduce 78 omitted + +# reduce 79 omitted + +# reduce 80 omitted + +# reduce 81 omitted + +# reduce 82 omitted + +# reduce 83 omitted + +# reduce 84 omitted + +# reduce 85 omitted + +# reduce 86 omitted + +# reduce 87 omitted + +# reduce 88 omitted + +# reduce 89 omitted + +# reduce 90 omitted + +# reduce 91 omitted + +module_eval(<<'.,.,', 'huia.y', 152) + def _reduce_92(val, _values, result) + return allocate_local_assignment val[0], val[2] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 153) + def _reduce_93(val, _values, result) + return binary val[0], val[2], 'plus:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 154) + def _reduce_94(val, _values, result) + return binary val[0], val[2], 'minus:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 155) + def _reduce_95(val, _values, result) + return binary val[0], val[2], 'multiplyBy:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 156) + def _reduce_96(val, _values, result) + return binary val[0], val[2], 'divideBy:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 157) + def _reduce_97(val, _values, result) + return binary val[0], val[2], 'toThePowerOf:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 158) + def _reduce_98(val, _values, result) + return binary val[0], val[2], 'moduloOf:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 159) + def _reduce_99(val, _values, result) + return binary val[0], val[2], 'isEqualTo:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 160) + def _reduce_100(val, _values, result) + return binary val[0], val[2], 'isNotEqualTo:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 161) + def _reduce_101(val, _values, result) + return binary val[0], val[2], 'logicalOr:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 162) + def _reduce_102(val, _values, result) + return binary val[0], val[2], 'logicalAnd:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 163) + def _reduce_103(val, _values, result) + return binary val[0], val[2], 'isGreaterThan:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 164) + def _reduce_104(val, _values, result) + return binary val[0], val[2], 'isLessThan:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 165) + def _reduce_105(val, _values, result) + return binary val[0], val[2], 'isGreaterOrEqualTo:' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 166) + def _reduce_106(val, _values, result) + return binary val[0], val[2], 'isLessOrEqualTo:' + result + end +.,., + +# reduce 107 omitted + +# reduce 108 omitted + +# reduce 109 omitted + +# reduce 110 omitted + +module_eval(<<'.,.,', 'huia.y', 173) + def _reduce_111(val, _values, result) + return unary val[1], 'unaryNot' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 174) + def _reduce_112(val, _values, result) + return unary val[1], 'unaryPlus' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 175) + def _reduce_113(val, _values, result) + return unary val[1], 'unaryMinus' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 176) + def _reduce_114(val, _values, result) + return unary val[1], 'unaryComplement' + result + end +.,., + +# reduce 115 omitted + +# reduce 116 omitted + +# reduce 117 omitted + +# reduce 118 omitted + +# reduce 119 omitted + +# reduce 120 omitted + +# reduce 121 omitted + +module_eval(<<'.,.,', 'huia.y', 186) + def _reduce_122(val, _values, result) + return n :Float, val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 187) + def _reduce_123(val, _values, result) + return n :Integer, val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 188) + def _reduce_124(val, _values, result) + return n :Nil + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 189) + def _reduce_125(val, _values, result) + return n :True + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 190) + def _reduce_126(val, _values, result) + return n :False + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 191) + def _reduce_127(val, _values, result) + return n :Self + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 193) + def _reduce_128(val, _values, result) + return n :String, val[0] + result + end +.,., + +# reduce 129 omitted + +# reduce 130 omitted + +module_eval(<<'.,.,', 'huia.y', 197) + def _reduce_131(val, _values, result) + return val[1] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 198) + def _reduce_132(val, _values, result) + return val[1] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 199) + def _reduce_133(val, _values, result) + return n :InterpolatedString, val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 200) + def _reduce_134(val, _values, result) + val[0].append(val[1]); return val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 201) + def _reduce_135(val, _values, result) + return val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 202) + def _reduce_136(val, _values, result) + return to_string(val[0]) + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 203) + def _reduce_137(val, _values, result) + return n :String, '' + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 205) + def _reduce_138(val, _values, result) + return n :String, val[0] + result + end +.,., + +module_eval(<<'.,.,', 'huia.y', 206) + def _reduce_139(val, _values, result) + val[0].append(val[1]); return val[0] + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] +end + + end # class Parser + end # module Huia diff --git a/test/regress/journey.rb b/test/regress/journey.rb new file mode 100644 index 00000000..455d812a --- /dev/null +++ b/test/regress/journey.rb @@ -0,0 +1,214 @@ +# +# DO NOT MODIFY!!!! +# This file was automatically generated by Racc 2.0.0.dev +# (codename: Mecha Oishii) from Racc grammar file "journey.y". +# + +require 'racc/parser.rb' + +Object.module_eval(<<'...end journey.y/module_eval...', 'journey.y', 46) + +require 'journey/parser_extras' +...end journey.y/module_eval... +module Journey + class Parser < Racc::Parser +##### State transition tables begin ### + +racc_action_table = [ +17, 21, 13, 15, 14, 7, nil, 16, 8, 19, 13, 15, 14, 7, 23, +16, 8, 19, 13, 15, 14, 7, nil, 16, 8, 13, 15, 14, 7, nil, +16, 8, 13, 15, 14, 7, nil, 16, 8] + +racc_action_check = [ +1, 17, 1, 1, 1, 1, nil, 1, 1, 1, 20, 20, 20, 20, 20, +20, 20, 20, 0, 0, 0, 0, nil, 0, 0, 7, 7, 7, 7, nil, +7, 7, 19, 19, 19, 19, nil, 19, 19] + +racc_action_pointer = [ +16, 0, nil, nil, nil, nil, nil, 23, nil, nil, nil, nil, nil, nil, nil, +nil, nil, 1, nil, 30, 8, nil, nil, nil] + +racc_action_default = [-18, -18, -2, -3, -4, -5, -6, -18, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -1, -18, -18, 24, -8, -7] + +racc_goto_table = [ +18, 1, nil, nil, nil, nil, nil, nil, 20, nil, nil, nil, nil, nil, nil, +nil, nil, nil, 22, 18] + +racc_goto_check = [ +2, 1, nil, nil, nil, nil, nil, nil, 1, nil, nil, nil, nil, nil, nil, +nil, nil, nil, 2, 2] + +racc_goto_pointer = [nil, 1, -1, nil, nil, nil, nil, nil, nil, nil, nil] + +racc_goto_default = [nil, nil, 2, 3, 4, 5, 6, 9, 10, 11, 12] + +racc_reduce_table = [ + 0, 0, :racc_error, + 2, 11, :_reduce_1, + 1, 11, :_reduce_2, + 1, 11, :_reduce_none, + 1, 12, :_reduce_none, + 1, 12, :_reduce_none, + 1, 12, :_reduce_none, + 3, 15, :_reduce_7, + 3, 13, :_reduce_8, + 1, 16, :_reduce_9, + 1, 14, :_reduce_none, + 1, 14, :_reduce_none, + 1, 14, :_reduce_none, + 1, 14, :_reduce_none, + 1, 19, :_reduce_14, + 1, 17, :_reduce_15, + 1, 18, :_reduce_16, + 1, 20, :_reduce_17 ] + +racc_reduce_n = 18 + +racc_shift_n = 24 + +racc_token_table = { + false => 0, + :error => 1, + :SLASH => 2, + :LITERAL => 3, + :SYMBOL => 4, + :LPAREN => 5, + :RPAREN => 6, + :DOT => 7, + :STAR => 8, + :OR => 9 } + +racc_nt_base = 10 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ + "$end", + "error", + "SLASH", + "LITERAL", + "SYMBOL", + "LPAREN", + "RPAREN", + "DOT", + "STAR", + "OR", + "$start", + "expressions", + "expression", + "or", + "terminal", + "group", + "star", + "symbol", + "literal", + "slash", + "dot" ] + +Racc_debug_parser = false + +##### State transition tables end ##### + +# reduce 0 omitted + +module_eval(<<'.,.,', 'journey.y', 6) + def _reduce_1(val, _values, result) + result = Cat.new(val.first, val.last) + result + end +.,., + +module_eval(<<'.,.,', 'journey.y', 7) + def _reduce_2(val, _values, result) + result = val.first + result + end +.,., + +# reduce 3 omitted + +# reduce 4 omitted + +# reduce 5 omitted + +# reduce 6 omitted + +module_eval(<<'.,.,', 'journey.y', 16) + def _reduce_7(val, _values, result) + result = Group.new(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'journey.y', 19) + def _reduce_8(val, _values, result) + result = Or.new([val.first, val.last]) + result + end +.,., + +module_eval(<<'.,.,', 'journey.y', 22) + def _reduce_9(val, _values, result) + result = Star.new(Symbol.new(val.last)) + result + end +.,., + +# reduce 10 omitted + +# reduce 11 omitted + +# reduce 12 omitted + +# reduce 13 omitted + +module_eval(<<'.,.,', 'journey.y', 31) + def _reduce_14(val, _values, result) + result = Slash.new('/') + result + end +.,., + +module_eval(<<'.,.,', 'journey.y', 34) + def _reduce_15(val, _values, result) + result = Symbol.new(val.first) + result + end +.,., + +module_eval(<<'.,.,', 'journey.y', 37) + def _reduce_16(val, _values, result) + result = Literal.new(val.first) + result + end +.,., + +module_eval(<<'.,.,', 'journey.y', 39) + def _reduce_17(val, _values, result) + result = Dot.new(val.first) + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] +end + + end # class Parser + end # module Journey diff --git a/test/regress/liquor.rb b/test/regress/liquor.rb new file mode 100644 index 00000000..97bde874 --- /dev/null +++ b/test/regress/liquor.rb @@ -0,0 +1,822 @@ +# +# DO NOT MODIFY!!!! +# This file was automatically generated by Racc 2.0.0.dev +# (codename: Mecha Oishii) from Racc grammar file "liquor.y". +# + +require 'racc/parser.rb' +module Liquor + class Parser < Racc::Parser + +module_eval(<<'...end liquor.y/module_eval...', 'liquor.y', 216) + attr_reader :errors, :ast + + def initialize(tags={}) + super() + + @errors = [] + @ast = nil + @tags = tags + end + + def success? + @errors.empty? + end + + def parse(string, name='(code)') + @errors.clear + @name = name + @ast = nil + + begin + @stream = Lexer.lex(string, @name, @tags) + @ast = do_parse + rescue Liquor::SyntaxError => e + @errors << e + end + + success? + end + + def next_token + tok = @stream.shift + [ tok[0], tok ] if tok + end + + TOKEN_NAME_MAP = { + :comma => ',', + :dot => '.', + :lblock => '{%', + :rblock => '%}', + :linterp => '{{', + :rinterp => '}}', + :lbracket => '[', + :rbracket => ']', + :lparen => '(', + :rparen => ')', + :pipe => '|', + :op_not => '!', + :op_mul => '*', + :op_div => '/', + :op_mod => '%', + :op_plus => '+', + :op_minus => '-', + :op_eq => '==', + :op_neq => '!=', + :op_lt => '<', + :op_leq => '<=', + :op_gt => '>', + :op_geq => '>=', + :keyword => 'keyword argument name', + :kwarg => 'keyword argument', + :ident => 'identifier', + } + + def on_error(error_token_id, error_token, value_stack) + if token_to_str(error_token_id) == "$end" + raise Liquor::SyntaxError.new("unexpected end of program", { + file: @name + }) + else + type, (loc, value) = error_token + type = TOKEN_NAME_MAP[type] || type + + raise Liquor::SyntaxError.new("unexpected token `#{type}'", loc) + end + end + + def retag(nodes) + loc = nodes.map { |node| node[1] }.compact + first, *, last = loc + return first if last.nil? + + { + file: first[:file], + line: first[:line], + start: first[:start], + end: last[:end], + } + end + + def reduce_tag_args(list) + list.each_slice(2).reduce([]) { |args, (k, v)| + if v[0] == :block + args << [ :blockarg, retag([ k, v ]), k, v[2] || [] ] + else + args << [ :kwarg, retag([ k, v ]), k, v ] + end + } + end +...end liquor.y/module_eval... +##### State transition tables begin ### + +racc_action_table = [ +26, 26, 26, 96, 7, 22, 97, 25, 25, 25, 28, 32, 36, 37, 34, +35, 31, 29, 27, 33, 26, 30, 38, 39, 26, 13, 15, 25, 26, 75, +21, 25, 14, 96, 28, 25, 97, 23, 41, 18, 31, 29, 27, 19, 26, +30, 96, 43, 54, 97, 70, 25, 77, 16, 28, 32, 36, 37, 34, 35, +31, 29, 27, 33, 26, 30, 38, 39, 40, 13, 15, 25, 24, 43, 21, +84, 14, 13, 15, 74, 87, 70, 21, 18, 14, 13, 15, 19, 94, 98, +21, 18, 14, 13, 15, 19, 107, 16, 21, 18, 14, 111, nil, 19, nil, +16, 6, 18, nil, 5, nil, 19, nil, 16, nil, 13, 15, 52, 13, 15, +21, 16, 14, 21, nil, 14, 2, nil, nil, 18, 13, 15, 18, 19, nil, +21, 19, 14, nil, 51, nil, nil, 6, 16, 18, 5, 16, nil, 19, 13, +15, nil, 13, 15, 21, nil, 14, 21, 16, 14, nil, nil, 2, 18, 13, +15, 18, 19, nil, 21, 19, 14, nil, nil, nil, nil, 6, 16, 18, 5, +16, nil, 19, 13, 15, nil, 13, 15, 21, nil, 14, 21, 16, 14, nil, +nil, 2, 18, 13, 15, 18, 19, nil, 21, 19, 14, nil, nil, nil, nil, +6, 16, 18, 5, 16, nil, 19, 13, 15, nil, 13, 15, 21, nil, 14, +21, 16, 14, nil, nil, 2, 18, 13, 15, 18, 19, nil, 21, 19, 14, +nil, nil, nil, nil, 6, 16, 18, 5, 16, nil, 19, 13, 15, nil, 13, +15, 21, nil, 14, 21, 16, 14, nil, nil, 2, 18, 13, 15, 18, 19, +nil, 21, 19, 14, nil, nil, nil, nil, 6, 16, 18, 5, 16, nil, 19, +13, 15, 74, 13, 15, 21, nil, 14, 21, 16, 14, nil, nil, 2, 18, +13, 15, 18, 19, nil, 21, 19, 14, nil, nil, nil, nil, 81, 16, 18, +nil, 16, nil, 19, 13, 15, nil, 13, 15, 21, nil, 14, 21, 16, 14, +nil, nil, nil, 18, 13, 15, 18, 19, nil, 21, 19, 14, nil, nil, nil, +nil, 101, 16, 18, nil, 16, nil, 19, 26, nil, nil, nil, nil, 106, nil, +25, nil, 16, 28, 32, 36, 37, 34, 35, 31, 29, 27, 33, nil, 30, +38, 39, 26, nil, nil, 82, 52, 6, nil, 25, 5, nil, 28, 32, 36, +37, 34, 35, 31, 29, 27, 33, 26, 30, 38, 39, 52, 2, 51, 25, +nil, nil, 28, 32, 36, 37, 34, 35, 31, 29, 27, 33, nil, 30, 38, +39, 76, 26, 51, nil, nil, nil, nil, nil, 25, nil, nil, 28, 32, 36, +37, 34, 35, 31, 29, 27, 33, 26, 30, 38, 39, 74, nil, nil, 25, +nil, nil, 28, 32, 36, 37, 34, 35, 31, 29, 27, 33, 26, 30, 38, +39, 74, nil, nil, 25, nil, nil, 28, 32, 36, 37, 34, 35, 31, 29, +27, 33, 26, 30, 38, 39, 102, nil, nil, 25, nil, nil, 28, 32, 36, +37, 34, 35, 31, 29, 27, 33, nil, 30, 38, 39, 26, 96, nil, nil, +97, nil, nil, 25, nil, nil, 28, 32, 36, 37, 34, 35, 31, 29, 27, +33, 26, 30, 38, 39, nil, nil, nil, 25, nil, nil, 28, 32, 36, 37, +34, 35, 31, 29, 27, 33, 26, 30, 38, nil, nil, nil, nil, 25, nil, +nil, 28, nil, 26, nil, nil, nil, 31, 29, 27, 25, nil, 30, 28, nil, +26, nil, nil, nil, 31, 29, 27, 25, nil, 30, 28, nil, 26, nil, nil, +nil, 31, 29, 27, 25, nil, 30, 28, nil, 26, nil, nil, nil, 31, 29, +27, 25, nil, 30, 28, nil, 26, nil, nil, nil, 31, 29, 27, 25, nil, +30, 28, 32, 36, 37, 34, 35, 31, 29, 27, 33, 26, 30, 26, nil, +nil, nil, nil, 25, nil, 25, 28, nil, 28, nil, nil, nil, nil, 29, 27, +29, 27] + +racc_action_check = [ +44, 45, 46, 94, 1, 6, 94, 44, 45, 46, 44, 44, 44, 44, 44, +44, 44, 44, 44, 44, 55, 44, 44, 44, 60, 5, 5, 55, 56, 44, +5, 60, 5, 107, 60, 56, 107, 7, 12, 5, 60, 60, 60, 5, 11, +60, 111, 13, 26, 111, 40, 11, 48, 5, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 57, 11, 11, 11, 11, 14, 14, 57, 11, 54, 14, +69, 14, 18, 18, 70, 72, 84, 18, 14, 18, 19, 19, 14, 91, 96, +19, 18, 19, 21, 21, 18, 103, 14, 21, 19, 21, 109, nil, 19, nil, +18, 0, 21, nil, 0, nil, 21, nil, 19, nil, 22, 22, 22, 25, 25, +22, 21, 22, 25, nil, 25, 0, nil, nil, 22, 27, 27, 25, 22, nil, +27, 25, 27, nil, 22, nil, nil, 2, 22, 27, 2, 25, nil, 27, 28, +28, nil, 29, 29, 28, nil, 28, 29, 27, 29, nil, nil, 2, 28, 30, +30, 29, 28, nil, 30, 29, 30, nil, nil, nil, nil, 3, 28, 30, 3, +29, nil, 30, 31, 31, nil, 32, 32, 31, nil, 31, 32, 30, 32, nil, +nil, 3, 31, 33, 33, 32, 31, nil, 33, 32, 33, nil, nil, nil, nil, +4, 31, 33, 4, 32, nil, 33, 34, 34, nil, 35, 35, 34, nil, 34, +35, 33, 35, nil, nil, 4, 34, 36, 36, 35, 34, nil, 36, 35, 36, +nil, nil, nil, nil, 81, 34, 36, 81, 35, nil, 36, 37, 37, nil, 38, +38, 37, nil, 37, 38, 36, 38, nil, nil, 81, 37, 39, 39, 38, 37, +nil, 39, 38, 39, nil, nil, nil, nil, 101, 37, 39, 101, 38, nil, 39, +43, 43, 43, 52, 52, 43, nil, 43, 52, 39, 52, nil, nil, 101, 43, +74, 74, 52, 43, nil, 74, 52, 74, nil, nil, nil, nil, 52, 43, 74, +nil, 52, nil, 74, 76, 76, nil, 97, 97, 76, nil, 76, 97, 74, 97, +nil, nil, nil, 76, 102, 102, 97, 76, nil, 102, 97, 102, nil, nil, nil, +nil, 97, 76, 102, nil, 97, nil, 102, 53, nil, nil, nil, nil, 102, nil, +53, nil, 102, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, nil, 53, +53, 53, 49, nil, nil, 53, 49, 106, nil, 49, 106, nil, 49, 49, 49, +49, 49, 49, 49, 49, 49, 49, 79, 49, 49, 49, 79, 106, 49, 79, +nil, nil, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, nil, 79, 79, +79, 47, 47, 79, nil, nil, nil, nil, nil, 47, nil, nil, 47, 47, 47, +47, 47, 47, 47, 47, 47, 47, 71, 47, 47, 47, 71, nil, nil, 71, +nil, nil, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 88, 71, 71, +71, 88, nil, nil, 88, nil, nil, 88, 88, 88, 88, 88, 88, 88, 88, +88, 88, 99, 88, 88, 88, 99, nil, nil, 99, nil, nil, 99, 99, 99, +99, 99, 99, 99, 99, 99, 99, nil, 99, 99, 99, 104, 104, nil, nil, +104, nil, nil, 104, nil, nil, 104, 104, 104, 104, 104, 104, 104, 104, 104, +104, 67, 104, 104, 104, nil, nil, nil, 67, nil, nil, 67, 67, 67, 67, +67, 67, 67, 67, 67, 67, 61, 67, 67, nil, nil, nil, nil, 61, nil, +nil, 61, nil, 62, nil, nil, nil, 61, 61, 61, 62, nil, 61, 62, nil, +63, nil, nil, nil, 62, 62, 62, 63, nil, 62, 63, nil, 64, nil, nil, +nil, 63, 63, 63, 64, nil, 63, 64, nil, 65, nil, nil, nil, 64, 64, +64, 65, nil, 64, 65, nil, 66, nil, nil, nil, 65, 65, 65, 66, nil, +65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 58, 66, 59, nil, +nil, nil, nil, 58, nil, 59, 58, nil, 59, nil, nil, nil, nil, 58, 58, +59, 59] + +racc_action_pointer = [ +98, 4, 134, 168, 202, 20, 0, 37, nil, nil, nil, 41, 7, 35, 64, +nil, nil, nil, 72, 80, nil, 88, 110, nil, nil, 113, 43, 125, 144, 147, +159, 178, 181, 193, 212, 215, 227, 246, 249, 261, 45, nil, nil, 280, -3, -2, - +1, 419, 22, 374, nil, nil, 283, 350, 61, 17, 25, 61, 623, 625, 21, +543, 555, 567, 579, 591, 603, 523, nil, 48, 72, 439, 48, nil, 295, nil, +314, nil, nil, 394, nil, 236, nil, nil, 76, nil, nil, nil, 459, nil, nil, +79, nil, nil, - +1, nil, 60, 317, nil, 479, nil, 270, 329, 87, 503, nil, 374, 29, nil, +92, nil, 42, nil] + +racc_action_default = [-1, -57, -1, -1, -1, -57, -57, -57, -2, -3, -4, -57, -57, -7, -57, -9, -10, -11, -57, -57, -31, -35, -57, 113, -5, -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, -57, -6, -12, -40, -57, -16, -17, -34, -57, -57, -46, -47, -57, -57, -15, -18, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -41, -43, -40, -40, -57, -38, -57, -8, -35, -32, -45, -57, -48, -1, -13, -14, -57, -44, -37, -36, -40, -33, -50, -57, -42, -39, -57, -49, -57, -57, -51, -57, -52, -1, -57, -57, -57, -54, -1, -57, -56, -57, -53, -57, -55] + +racc_goto_table = [ +1, 11, 8, 9, 10, 48, 68, 12, 42, 50, 44, 72, 80, 73, 45, +46, 100, 105, 49, nil, nil, 53, nil, 55, 56, 57, 58, 59, 60, 61, +62, 63, 64, 65, 66, 67, 78, nil, nil, 71, 85, 86, 95, nil, nil, +nil, nil, nil, 79, 83, 92, nil, 108, nil, nil, 110, nil, nil, 93, 112, +89, nil, nil, nil, nil, nil, 90, nil, nil, nil, 88, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, 91, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, 99, nil, nil, nil, nil, 104, nil, nil, 103, nil, nil, nil, +nil, 109] + +racc_goto_check = [ +1, 4, 1, 1, 1, 9, 12, 5, 8, 14, 4, 10, 15, 11, 4, +4, 17, 18, 4, nil, nil, 4, nil, 4, 4, 4, 4, 4, 4, 4, +4, 4, 4, 4, 4, 4, 14, nil, nil, 4, 11, 11, 16, nil, nil, +nil, nil, nil, 4, 8, 12, nil, 16, nil, nil, 16, nil, nil, 11, 16, +9, nil, nil, nil, nil, nil, 14, nil, nil, nil, 4, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, 1, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, 4, nil, nil, nil, nil, 4, nil, nil, 1, nil, nil, nil, +nil, 1] + +racc_goto_pointer = [nil, 0, nil, nil, -4, 2, nil, nil, -5, -16, -32, -30, -34, nil, -13, -40, -52, -81, -85] + +racc_goto_default = [ +nil, nil, 3, 4, 47, nil, 20, 17, nil, nil, nil, nil, nil, 69, nil, +nil, nil, nil, nil] + +racc_reduce_table = [ + 0, 0, :racc_error, + 0, 37, :_reduce_1, + 2, 37, :_reduce_2, + 2, 37, :_reduce_3, + 2, 37, :_reduce_4, + 3, 38, :_reduce_5, + 3, 38, :_reduce_6, + 1, 42, :_reduce_none, + 3, 42, :_reduce_8, + 1, 40, :_reduce_none, + 1, 40, :_reduce_none, + 1, 40, :_reduce_none, + 2, 40, :_reduce_12, + 4, 40, :_reduce_13, + 4, 40, :_reduce_14, + 3, 40, :_reduce_15, + 2, 40, :_reduce_16, + 2, 40, :_reduce_17, + 3, 40, :_reduce_18, + 3, 40, :_reduce_19, + 3, 40, :_reduce_20, + 3, 40, :_reduce_21, + 3, 40, :_reduce_22, + 3, 40, :_reduce_23, + 3, 40, :_reduce_24, + 3, 40, :_reduce_25, + 3, 40, :_reduce_26, + 3, 40, :_reduce_27, + 3, 40, :_reduce_28, + 3, 40, :_reduce_29, + 3, 40, :_reduce_30, + 1, 40, :_reduce_none, + 3, 43, :_reduce_32, + 3, 45, :_reduce_33, + 1, 45, :_reduce_34, + 0, 45, :_reduce_35, + 3, 44, :_reduce_36, + 2, 46, :_reduce_37, + 1, 46, :_reduce_38, + 3, 47, :_reduce_39, + 0, 47, :_reduce_40, + 3, 41, :_reduce_41, + 3, 48, :_reduce_42, + 1, 48, :_reduce_43, + 2, 49, :_reduce_44, + 4, 39, :_reduce_45, + 3, 39, :_reduce_46, + 1, 50, :_reduce_47, + 2, 50, :_reduce_48, + 4, 51, :_reduce_49, + 2, 51, :_reduce_50, + 2, 52, :_reduce_51, + 2, 52, :_reduce_52, + 4, 53, :_reduce_53, + 3, 53, :_reduce_54, + 4, 54, :_reduce_55, + 2, 54, :_reduce_56 ] + +racc_reduce_n = 57 + +racc_shift_n = 113 + +racc_token_table = { + false => 0, + :error => 1, + :comma => 2, + :dot => 3, + :endtag => 4, + :ident => 5, + :integer => 6, + :keyword => 7, + :lblock => 8, + :lblock2 => 9, + :lbracket => 10, + :linterp => 11, + :lparen => 12, + :op_div => 13, + :op_eq => 14, + :op_gt => 15, + :op_geq => 16, + :op_lt => 17, + :op_leq => 18, + :op_minus => 19, + :op_mod => 20, + :op_mul => 21, + :op_neq => 22, + :op_not => 23, + :op_plus => 24, + :op_and => 25, + :op_or => 26, + :pipe => 27, + :plaintext => 28, + :rblock => 29, + :rbracket => 30, + :rinterp => 31, + :rparen => 32, + :string => 33, + :tag_ident => 34, + :op_uminus => 35 } + +racc_nt_base = 36 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ + "$end", + "error", + "comma", + "dot", + "endtag", + "ident", + "integer", + "keyword", + "lblock", + "lblock2", + "lbracket", + "linterp", + "lparen", + "op_div", + "op_eq", + "op_gt", + "op_geq", + "op_lt", + "op_leq", + "op_minus", + "op_mod", + "op_mul", + "op_neq", + "op_not", + "op_plus", + "op_and", + "op_or", + "pipe", + "plaintext", + "rblock", + "rbracket", + "rinterp", + "rparen", + "string", + "tag_ident", + "op_uminus", + "$start", + "block", + "interp", + "tag", + "expr", + "filter_chain", + "primary_expr", + "tuple", + "function_args", + "tuple_content", + "function_args_inside", + "function_keywords", + "filter_chain_cont", + "filter_call", + "tag_first_cont", + "tag_first_cont2", + "tag_next_cont", + "tag_next_cont2", + "tag_next_cont3" ] + +Racc_debug_parser = false + +##### State transition tables end ##### + +# reduce 0 omitted + +module_eval(<<'.,.,', 'liquor.y', 47) + def _reduce_1(val, _values, result) + result = [] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 49) + def _reduce_2(val, _values, result) + result = [ val[0], *val[1] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 51) + def _reduce_3(val, _values, result) + result = [ val[0], *val[1] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 53) + def _reduce_4(val, _values, result) + result = [ val[0], *val[1] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 57) + def _reduce_5(val, _values, result) + result = [ :interp, retag(val), val[1] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 59) + def _reduce_6(val, _values, result) + result = [ :interp, retag(val), val[1] ] + result + end +.,., + +# reduce 7 omitted + +module_eval(<<'.,.,', 'liquor.y', 64) + def _reduce_8(val, _values, result) + result = [ val[1][0], retag(val), *val[1][2..-1] ] + result + end +.,., + +# reduce 9 omitted + +# reduce 10 omitted + +# reduce 11 omitted + +module_eval(<<'.,.,', 'liquor.y', 71) + def _reduce_12(val, _values, result) + result = [ :call, retag(val), val[0], val[1] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 73) + def _reduce_13(val, _values, result) + result = [ :index, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 75) + def _reduce_14(val, _values, result) + result = [ :external, retag(val), val[0], val[2], val[3] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 77) + def _reduce_15(val, _values, result) + result = [ :external, retag(val), val[0], val[2], nil ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 79) + def _reduce_16(val, _values, result) + result = [ :uminus, retag(val), val[1] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 81) + def _reduce_17(val, _values, result) + result = [ :not, retag(val), val[1] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 83) + def _reduce_18(val, _values, result) + result = [ :mul, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 85) + def _reduce_19(val, _values, result) + result = [ :div, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 87) + def _reduce_20(val, _values, result) + result = [ :mod, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 89) + def _reduce_21(val, _values, result) + result = [ :plus, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 91) + def _reduce_22(val, _values, result) + result = [ :minus, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 93) + def _reduce_23(val, _values, result) + result = [ :eq, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 95) + def _reduce_24(val, _values, result) + result = [ :neq, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 97) + def _reduce_25(val, _values, result) + result = [ :lt, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 99) + def _reduce_26(val, _values, result) + result = [ :leq, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 101) + def _reduce_27(val, _values, result) + result = [ :gt, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 103) + def _reduce_28(val, _values, result) + result = [ :geq, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 105) + def _reduce_29(val, _values, result) + result = [ :and, retag(val), val[0], val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 107) + def _reduce_30(val, _values, result) + result = [ :or, retag(val), val[0], val[2] ] + result + end +.,., + +# reduce 31 omitted + +module_eval(<<'.,.,', 'liquor.y', 112) + def _reduce_32(val, _values, result) + result = [ :tuple, retag(val), val[1].compact ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 116) + def _reduce_33(val, _values, result) + result = [ val[0], *val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 118) + def _reduce_34(val, _values, result) + result = [ val[0] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 120) + def _reduce_35(val, _values, result) + result = [ ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 124) + def _reduce_36(val, _values, result) + result = [ :args, retag(val), *val[1] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 128) + def _reduce_37(val, _values, result) + result = [ val[0], val[1][2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 130) + def _reduce_38(val, _values, result) + result = [ nil, val[0][2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 134) + def _reduce_39(val, _values, result) + name = val[0][2].to_sym + tail = val[2][2] + loc = retag([ val[0], val[1] ]) + + if tail.include? name + @errors << SyntaxError.new("duplicate keyword argument `#{val[0][2]}'", + tail[name][1]) + end + + hash = { + name => [ val[1][0], loc, *val[1][2..-1] ] + }.merge(tail) + + result = [ :keywords, retag([ loc, val[2] ]), hash ] + + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 150) + def _reduce_40(val, _values, result) + result = [ :keywords, nil, {} ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 154) + def _reduce_41(val, _values, result) + result = [ val[0], *val[2] ]. + reduce { |tree, node| node[3][2] = tree; node } + + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 160) + def _reduce_42(val, _values, result) + result = [ val[0], *val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 162) + def _reduce_43(val, _values, result) + result = [ val[0] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 166) + def _reduce_44(val, _values, result) + ident_loc = val[0][1] + empty_args_loc = { line: ident_loc[:line], + start: ident_loc[:end] + 1, + end: ident_loc[:end] + 1, } + result = [ :call, val[0][1], val[0], + [ :args, val[1][1] || empty_args_loc, nil, val[1][2] ] ] + + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 176) + def _reduce_45(val, _values, result) + result = [ :tag, retag(val), val[1], val[2], *reduce_tag_args(val[3][2]) ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 178) + def _reduce_46(val, _values, result) + result = [ :tag, retag(val), val[1], nil, *reduce_tag_args(val[2][2]) ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 186) + def _reduce_47(val, _values, result) + result = [ :cont, retag(val), [] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 188) + def _reduce_48(val, _values, result) + result = [ :cont, retag(val), [ val[0], *val[1][2] ] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 192) + def _reduce_49(val, _values, result) + result = [ :cont2, val[0][1], [ [:block, val[0][1], val[1] ], *val[3] ] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 194) + def _reduce_50(val, _values, result) + result = [ :cont2, retag(val), [ val[0], *val[1][2] ] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 198) + def _reduce_51(val, _values, result) + result = [] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 200) + def _reduce_52(val, _values, result) + result = [ val[0], *val[1] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 204) + def _reduce_53(val, _values, result) + result = [ [:block, val[0][1], val[1] ], *val[3] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 206) + def _reduce_54(val, _values, result) + result = [ val[0], val[1], *val[2] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 210) + def _reduce_55(val, _values, result) + result = [ [:block, val[0][1], val[1] ], *val[3] ] + result + end +.,., + +module_eval(<<'.,.,', 'liquor.y', 212) + def _reduce_56(val, _values, result) + result = [ val[0], *val[1] ] + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] +end + + end # class Parser + end # module Liquor diff --git a/test/regress/lr_not_lalr.out b/test/regress/lr_not_lalr.out new file mode 100644 index 00000000..f1b5cbf9 --- /dev/null +++ b/test/regress/lr_not_lalr.out @@ -0,0 +1,35 @@ +Parsing grammar file... +Generating and resolving LALR states... +Creating parser file... + +Warning: This rule will never be used due to low precedence: +lr_not_lalr.y:12: F: e + +When the next token is either a or b, it is overridden by this higher-precedence rule: +lr_not_lalr.y:11: E: e + +Warning: Reduce/reduce conflict on a, after the following input: +a e + +It is possible to reduce by either of these rules: +lr_not_lalr.y:11: E: e +lr_not_lalr.y:12: F: e + +After reducing to E, one path to a successful parse would be: +a (reduce to S) + +I can't see any way that reducing to F could possibly lead to a successful parse from this situation. But maybe if this parser state was reached through a different input sequence, it could. I'm just a LALR parser generator and I can be pretty daft sometimes. + +Warning: Reduce/reduce conflict on b, after the following input: +a e + +It is possible to reduce by either of these rules: +lr_not_lalr.y:11: E: e +lr_not_lalr.y:12: F: e + +I can't see any way that reducing to E could possibly lead to a successful parse from this situation. But maybe if this parser state was reached through a different input sequence, it could. I'm just a LALR parser generator and I can be pretty daft sometimes. + +After reducing to F, one path to a successful parse would be: +b (reduce to S) + +1 useless rule, 2 reduce/reduce conflicts diff --git a/test/regress/lr_not_lalr2.out b/test/regress/lr_not_lalr2.out new file mode 100644 index 00000000..0e9c2b60 --- /dev/null +++ b/test/regress/lr_not_lalr2.out @@ -0,0 +1,35 @@ +Parsing grammar file... +Generating and resolving LALR states... +Creating parser file... + +Warning: This rule will never be used due to low precedence: +lr_not_lalr2.y:13: F: A + +When the next token is either "]" or ")", it is overridden by this higher-precedence rule: +lr_not_lalr2.y:12: E: A + +Warning: Reduce/reduce conflict on "]", after the following input: +A + +It is possible to reduce by either of these rules: +lr_not_lalr2.y:12: E: A +lr_not_lalr2.y:13: F: A + +After reducing to E, one path to a successful parse would be: +"]" (reduce to S) + +I can't see any way that reducing to F could possibly lead to a successful parse from this situation. But maybe if this parser state was reached through a different input sequence, it could. I'm just a LALR parser generator and I can be pretty daft sometimes. + +Warning: Reduce/reduce conflict on ")", after the following input: +A + +It is possible to reduce by either of these rules: +lr_not_lalr2.y:12: E: A +lr_not_lalr2.y:13: F: A + +I can't see any way that reducing to E could possibly lead to a successful parse from this situation. But maybe if this parser state was reached through a different input sequence, it could. I'm just a LALR parser generator and I can be pretty daft sometimes. + +After reducing to F, one path to a successful parse would be: +")" (reduce to S) + +1 useless rule, 2 reduce/reduce conflicts diff --git a/test/regress/machete.rb b/test/regress/machete.rb new file mode 100644 index 00000000..60540dea --- /dev/null +++ b/test/regress/machete.rb @@ -0,0 +1,806 @@ +# +# DO NOT MODIFY!!!! +# This file was automatically generated by Racc 2.0.0.dev +# (codename: Mecha Oishii) from Racc grammar file "machete.y". +# + +require 'racc/parser.rb' +module Machete + class Parser < Racc::Parser + +module_eval(<<'...end machete.y/module_eval...', 'machete.y', 175) + +include Matchers + +class SyntaxError < StandardError; end + +def parse(input) + @input = input + @pos = 0 + + do_parse +end + +private + +def integer_value(value) + if value =~ /^0[bB]/ + value[2..-1].to_i(2) + elsif value =~ /^0[oO]/ + value[2..-1].to_i(8) + elsif value =~ /^0[dD]/ + value[2..-1].to_i(10) + elsif value =~ /^0[xX]/ + value[2..-1].to_i(16) + elsif value =~ /^0/ + value.to_i(8) + else + value.to_i + end +end + +def symbol_value(value) + value[1..-1].to_sym +end + +def string_value(value) + quote = value[0..0] + if quote == "'" + value[1..-2].gsub("\\\\", "\\").gsub("\\'", "'") + elsif quote == '"' + value[1..-2]. + gsub("\\\\", "\\"). + gsub('\\"', '"'). + gsub("\\n", "\n"). + gsub("\\t", "\t"). + gsub("\\r", "\r"). + gsub("\\f", "\f"). + gsub("\\v", "\v"). + gsub("\\a", "\a"). + gsub("\\e", "\e"). + gsub("\\b", "\b"). + gsub("\\s", "\s"). + gsub(/\\([0-7]{1,3})/) { $1.to_i(8).chr }. + gsub(/\\x([0-9a-fA-F]{1,2})/) { $1.to_i(16).chr } + else + raise "Unknown quote: #{quote.inspect}." + end +end + +REGEXP_OPTIONS = { + 'i' => Regexp::IGNORECASE, + 'm' => Regexp::MULTILINE, + 'x' => Regexp::EXTENDED +} + +def regexp_value(value) + /\A\/(.*)\/([imx]*)\z/ =~ value + pattern, options = $1, $2 + + Regexp.new(pattern, options.chars.map { |ch| REGEXP_OPTIONS[ch] }.inject(:|)) +end + +# "^" needs to be here because if it were among operators recognized by +# METHOD_NAME, "^=" would be recognized as two tokens. +SIMPLE_TOKENS = [ + "|", + "<", + ">", + ",", + "=", + "^=", + "^", + "$=", + "[", + "]", + "*=", + "*", + "+", + "?", + "{", + "}" +] + +COMPLEX_TOKENS = [ + [:NIL, /^nil/], + [:TRUE, /^true/], + [:FALSE, /^false/], + # INTEGER needs to be before METHOD_NAME, otherwise e.g. "+1" would be + # recognized as two tokens. + [ + :INTEGER, + /^ + [+-]? # sign + ( + 0[bB][01]+(_[01]+)* # binary (prefixed) + | + 0[oO][0-7]+(_[0-7]+)* # octal (prefixed) + | + 0[dD]\d+(_\d+)* # decimal (prefixed) + | + 0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)* # hexadecimal (prefixed) + | + 0[0-7]*(_[0-7]+)* # octal (unprefixed) + | + [1-9]\d*(_\d+)* # decimal (unprefixed) + ) + /x + ], + [ + :SYMBOL, + /^ + : + ( + # class name + [A-Z][a-zA-Z0-9_]* + | + # regular method name + [a-z_][a-zA-Z0-9_]*[?!=]? + | + # instance variable name + @[a-zA-Z_][a-zA-Z0-9_]* + | + # class variable name + @@[a-zA-Z_][a-zA-Z0-9_]* + | + # operator (sorted by length, then alphabetically) + (<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[%&*+\-\/<>^`|~]) + ) + /x + ], + [ + :STRING, + /^ + ( + ' # sinqle-quoted string + ( + \\[\\'] # escape + | + [^'] # regular character + )* + ' + | + " # double-quoted string + ( + \\ # escape + ( + [\\"ntrfvaebs] # one-character escape + | + [0-7]{1,3} # octal number escape + | + x[0-9a-fA-F]{1,2} # hexadecimal number escape + ) + | + [^"] # regular character + )* + " + ) + /x + ], + [ + :REGEXP, + /^ + \/ + ( + \\ # escape + ( + [\\\/ntrfvaebs\(\)\[\]\{\}\-\.\?\*\+\|\^\$] # one-character escape + | + [0-7]{2,3} # octal number escape + | + x[0-9a-fA-F]{1,2} # hexadecimal number escape + ) + | + [^\/] # regular character + )* + \/ + [imx]* + /x + ], + # ANY, EVEN and ODD need to be before METHOD_NAME, otherwise they would be + # recognized as method names. + [:ANY, /^any/], + [:EVEN, /^even/], + [:ODD, /^odd/], + # We exclude "*", "+", "<", ">", "^" and "|" from method names since they are + # lexed as simple tokens. This is because they have also other meanings in + # Machette patterns beside Ruby method names. + [ + :METHOD_NAME, + /^ + ( + # regular name + [a-z_][a-zA-Z0-9_]*[?!=]? + | + # operator (sorted by length, then alphabetically) + (<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[%&\-\/`~]) + ) + /x + ], + [:CLASS_NAME, /^[A-Z][a-zA-Z0-9_]*/] +] + +def next_token + skip_whitespace + + return false if remaining_input.empty? + + # Complex tokens need to be before simple tokens, otherwise e.g. "<<" would be + # recognized as two tokens. + + COMPLEX_TOKENS.each do |type, regexp| + if remaining_input =~ regexp + @pos += $&.length + return [type, $&] + end + end + + SIMPLE_TOKENS.each do |token| + if remaining_input[0...token.length] == token + @pos += token.length + return [token, token] + end + end + + raise SyntaxError, "Unexpected character: #{remaining_input[0..0].inspect}." +end + +def skip_whitespace + if remaining_input =~ /\A^[ \t\r\n]+/ + @pos += $&.length + end +end + +def remaining_input + @input[@pos..-1] +end + +def on_error(error_token_id, error_value, value_stack) + raise SyntaxError, "Unexpected token: #{error_value.inspect}." +end +...end machete.y/module_eval... +##### State transition tables begin ### + +racc_action_table = [ +75, 19, 9, 10, 11, 12, 13, 14, 15, 16, 66, 67, 68, 7, 24, +9, 10, 11, 12, 13, 14, 15, 16, 17, 74, 8, 7, 47, 9, 10, +11, 12, 13, 14, 15, 16, 48, 18, 8, 7, 71, 9, 10, 11, 12, +13, 14, 15, 16, 72, 70, 8, 7, 73, 9, 10, 11, 12, 13, 14, +15, 16, 69, 18, 8, 7, 30, 31, 32, 51, 52, 53, 54, 33, 34, +35, 29, 8, 41, 38, 39, 76, 30, 31, 32, 77, 36, 37, 40, 33, +34, 35, 29, nil, 41, 38, 39, 18, 49, 50, 62, 63, 36, 37, 40, +43, 44, 55, 64, 65, 45, 46, 57, 58, nil, nil, nil, nil, nil, 56] + +racc_action_check = [ +70, 7, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54, 54, 0, 17, +8, 8, 8, 8, 8, 8, 8, 8, 1, 70, 0, 8, 21, 18, 18, +18, 18, 18, 18, 18, 18, 22, 1, 8, 18, 56, 48, 48, 48, 48, +48, 48, 48, 48, 57, 55, 18, 48, 58, 51, 51, 51, 51, 51, 51, +51, 51, 55, 61, 48, 51, 19, 19, 19, 28, 28, 28, 28, 19, 19, +19, 19, 51, 19, 19, 19, 71, 50, 50, 50, 75, 19, 19, 19, 50, +50, 50, 50, nil, 50, 50, 50, 20, 26, 26, 52, 52, 50, 50, 50, +20, 20, 46, 53, 53, 20, 20, 46, 46, nil, nil, nil, nil, nil, 46] + +racc_action_pointer = [0, 23, nil, nil, nil, nil, nil, - +14, 13, nil, nil, nil, nil, nil, nil, nil, nil, 14, 26, 64, 83, 1, +19, nil, nil, nil, 82, nil, 51, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, 102, nil, 39, nil, 80, 52, +94, 102, 4, 33, 35, 20, 24, nil, nil, 49, nil, nil, nil, nil, nil, +nil, nil, nil, -5, 52, nil, nil, nil, 56, nil, nil] + +racc_action_default = [-56, -56, -1, -3, -4, -5, -6, -7, -33, -48, -49, -50, -51, -52, -53, -54, -55, -56, -56, -56, -37, -56, -34, -35, 78, -2, -56, -9, -56, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -31, -38, -39, -40, -41, -56, -32, -56, -8, -56, -56, -56, -56, -56, -56, -56, -56, -56, -36, -10, -11, -12, -15, -13, -16, -14, -17, -18, -42, -56, -56, -46, -47, -43, -56, -44, -45] + +racc_goto_table = [ +1, 23, 27, 25, 26, 21, 22, 42, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, 60, nil, nil, nil, nil, nil, nil, nil, 59, nil, nil, nil, +nil, nil, nil, nil, nil, nil, 61] + +racc_goto_check = [ +1, 12, 8, 2, 7, 10, 11, 13, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, 8, nil, nil, nil, nil, nil, nil, nil, 12, nil, nil, nil, +nil, nil, nil, nil, nil, nil, 1] + +racc_goto_pointer = [nil, 0, -15, nil, nil, nil, nil, -15, -17, nil, -3, -2, -7, -13] + +racc_goto_default = [nil, 20, 2, 3, 4, 5, 6, nil, nil, 28, nil, nil, nil, nil] + +racc_reduce_table = [ + 0, 0, :racc_error, + 1, 31, :_reduce_none, + 3, 31, :_reduce_2, + 1, 32, :_reduce_none, + 1, 32, :_reduce_none, + 1, 32, :_reduce_none, + 1, 32, :_reduce_none, + 1, 33, :_reduce_7, + 4, 33, :_reduce_8, + 1, 37, :_reduce_none, + 3, 37, :_reduce_10, + 3, 38, :_reduce_11, + 3, 38, :_reduce_12, + 3, 38, :_reduce_13, + 3, 38, :_reduce_14, + 3, 38, :_reduce_15, + 3, 38, :_reduce_16, + 3, 38, :_reduce_17, + 3, 38, :_reduce_18, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 1, 39, :_reduce_none, + 3, 34, :_reduce_32, + 0, 40, :_reduce_33, + 1, 40, :_reduce_none, + 1, 41, :_reduce_35, + 3, 41, :_reduce_36, + 1, 42, :_reduce_none, + 2, 42, :_reduce_38, + 1, 43, :_reduce_39, + 1, 43, :_reduce_40, + 1, 43, :_reduce_41, + 3, 43, :_reduce_42, + 4, 43, :_reduce_43, + 4, 43, :_reduce_44, + 5, 43, :_reduce_45, + 3, 43, :_reduce_46, + 3, 43, :_reduce_47, + 1, 35, :_reduce_48, + 1, 35, :_reduce_49, + 1, 35, :_reduce_50, + 1, 35, :_reduce_51, + 1, 35, :_reduce_52, + 1, 35, :_reduce_53, + 1, 35, :_reduce_54, + 1, 36, :_reduce_55 ] + +racc_reduce_n = 56 + +racc_shift_n = 78 + +racc_token_table = { + false => 0, + :error => 1, + :NIL => 2, + :TRUE => 3, + :FALSE => 4, + :INTEGER => 5, + :SYMBOL => 6, + :STRING => 7, + :REGEXP => 8, + :ANY => 9, + :EVEN => 10, + :ODD => 11, + :METHOD_NAME => 12, + :CLASS_NAME => 13, + "|" => 14, + "<" => 15, + ">" => 16, + "," => 17, + "=" => 18, + "^=" => 19, + "$=" => 20, + "*=" => 21, + "*" => 22, + "+" => 23, + "^" => 24, + "[" => 25, + "]" => 26, + "?" => 27, + "{" => 28, + "}" => 29 } + +racc_nt_base = 30 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ + "$end", + "error", + "NIL", + "TRUE", + "FALSE", + "INTEGER", + "SYMBOL", + "STRING", + "REGEXP", + "ANY", + "EVEN", + "ODD", + "METHOD_NAME", + "CLASS_NAME", + "\"|\"", + "\"<\"", + "\">\"", + "\",\"", + "\"=\"", + "\"^=\"", + "\"$=\"", + "\"*=\"", + "\"*\"", + "\"+\"", + "\"^\"", + "\"[\"", + "\"]\"", + "\"?\"", + "\"{\"", + "\"}\"", + "$start", + "expression", + "primary", + "node", + "array", + "literal", + "any", + "attrs", + "attr", + "method_name", + "items_opt", + "items", + "item", + "quantifier" ] + +Racc_debug_parser = false + +##### State transition tables end ##### + +# reduce 0 omitted + +# reduce 1 omitted + +module_eval(<<'.,.,', 'machete.y', 44) + def _reduce_2(val, _values, result) + result = if val[0].is_a?(ChoiceMatcher) + ChoiceMatcher.new(val[0].alternatives << val[2]) + else + ChoiceMatcher.new([val[0], val[2]]) + end + + result + end +.,., + +# reduce 3 omitted + +# reduce 4 omitted + +# reduce 5 omitted + +# reduce 6 omitted + +module_eval(<<'.,.,', 'machete.y', 57) + def _reduce_7(val, _values, result) + result = NodeMatcher.new(val[0].to_sym) + + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 60) + def _reduce_8(val, _values, result) + result = NodeMatcher.new(val[0].to_sym, val[2]) + + result + end +.,., + +# reduce 9 omitted + +module_eval(<<'.,.,', 'machete.y', 64) + def _reduce_10(val, _values, result) + result = val[0].merge(val[2]) + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 66) + def _reduce_11(val, _values, result) + result = { val[0].to_sym => val[2] } + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 68) + def _reduce_12(val, _values, result) + result = { + val[0].to_sym => SymbolRegexpMatcher.new( + Regexp.new("^" + Regexp.escape(symbol_value(val[2]).to_s)) + ) + } + + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 75) + def _reduce_13(val, _values, result) + result = { + val[0].to_sym => SymbolRegexpMatcher.new( + Regexp.new(Regexp.escape(symbol_value(val[2]).to_s) + "$") + ) + } + + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 82) + def _reduce_14(val, _values, result) + result = { + val[0].to_sym => SymbolRegexpMatcher.new( + Regexp.new(Regexp.escape(symbol_value(val[2]).to_s)) + ) + } + + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 89) + def _reduce_15(val, _values, result) + result = { + val[0].to_sym => StringRegexpMatcher.new( + Regexp.new("^" + Regexp.escape(string_value(val[2]))) + ) + } + + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 96) + def _reduce_16(val, _values, result) + result = { + val[0].to_sym => StringRegexpMatcher.new( + Regexp.new(Regexp.escape(string_value(val[2])) + "$") + ) + } + + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 103) + def _reduce_17(val, _values, result) + result = { + val[0].to_sym => StringRegexpMatcher.new( + Regexp.new(Regexp.escape(string_value(val[2]))) + ) + } + + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 110) + def _reduce_18(val, _values, result) + result = { + val[0].to_sym => IndifferentRegexpMatcher.new( + Regexp.new(regexp_value(val[2])) + ) + } + + result + end +.,., + +# reduce 19 omitted + +# reduce 20 omitted + +# reduce 21 omitted + +# reduce 22 omitted + +# reduce 23 omitted + +# reduce 24 omitted + +# reduce 25 omitted + +# reduce 26 omitted + +# reduce 27 omitted + +# reduce 28 omitted + +# reduce 29 omitted + +# reduce 30 omitted + +# reduce 31 omitted + +module_eval(<<'.,.,', 'machete.y', 134) + def _reduce_32(val, _values, result) + result = ArrayMatcher.new(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 136) + def _reduce_33(val, _values, result) + result = [] + result + end +.,., + +# reduce 34 omitted + +module_eval(<<'.,.,', 'machete.y', 139) + def _reduce_35(val, _values, result) + result = [val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 140) + def _reduce_36(val, _values, result) + result = val[0] << val[2] + result + end +.,., + +# reduce 37 omitted + +module_eval(<<'.,.,', 'machete.y', 143) + def _reduce_38(val, _values, result) + result = Quantifier.new(val[0], *val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 145) + def _reduce_39(val, _values, result) + result = [0, nil, 1] + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 146) + def _reduce_40(val, _values, result) + result = [1, nil, 1] + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 147) + def _reduce_41(val, _values, result) + result = [0, 1, 1] + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 149) + def _reduce_42(val, _values, result) + result = [integer_value(val[1]), integer_value(val[1]), 1] + + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 152) + def _reduce_43(val, _values, result) + result = [integer_value(val[1]), nil, 1] + + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 155) + def _reduce_44(val, _values, result) + result = [0, integer_value(val[2]), 1] + + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 158) + def _reduce_45(val, _values, result) + result = [integer_value(val[1]), integer_value(val[3]), 1] + + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 160) + def _reduce_46(val, _values, result) + result = [0, nil, 2] + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 161) + def _reduce_47(val, _values, result) + result = [1, nil, 2] + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 163) + def _reduce_48(val, _values, result) + result = LiteralMatcher.new(nil) + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 164) + def _reduce_49(val, _values, result) + result = LiteralMatcher.new(true) + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 165) + def _reduce_50(val, _values, result) + result = LiteralMatcher.new(false) + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 166) + def _reduce_51(val, _values, result) + result = LiteralMatcher.new(integer_value(val[0])) + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 167) + def _reduce_52(val, _values, result) + result = LiteralMatcher.new(symbol_value(val[0])) + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 168) + def _reduce_53(val, _values, result) + result = LiteralMatcher.new(string_value(val[0])) + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 169) + def _reduce_54(val, _values, result) + result = LiteralMatcher.new(regexp_value(val[0])) + result + end +.,., + +module_eval(<<'.,.,', 'machete.y', 171) + def _reduce_55(val, _values, result) + result = AnyMatcher.new + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] +end + + end # class Parser + end # module Machete diff --git a/test/regress/mediacloth.rb b/test/regress/mediacloth.rb new file mode 100644 index 00000000..70882f23 --- /dev/null +++ b/test/regress/mediacloth.rb @@ -0,0 +1,1339 @@ +# +# DO NOT MODIFY!!!! +# This file was automatically generated by Racc 2.0.0.dev +# (codename: Mecha Oishii) from Racc grammar file "mediacloth.y". +# + +require 'racc/parser.rb' + +Object.module_eval(<<'...end mediacloth.y/module_eval...', 'mediacloth.y', 561) +require 'mediacloth/mediawikiast' + +...end mediacloth.y/module_eval... +class MediaWikiParser < Racc::Parser + +module_eval(<<'...end mediacloth.y/module_eval...2', 'mediacloth.y', 564) + +attr_accessor :lexer + +def initialize + @nodes = [] + @context = [] + @wiki_ast_length = 0 + super +end + +#Tokenizes input string and parses it. +def parse(input) + @yydebug=true + lexer.tokenize(input) + do_parse + return @nodes.last +end + +#Asks the lexer to return the next token. +def next_token + token = @lexer.lex + if token[0].to_s.upcase.include? "_START" + @context << token[2..3] + elsif token[0].to_s.upcase.include? "_END" + @ast_index = @context.last[0] + @ast_length = token[2] + token[3] - @context.last[0] + @context.pop + else + @ast_index = token[2] + @ast_length = token[3] + end + + @wiki_ast_length += token[3] + + return token[0..1] +end +...end mediacloth.y/module_eval...2 +##### State transition tables begin ### + +racc_action_table = [ +22, 28, 50, 29, 61, 13, 63, 132, 15, 86, 37, 87, 24, 33, 86, +34, 87, 35, 85, 23, 26, 25, 27, 12, 86, 30, 87, 31, 86, 42, +87, 32, 44, 86, 48, 87, 57, 17, 57, 22, 28, 21, 29, 46, 13, +51, 67, 15, 68, 11, 36, 24, 33, 14, 34, 69, 35, 36, 23, 26, +25, 27, 12, 86, 30, 87, 31, 75, 73, 70, 32, 48, 81, 71, 72, +76, 17, 77, 22, 28, 21, 29, 82, 13, 45, 51, 15, -65, 11, 36, 24, 33, 14, 34, - +65, 35, 63, 23, 26, 25, 27, 12, 96, 30, 63, 31, 106, 109, 110, +32, 113, 114, 48, 117, 118, 17, 124, 22, 28, 21, 29, 57, 13, 127, +128, 15, 131, 11, 36, 24, 33, 14, 34, 136, 35, 137, 23, 26, 25, +27, 12, 138, 30, 75, 31, 51, 141, - +63, 32, 106, 106, 150, 153, 51, 17, nil, nil, nil, 21, nil, 22, 28, +53, 29, nil, 13, 11, 36, 15, nil, 14, nil, 24, 33, nil, 34, nil, +35, nil, 23, 26, 25, 27, 12, nil, 30, nil, 31, nil, nil, nil, 32, +nil, nil, nil, nil, nil, 17, nil, 22, 28, 21, 29, 55, 13, nil, nil, +15, nil, 11, 36, 24, 33, 14, 34, nil, 35, nil, 23, 26, 25, 27, +12, nil, 30, nil, 31, nil, nil, nil, 32, nil, nil, nil, nil, nil, 17, +nil, 22, 28, 21, 29, nil, 13, nil, nil, 15, nil, 11, 36, 24, 33, +14, 34, nil, 35, nil, 23, 26, 25, 27, 12, nil, 30, nil, 31, nil, +nil, nil, 32, nil, nil, nil, nil, nil, 17, nil, 22, 28, 21, 29, nil, +13, nil, nil, 15, nil, 11, 36, 24, 33, 14, 34, nil, 35, nil, 23, +26, 25, 27, 12, nil, 30, nil, 31, nil, nil, nil, 32, nil, nil, nil, +nil, nil, 17, nil, 22, 28, 21, 29, nil, 13, nil, nil, 15, nil, 11, +36, 24, 33, 14, 34, nil, 35, nil, 23, 26, 25, 27, 12, nil, 30, +nil, 31, nil, nil, nil, 32, nil, nil, nil, nil, nil, 17, nil, 22, 28, +21, 29, nil, 13, nil, nil, 15, nil, 11, 36, 24, 33, 14, 34, nil, +35, nil, 23, 26, 25, 27, 12, nil, 30, nil, 31, nil, nil, nil, 32, +nil, nil, nil, nil, nil, 17, nil, 22, 28, 21, 29, nil, 13, nil, nil, +15, nil, 11, 36, 24, 33, 14, 34, nil, 35, nil, 23, 26, 25, 27, +12, nil, 30, nil, 31, nil, nil, nil, 32, nil, nil, nil, nil, nil, 17, +78, nil, nil, 21, nil, 22, 28, 88, 29, nil, 13, 11, 36, 15, nil, +14, nil, 24, 33, nil, 34, nil, 35, nil, 23, 26, 25, 27, 12, nil, +30, nil, 31, nil, nil, nil, 32, nil, nil, nil, nil, nil, 17, nil, 22, +28, 21, 29, 89, 13, nil, nil, 15, nil, 11, 36, 24, 33, 14, 34, +nil, 35, nil, 23, 26, 25, 27, 12, nil, 30, nil, 31, nil, nil, nil, +32, nil, nil, nil, nil, nil, 17, nil, 22, 28, 21, 29, nil, 13, nil, +nil, 15, nil, 11, 36, 24, 33, 14, 34, nil, 35, nil, 23, 26, 25, +27, 12, nil, 30, nil, 31, nil, nil, 93, 32, nil, nil, nil, nil, nil, +17, nil, 22, 28, 21, 29, nil, 13, nil, nil, 15, nil, 11, 36, 24, +33, 14, 34, nil, 35, nil, 23, 26, 25, 27, 12, nil, 30, nil, 31, +nil, nil, nil, 32, nil, nil, 98, nil, nil, 17, nil, 22, 28, 21, 29, +nil, 13, nil, nil, 15, nil, 11, 36, 24, 33, 14, 34, nil, 35, nil, +23, 26, 25, 27, 12, nil, 30, nil, 31, nil, nil, nil, 32, nil, nil, +nil, nil, 101, 17, nil, nil, nil, 21, nil, 22, 28, nil, 29, nil, 13, +11, 36, 15, nil, 14, nil, 24, 33, 102, 34, nil, 35, nil, 23, 26, +25, 27, 12, nil, 30, nil, 31, nil, nil, nil, 32, nil, nil, nil, nil, +nil, 17, nil, 22, 28, 21, 29, nil, 13, nil, nil, 15, nil, 11, 36, +24, 33, 14, 34, 103, 35, nil, 23, 26, 25, 27, 12, nil, 30, nil, +31, nil, nil, nil, 32, nil, nil, nil, nil, nil, 17, nil, 22, 28, 21, +29, nil, 13, nil, nil, 15, nil, 11, 36, 24, 33, 14, 34, nil, 35, +104, 23, 26, 25, 27, 12, nil, 30, nil, 31, nil, nil, nil, 32, nil, +nil, nil, nil, nil, 17, nil, 22, 28, 21, 29, nil, 13, nil, nil, 15, +nil, 11, 36, 24, 33, 14, 34, nil, 35, nil, 23, 26, 25, 27, 12, +nil, 30, nil, 31, nil, nil, nil, 32, nil, nil, nil, nil, nil, 17, nil, +22, 28, 21, 29, nil, 13, nil, nil, 15, nil, 11, 36, 24, 33, 14, +34, nil, 35, nil, 23, 26, 25, 27, 12, nil, 30, nil, 31, nil, nil, +nil, 32, nil, nil, nil, nil, nil, 17, nil, 22, 28, 21, 29, nil, 13, +nil, nil, 15, nil, 11, 36, 24, 33, 14, 34, nil, 35, nil, 23, 26, +25, 27, 12, nil, 30, nil, 31, nil, nil, nil, 32, nil, nil, nil, nil, +nil, 17, 115, 22, 28, 21, 29, nil, 13, nil, nil, 15, nil, 11, 36, +24, 33, 14, 34, nil, 35, nil, 23, 26, 25, 27, 12, nil, 30, nil, +31, nil, nil, nil, 32, nil, nil, nil, nil, nil, 17, nil, 22, 28, 21, +29, nil, 13, nil, 121, 15, nil, 11, 36, 24, 33, 14, 34, nil, 35, +nil, 23, 26, 25, 27, 12, nil, 30, nil, 31, nil, nil, nil, 32, nil, +nil, nil, nil, nil, 17, nil, 22, 28, 21, 29, nil, 13, nil, nil, 15, +123, 11, 36, 24, 33, 14, 34, nil, 35, nil, 23, 26, 25, 27, 12, +nil, 30, nil, 31, nil, nil, 126, 32, nil, nil, nil, nil, nil, 17, nil, +22, 28, 21, 29, nil, 13, nil, nil, 15, nil, 11, 36, 24, 33, 14, +34, nil, 35, nil, 23, 26, 25, 27, 12, nil, 30, nil, 31, nil, nil, +nil, 32, nil, nil, 129, nil, nil, 17, nil, 22, 28, 21, 29, nil, 13, +nil, nil, 15, nil, 11, 36, 24, 33, 14, 34, nil, 35, nil, 23, 26, +25, 27, 12, nil, 30, nil, 31, nil, nil, nil, 32, nil, nil, nil, nil, +130, 17, nil, 22, 28, 21, 29, nil, 13, nil, 134, 15, nil, 11, 36, +24, 33, 14, 34, nil, 35, nil, 23, 26, 25, 27, 12, nil, 30, nil, +31, nil, nil, nil, 32, nil, nil, nil, nil, nil, 17, nil, 22, 28, 21, +29, nil, 13, nil, nil, 15, nil, 11, 36, 24, 33, 14, 34, nil, 35, +nil, 23, 26, 25, 27, 12, nil, 30, nil, 31, nil, nil, nil, 32, nil, +nil, nil, nil, nil, 17, nil, 22, 28, 21, 29, nil, 13, nil, nil, 15, +nil, 11, 36, 24, 33, 14, 34, nil, 35, nil, 23, 26, 25, 27, 12, +nil, 30, nil, 31, nil, nil, nil, 32, nil, nil, nil, nil, nil, 17, nil, +22, 28, 21, 29, nil, 13, nil, 142, 15, nil, 11, 36, 24, 33, 14, +34, nil, 35, nil, 23, 26, 25, 27, 12, nil, 30, nil, 31, nil, nil, +nil, 32, nil, nil, nil, nil, nil, 17, nil, 22, 28, 21, 29, nil, 13, +nil, nil, 15, 144, 11, 36, 24, 33, 14, 34, nil, 35, nil, 23, 26, +25, 27, 12, nil, 30, nil, 31, nil, nil, nil, 32, nil, nil, nil, nil, +nil, 17, nil, nil, nil, 21, nil, nil, nil, nil, nil, nil, nil, 11, 36, +22, 28, 14, 29, nil, 13, nil, nil, 15, nil, 136, nil, 24, 33, nil, +34, nil, 35, nil, 23, 26, 25, 27, 12, nil, 30, nil, 31, nil, nil, +nil, 32, nil, nil, nil, nil, nil, 17, nil, nil, nil, 21, nil, nil, nil, +nil, nil, nil, nil, 11, 36, 22, 28, 14, 29, nil, 13, nil, nil, 15, +nil, 136, nil, 24, 33, nil, 34, nil, 35, nil, 23, 26, 25, 27, 12, +nil, 30, nil, 31, nil, nil, nil, 32, nil, nil, nil, nil, nil, 17, nil, +nil, nil, 21, nil, nil, nil, nil, nil, nil, nil, 11, 36, nil, nil, 14] + +racc_action_check = [ +0, 0, 21, 0, 32, 0, 32, 106, 0, 85, 1, 85, 0, 0, 121, +0, 121, 0, 51, 0, 0, 0, 0, 0, 123, 0, 123, 0, 142, 13, +142, 0, 15, 144, 17, 144, 30, 0, 31, 2, 2, 0, 2, 15, 2, +21, 36, 2, 37, 0, 0, 2, 2, 0, 2, 39, 2, 106, 2, 2, +2, 2, 2, 51, 2, 51, 2, 44, 44, 41, 2, 48, 48, 42, 43, +45, 2, 46, 12, 12, 2, 12, 49, 12, 15, 50, 12, 56, 2, 2, +12, 12, 2, 12, 58, 12, 59, 12, 12, 12, 12, 12, 60, 12, 62, +12, 67, 73, 74, 12, 76, 77, 81, 83, 84, 12, 90, 14, 14, 12, +14, 91, 14, 94, 95, 14, 105, 12, 12, 14, 14, 12, 14, 109, 14, +112, 14, 14, 14, 14, 14, 113, 14, 114, 14, 118, 119, 125, 14, 132, +133, 135, 139, 141, 14, nil, nil, nil, 14, nil, 28, 28, 28, 28, nil, +28, 14, 14, 28, nil, 14, nil, 28, 28, nil, 28, nil, 28, nil, 28, +28, 28, 28, 28, nil, 28, nil, 28, nil, nil, nil, 28, nil, nil, nil, +nil, nil, 28, nil, 29, 29, 28, 29, 29, 29, nil, nil, 29, nil, 28, +28, 29, 29, 28, 29, nil, 29, nil, 29, 29, 29, 29, 29, nil, 29, +nil, 29, nil, nil, nil, 29, nil, nil, nil, nil, nil, 29, nil, 33, 33, +29, 33, nil, 33, nil, nil, 33, nil, 29, 29, 33, 33, 29, 33, nil, +33, nil, 33, 33, 33, 33, 33, nil, 33, nil, 33, nil, nil, nil, 33, +nil, nil, nil, nil, nil, 33, nil, 34, 34, 33, 34, nil, 34, nil, nil, +34, nil, 33, 33, 34, 34, 33, 34, nil, 34, nil, 34, 34, 34, 34, +34, nil, 34, nil, 34, nil, nil, nil, 34, nil, nil, nil, nil, nil, 34, +nil, 35, 35, 34, 35, nil, 35, nil, nil, 35, nil, 34, 34, 35, 35, +34, 35, nil, 35, nil, 35, 35, 35, 35, 35, nil, 35, nil, 35, nil, +nil, nil, 35, nil, nil, nil, nil, nil, 35, nil, 40, 40, 35, 40, nil, +40, nil, nil, 40, nil, 35, 35, 40, 40, 35, 40, nil, 40, nil, 40, +40, 40, 40, 40, nil, 40, nil, 40, nil, nil, nil, 40, nil, nil, nil, +nil, nil, 40, nil, 47, 47, 40, 47, nil, 47, nil, nil, 47, nil, 40, +40, 47, 47, 40, 47, nil, 47, nil, 47, 47, 47, 47, 47, nil, 47, +nil, 47, nil, nil, nil, 47, nil, nil, nil, nil, nil, 47, 47, nil, nil, +47, nil, 52, 52, 52, 52, nil, 52, 47, 47, 52, nil, 47, nil, 52, +52, nil, 52, nil, 52, nil, 52, 52, 52, 52, 52, nil, 52, nil, 52, +nil, nil, nil, 52, nil, nil, nil, nil, nil, 52, nil, 54, 54, 52, 54, +54, 54, nil, nil, 54, nil, 52, 52, 54, 54, 52, 54, nil, 54, nil, +54, 54, 54, 54, 54, nil, 54, nil, 54, nil, nil, nil, 54, nil, nil, +nil, nil, nil, 54, nil, 57, 57, 54, 57, nil, 57, nil, nil, 57, nil, +54, 54, 57, 57, 54, 57, nil, 57, nil, 57, 57, 57, 57, 57, nil, +57, nil, 57, nil, nil, 57, 57, nil, nil, nil, nil, nil, 57, nil, 61, +61, 57, 61, nil, 61, nil, nil, 61, nil, 57, 57, 61, 61, 57, 61, +nil, 61, nil, 61, 61, 61, 61, 61, nil, 61, nil, 61, nil, nil, nil, +61, nil, nil, 61, nil, nil, 61, nil, 63, 63, 61, 63, nil, 63, nil, +nil, 63, nil, 61, 61, 63, 63, 61, 63, nil, 63, nil, 63, 63, 63, +63, 63, nil, 63, nil, 63, nil, nil, nil, 63, nil, nil, nil, nil, 63, +63, nil, nil, nil, 63, nil, 64, 64, nil, 64, nil, 64, 63, 63, 64, +nil, 63, nil, 64, 64, 64, 64, nil, 64, nil, 64, 64, 64, 64, 64, +nil, 64, nil, 64, nil, nil, nil, 64, nil, nil, nil, nil, nil, 64, nil, +65, 65, 64, 65, nil, 65, nil, nil, 65, nil, 64, 64, 65, 65, 64, +65, 65, 65, nil, 65, 65, 65, 65, 65, nil, 65, nil, 65, nil, nil, +nil, 65, nil, nil, nil, nil, nil, 65, nil, 66, 66, 65, 66, nil, 66, +nil, nil, 66, nil, 65, 65, 66, 66, 65, 66, nil, 66, 66, 66, 66, +66, 66, 66, nil, 66, nil, 66, nil, nil, nil, 66, nil, nil, nil, nil, +nil, 66, nil, 71, 71, 66, 71, nil, 71, nil, nil, 71, nil, 66, 66, +71, 71, 66, 71, nil, 71, nil, 71, 71, 71, 71, 71, nil, 71, nil, +71, nil, nil, nil, 71, nil, nil, nil, nil, nil, 71, nil, 75, 75, 71, +75, nil, 75, nil, nil, 75, nil, 71, 71, 75, 75, 71, 75, nil, 75, +nil, 75, 75, 75, 75, 75, nil, 75, nil, 75, nil, nil, nil, 75, nil, +nil, nil, nil, nil, 75, nil, 79, 79, 75, 79, nil, 79, nil, nil, 79, +nil, 75, 75, 79, 79, 75, 79, nil, 79, nil, 79, 79, 79, 79, 79, +nil, 79, nil, 79, nil, nil, nil, 79, nil, nil, nil, nil, nil, 79, 79, +86, 86, 79, 86, nil, 86, nil, nil, 86, nil, 79, 79, 86, 86, 79, +86, nil, 86, nil, 86, 86, 86, 86, 86, nil, 86, nil, 86, nil, nil, +nil, 86, nil, nil, nil, nil, nil, 86, nil, 87, 87, 86, 87, nil, 87, +nil, 86, 87, nil, 86, 86, 87, 87, 86, 87, nil, 87, nil, 87, 87, +87, 87, 87, nil, 87, nil, 87, nil, nil, nil, 87, nil, nil, nil, nil, +nil, 87, nil, 92, 92, 87, 92, nil, 92, nil, nil, 92, 87, 87, 87, +92, 92, 87, 92, nil, 92, nil, 92, 92, 92, 92, 92, nil, 92, nil, +92, nil, nil, 92, 92, nil, nil, nil, nil, nil, 92, nil, 97, 97, 92, +97, nil, 97, nil, nil, 97, nil, 92, 92, 97, 97, 92, 97, nil, 97, +nil, 97, 97, 97, 97, 97, nil, 97, nil, 97, nil, nil, nil, 97, nil, +nil, 97, nil, nil, 97, nil, 100, 100, 97, 100, nil, 100, nil, nil, 100, +nil, 97, 97, 100, 100, 97, 100, nil, 100, nil, 100, 100, 100, 100, 100, +nil, 100, nil, 100, nil, nil, nil, 100, nil, nil, nil, nil, 100, 100, nil, +108, 108, 100, 108, nil, 108, nil, 108, 108, nil, 100, 100, 108, 108, 100, +108, nil, 108, nil, 108, 108, 108, 108, 108, nil, 108, nil, 108, nil, nil, +nil, 108, nil, nil, nil, nil, nil, 108, nil, 111, 111, 108, 111, nil, 111, +nil, nil, 111, nil, 108, 108, 111, 111, 108, 111, nil, 111, nil, 111, 111, +111, 111, 111, nil, 111, nil, 111, nil, nil, nil, 111, nil, nil, nil, nil, +nil, 111, nil, 120, 120, 111, 120, nil, 120, nil, nil, 120, nil, 111, 111, +120, 120, 111, 120, nil, 120, nil, 120, 120, 120, 120, 120, nil, 120, nil, +120, nil, nil, nil, 120, nil, nil, nil, nil, nil, 120, nil, 122, 122, 120, +122, nil, 122, nil, 120, 122, nil, 120, 120, 122, 122, 120, 122, nil, 122, +nil, 122, 122, 122, 122, 122, nil, 122, nil, 122, nil, nil, nil, 122, nil, +nil, nil, nil, nil, 122, nil, 134, 134, 122, 134, nil, 134, nil, nil, 134, +122, 122, 122, 134, 134, 122, 134, nil, 134, nil, 134, 134, 134, 134, 134, +nil, 134, nil, 134, nil, nil, nil, 134, nil, nil, nil, nil, nil, 134, nil, +nil, nil, 134, nil, nil, nil, nil, nil, nil, nil, 134, 134, 136, 136, 134, +136, nil, 136, nil, nil, 136, nil, 136, nil, 136, 136, nil, 136, nil, 136, +nil, 136, 136, 136, 136, 136, nil, 136, nil, 136, nil, nil, nil, 136, nil, +nil, nil, nil, nil, 136, nil, nil, nil, 136, nil, nil, nil, nil, nil, nil, +nil, 136, 136, 152, 152, 136, 152, nil, 152, nil, nil, 152, nil, 152, nil, +152, 152, nil, 152, nil, 152, nil, 152, 152, 152, 152, 152, nil, 152, nil, +152, nil, nil, nil, 152, nil, nil, nil, nil, nil, 152, nil, nil, nil, 152, +nil, nil, nil, nil, nil, nil, nil, 152, 152, nil, nil, 152] + +racc_action_pointer = [- +2, 10, 37, nil, nil, nil, nil, nil, nil, nil, nil, nil, 76, 27, 115, +30, nil, - +7, nil, nil, nil, 0, nil, nil, nil, nil, nil, nil, 158, 197, 5, 7, +- +31, 236, 275, 314, 44, 48, nil, 29, 353, 61, 64, 18, 55, 73, 23, +392, 30, 38, 40, 16, 435, nil, 474, nil, 59, 513, 64, 59, 68, 552, +67, 591, 634, 673, 712, 94, nil, nil, nil, 751, nil, 105, 97, 790, 98, +109, nil, 829, nil, 71, nil, 69, 68, - +38, 868, 907, nil, nil, 88, 90, 946, nil, 93, 90, nil, 985, nil, nil, +1024, nil, nil, nil, nil, 73, 5, nil, 1063, 121, nil, 1102, 124, 139, 131, +nil, nil, nil, 100, 100, 1141, -33, 1180, - +23, nil, 116, nil, nil, nil, nil, nil, nil, 137, 138, 1219, 140, 1270, nil, +nil, 141, nil, 108, -19, nil, -14, nil, nil, nil, nil, nil, nil, nil, 1321, nil, nil, nil, nil, nil] + +racc_action_default = [-83, -83, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -19, -83, -19, -83, -18, -23, -37, -39, -40, -43, -51, -52, -53, -54, -55, -56, -83, -83, -83, -83, -73, -83, -83, -83, -83, -83, -38, -83, -20, -83, -26, -83, -30, -83, -83, -83, -23, -83, -43, -46, -83, -57, -83, -58, -63, -83, -63, -73, -83, -83, -73, -83, -83, -83, -83, -80, 158, -11, -12, -83, -13, -83, -83, -83, -32, -83, -21, -83, -24, -23, -41, -83, -83, -46, -83, -83, -59, -60, -83, -83, -83, -66, -83, -83, -69, -83, -70, -72, -83, -74, -76, -77, -78, -83, -83, -27, -28, -34, -15, -31, -83, -83, -30, -22, -25, -42, -43, -83, -83, -46, -83, -46, -61, -65, -67, -62, -68, -71, -75, -79, -80, -80, -83, -83, -34, -16, -33, -83, -44, -43, -46, -47, -46, -49, -64, -81, -82, -29, -14, -35, -34, -17, -45, -48, -50, -36] + +racc_goto_table = [ +38, 84, 74, 105, 49, 39, 90, 43, 94, 60, 135, 1, 133, 2, 47, +41, 107, 112, 59, 56, 58, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, 83, nil, 119, 95, 151, 38, 99, nil, 52, 54, nil, nil, +80, 64, 65, 66, nil, 38, nil, 38, 157, nil, nil, nil, nil, nil, nil, +79, nil, 38, 38, 38, nil, nil, nil, 147, 148, 92, 143, 139, 145, 97, +146, 100, 38, 116, 149, 125, nil, nil, nil, 108, nil, nil, nil, 111, nil, +38, nil, 155, nil, 156, 38, nil, nil, 38, 120, 122, 140, nil, nil, nil, +nil, 38, nil, nil, 38, nil, nil, nil, nil, nil, nil, nil, nil, 38, nil, +38, nil, nil, nil, 154, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 108, nil, 152, +38] + +racc_goto_check = [ +3, 23, 15, 30, 22, 12, 25, 12, 25, 28, 14, 1, 11, 2, 18, +13, 19, 16, 27, 24, 24, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, 22, nil, 23, 28, 14, 3, 28, nil, 2, 2, nil, nil, +18, 2, 2, 2, nil, 3, nil, 3, 14, nil, nil, nil, nil, nil, nil, +2, nil, 3, 3, 3, nil, nil, nil, 30, 30, 2, 23, 15, 23, 2, +25, 2, 3, 18, 19, 24, nil, nil, nil, 2, nil, nil, nil, 2, nil, +3, nil, 23, nil, 23, 3, nil, nil, 3, 2, 2, 22, nil, nil, nil, +nil, 3, nil, nil, 3, nil, nil, nil, nil, nil, nil, nil, nil, 3, nil, +3, nil, nil, nil, 22, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 2, nil, 2, +3] + +racc_goto_pointer = [nil, 11, 13, -2, nil, nil, nil, nil, nil, nil, nil, -94, -7, 2, -99, -42, -59, nil, -3, -55, nil, nil, -17, -50, -11, -50, nil, -14, -23, nil, -64] + +racc_goto_default = [ +nil, nil, 40, 18, 3, 4, 5, 6, 7, 8, 9, 10, nil, nil, nil, +nil, nil, 16, nil, nil, 19, 20, nil, nil, nil, nil, 91, nil, nil, 62, +nil] + +racc_reduce_table = [ + 0, 0, :racc_error, + 1, 58, :_reduce_1, + 1, 60, :_reduce_2, + 1, 60, :_reduce_3, + 1, 60, :_reduce_4, + 1, 60, :_reduce_5, + 1, 60, :_reduce_6, + 1, 60, :_reduce_7, + 1, 60, :_reduce_8, + 1, 60, :_reduce_9, + 1, 60, :_reduce_10, + 3, 60, :_reduce_11, + 3, 60, :_reduce_12, + 3, 60, :_reduce_13, + 6, 60, :_reduce_14, + 4, 60, :_reduce_15, + 5, 60, :_reduce_16, + 6, 60, :_reduce_17, + 1, 60, :_reduce_none, + 0, 69, :_reduce_19, + 1, 69, :_reduce_20, + 3, 67, :_reduce_21, + 4, 67, :_reduce_22, + 0, 75, :_reduce_23, + 2, 75, :_reduce_24, + 3, 75, :_reduce_25, + 1, 70, :_reduce_26, + 3, 70, :_reduce_27, + 1, 76, :_reduce_28, + 3, 76, :_reduce_29, + 0, 72, :_reduce_30, + 2, 72, :_reduce_31, + 0, 73, :_reduce_32, + 2, 73, :_reduce_33, + 0, 71, :_reduce_34, + 2, 71, :_reduce_35, + 3, 71, :_reduce_36, + 1, 59, :_reduce_37, + 2, 59, :_reduce_38, + 1, 61, :_reduce_39, + 1, 61, :_reduce_40, + 3, 74, :_reduce_41, + 4, 74, :_reduce_42, + 0, 79, :_reduce_43, + 4, 79, :_reduce_44, + 5, 79, :_reduce_45, + 0, 80, :_reduce_46, + 3, 80, :_reduce_47, + 4, 80, :_reduce_48, + 3, 80, :_reduce_49, + 4, 80, :_reduce_50, + 1, 77, :_reduce_51, + 1, 77, :_reduce_52, + 1, 77, :_reduce_53, + 1, 77, :_reduce_54, + 1, 77, :_reduce_55, + 1, 77, :_reduce_56, + 2, 78, :_reduce_57, + 2, 78, :_reduce_58, + 3, 78, :_reduce_59, + 3, 78, :_reduce_60, + 4, 62, :_reduce_61, + 4, 63, :_reduce_62, + 0, 83, :_reduce_63, + 3, 82, :_reduce_64, + 0, 82, :_reduce_65, + 2, 81, :_reduce_66, + 3, 81, :_reduce_67, + 4, 64, :_reduce_68, + 3, 64, :_reduce_69, + 2, 84, :_reduce_70, + 3, 84, :_reduce_71, + 2, 85, :_reduce_72, + 0, 85, :_reduce_73, + 2, 86, :_reduce_74, + 3, 86, :_reduce_75, + 3, 65, :_reduce_76, + 3, 65, :_reduce_77, + 3, 66, :_reduce_78, + 4, 68, :_reduce_79, + 0, 87, :_reduce_80, + 3, 87, :_reduce_81, + 3, 87, :_reduce_82 ] + +racc_reduce_n = 83 + +racc_shift_n = 158 + +racc_token_table = { + false => 0, + :error => 1, + :TEXT => 2, + :BOLD_START => 3, + :BOLD_END => 4, + :ITALIC_START => 5, + :ITALIC_END => 6, + :LINK_START => 7, + :LINK_END => 8, + :LINKSEP => 9, + :INTLINK_START => 10, + :INTLINK_END => 11, + :INTLINKSEP => 12, + :RESOURCESEP => 13, + :CHAR_ENT => 14, + :PRE_START => 15, + :PRE_END => 16, + :PREINDENT_START => 17, + :PREINDENT_END => 18, + :SECTION_START => 19, + :SECTION_END => 20, + :HLINE => 21, + :SIGNATURE_NAME => 22, + :SIGNATURE_DATE => 23, + :SIGNATURE_FULL => 24, + :PARA_START => 25, + :PARA_END => 26, + :UL_START => 27, + :UL_END => 28, + :OL_START => 29, + :OL_END => 30, + :LI_START => 31, + :LI_END => 32, + :DL_START => 33, + :DL_END => 34, + :DT_START => 35, + :DT_END => 36, + :DD_START => 37, + :DD_END => 38, + :TAG_START => 39, + :TAG_END => 40, + :ATTR_NAME => 41, + :ATTR_VALUE => 42, + :TABLE_START => 43, + :TABLE_END => 44, + :ROW_START => 45, + :ROW_END => 46, + :HEAD_START => 47, + :HEAD_END => 48, + :CELL_START => 49, + :CELL_END => 50, + :KEYWORD => 51, + :TEMPLATE_START => 52, + :TEMPLATE_END => 53, + :CATEGORY => 54, + :PASTE_START => 55, + :PASTE_END => 56 } + +racc_nt_base = 57 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ + "$end", + "error", + "TEXT", + "BOLD_START", + "BOLD_END", + "ITALIC_START", + "ITALIC_END", + "LINK_START", + "LINK_END", + "LINKSEP", + "INTLINK_START", + "INTLINK_END", + "INTLINKSEP", + "RESOURCESEP", + "CHAR_ENT", + "PRE_START", + "PRE_END", + "PREINDENT_START", + "PREINDENT_END", + "SECTION_START", + "SECTION_END", + "HLINE", + "SIGNATURE_NAME", + "SIGNATURE_DATE", + "SIGNATURE_FULL", + "PARA_START", + "PARA_END", + "UL_START", + "UL_END", + "OL_START", + "OL_END", + "LI_START", + "LI_END", + "DL_START", + "DL_END", + "DT_START", + "DT_END", + "DD_START", + "DD_END", + "TAG_START", + "TAG_END", + "ATTR_NAME", + "ATTR_VALUE", + "TABLE_START", + "TABLE_END", + "ROW_START", + "ROW_END", + "HEAD_START", + "HEAD_END", + "CELL_START", + "CELL_END", + "KEYWORD", + "TEMPLATE_START", + "TEMPLATE_END", + "CATEGORY", + "PASTE_START", + "PASTE_END", + "$start", + "wiki", + "repeated_contents", + "contents", + "text", + "bulleted_list", + "numbered_list", + "dictionary_list", + "preformatted", + "section", + "tag", + "template", + "para_contents", + "link_contents", + "reslink_repeated_contents", + "intlink_repeated_contents", + "cat_sort_contents", + "table", + "tag_attributes", + "link_repeated_contents", + "element", + "formatted_element", + "table_contents", + "row_contents", + "list_item", + "list_contents", + "@action1", + "dictionary_term", + "dictionary_contents", + "dictionary_definition", + "template_parameters" ] + +Racc_debug_parser = false + +##### State transition tables end ##### + +# reduce 0 omitted + +module_eval(<<'.,.,', 'mediacloth.y', 47) + def _reduce_1(val, _values, result) + @nodes.push WikiAST.new(0, @wiki_ast_length) + #@nodes.last.children.insert(0, val[0]) + #puts val[0] + @nodes.last.children += val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 57) + def _reduce_2(val, _values, result) + result = val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 61) + def _reduce_3(val, _values, result) + result = val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 65) + def _reduce_4(val, _values, result) + result = val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 69) + def _reduce_5(val, _values, result) + list = ListAST.new(@ast_index, @ast_length) + list.list_type = :Dictionary + list.children = val[0] + result = list + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 76) + def _reduce_6(val, _values, result) + result = val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 80) + def _reduce_7(val, _values, result) + result = val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 84) + def _reduce_8(val, _values, result) + result = val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 88) + def _reduce_9(val, _values, result) + result = val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 92) + def _reduce_10(val, _values, result) + k = KeywordAST.new(@ast_index, @ast_length) + k.text = val[0] + result = k + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 98) + def _reduce_11(val, _values, result) + p = ParagraphAST.new(@ast_index, @ast_length) + p.children = val[1] + result = p + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 104) + def _reduce_12(val, _values, result) + l = LinkAST.new(@ast_index, @ast_length) + l.link_type = val[0] + l.url = val[1][0] + l.children += val[1][1..-1] if val[1].length > 1 + result = l + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 112) + def _reduce_13(val, _values, result) + p = PasteAST.new(@ast_index, @ast_length) + p.children = val[1] + result = p + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 118) + def _reduce_14(val, _values, result) + l = ResourceLinkAST.new(@ast_index, @ast_length) + l.prefix = val[1] + l.locator = val[3] + l.children = val[4] unless val[4].nil? or val[4].empty? + result = l + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 126) + def _reduce_15(val, _values, result) + l = InternalLinkAST.new(@ast_index, @ast_length) + l.locator = val[1] + l.children = val[2] unless val[2].nil? or val[2].empty? + result = l + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 133) + def _reduce_16(val, _values, result) + l = CategoryAST.new(@ast_index, @ast_length) + l.locator = val[2] + l.sort_as = val[3] + result = l + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 140) + def _reduce_17(val, _values, result) + l = CategoryLinkAST.new(@ast_index, @ast_length) + l.locator = val[3] + l.children = val[4] unless val[4].nil? or val[4].empty? + result = l + + result + end +.,., + +# reduce 18 omitted + +module_eval(<<'.,.,', 'mediacloth.y', 150) + def _reduce_19(val, _values, result) + result = nil + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 154) + def _reduce_20(val, _values, result) + result = val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 161) + def _reduce_21(val, _values, result) + if val[0] != val[2] + raise Racc::ParseError.new("XHTML end tag #{val[2]} does not match start tag #{val[0]}") + end + elem = ElementAST.new(@ast_index, @ast_length) + elem.name = val[0] + elem.attributes = val[1] + result = elem + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 171) + def _reduce_22(val, _values, result) + if val[0] != val[3] + raise Racc::ParseError.new("XHTML end tag #{val[3]} does not match start tag #{val[0]}") + end + elem = ElementAST.new(@ast_index, @ast_length) + elem.name = val[0] + elem.attributes = val[1] + elem.children += val[2] + result = elem + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 184) + def _reduce_23(val, _values, result) + result = nil + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 188) + def _reduce_24(val, _values, result) + attr_map = val[2] ? val[2] : {} + attr_map[val[0]] = true + result = attr_map + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 194) + def _reduce_25(val, _values, result) + attr_map = val[2] ? val[2] : {} + attr_map[val[0]] = val[1] + result = attr_map + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 204) + def _reduce_26(val, _values, result) + result = val + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 208) + def _reduce_27(val, _values, result) + result = [val[0]] + result += val[2] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 217) + def _reduce_28(val, _values, result) + result = val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 221) + def _reduce_29(val, _values, result) + result = val[0] + result += val[2] if val[2] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 229) + def _reduce_30(val, _values, result) + result = nil + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 233) + def _reduce_31(val, _values, result) + result = val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 239) + def _reduce_32(val, _values, result) + result = nil + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 243) + def _reduce_33(val, _values, result) + result = val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 249) + def _reduce_34(val, _values, result) + result = nil + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 253) + def _reduce_35(val, _values, result) + result = val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 257) + def _reduce_36(val, _values, result) + i = InternalLinkItemAST.new(@ast_index, @ast_length) + i.children = val[1] + result = [i] + result += val[2] if val[2] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 266) + def _reduce_37(val, _values, result) + result = [] + result << val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 271) + def _reduce_38(val, _values, result) + result = [] + result += val[0] + result << val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 279) + def _reduce_39(val, _values, result) + p = TextAST.new(@ast_index, @ast_length) + p.formatting = val[0][0] + p.contents = val[0][1] + result = p + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 286) + def _reduce_40(val, _values, result) + result = val[0] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 293) + def _reduce_41(val, _values, result) + table = TableAST.new(@ast_index, @ast_length) + table.children = val[1] unless val[1].nil? or val[1].empty? + result = table + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 299) + def _reduce_42(val, _values, result) + table = TableAST.new(@ast_index, @ast_length) + table.options = val[1] + table.children = val[2] unless val[2].nil? or val[2].empty? + result = table + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 307) + def _reduce_43(val, _values, result) + result = nil + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 311) + def _reduce_44(val, _values, result) + row = TableRowAST.new(@ast_index, @ast_length) + row.children = val[1] unless val[1].nil? or val[1].empty? + result = [row] + result += val[3] unless val[3].nil? or val[3].empty? + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 318) + def _reduce_45(val, _values, result) + row = TableRowAST.new(@ast_index, @ast_length) + row.children = val[2] unless val[2].nil? or val[2].empty? + row.options = val[1] + result = [row] + result += val[4] unless val[4].nil? or val[4].empty? + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 327) + def _reduce_46(val, _values, result) + result = nil + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 331) + def _reduce_47(val, _values, result) + cell = TableCellAST.new(@ast_index, @ast_length) + cell.type = :head + result = [cell] + result += val[2] unless val[2].nil? or val[2].empty? + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 338) + def _reduce_48(val, _values, result) + cell = TableCellAST.new(@ast_index, @ast_length) + cell.children = val[1] unless val[1].nil? or val[1].empty? + cell.type = :head + result = [cell] + result += val[3] unless val[3].nil? or val[3].empty? + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 346) + def _reduce_49(val, _values, result) + cell = TableCellAST.new(@ast_index, @ast_length) + cell.type = :body + result = [cell] + result += val[2] unless val[2].nil? or val[2].empty? + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 353) + def _reduce_50(val, _values, result) + if val[2] == 'attributes' + result = [] + else + cell = TableCellAST.new(@ast_index, @ast_length) + cell.children = val[1] unless val[1].nil? or val[1].empty? + cell.type = :body + result = [cell] + end + result += val[3] unless val[3].nil? or val[3].empty? + if val[2] == 'attributes' and val[3] and val[3].first.class == TableCellAST + val[3].first.attributes = val[1] + end + result + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 371) + def _reduce_51(val, _values, result) + return [:None, val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 373) + def _reduce_52(val, _values, result) + return [:HLine, val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 375) + def _reduce_53(val, _values, result) + return [:CharacterEntity, val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 377) + def _reduce_54(val, _values, result) + return [:SignatureDate, val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 379) + def _reduce_55(val, _values, result) + return [:SignatureName, val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 381) + def _reduce_56(val, _values, result) + return [:SignatureFull, val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 387) + def _reduce_57(val, _values, result) + result = FormattedAST.new(@ast_index, @ast_length) + result.formatting = :Bold + result + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 393) + def _reduce_58(val, _values, result) + result = FormattedAST.new(@ast_index, @ast_length) + result.formatting = :Italic + result + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 399) + def _reduce_59(val, _values, result) + p = FormattedAST.new(@ast_index, @ast_length) + p.formatting = :Bold + p.children += val[1] + result = p + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 406) + def _reduce_60(val, _values, result) + p = FormattedAST.new(@ast_index, @ast_length) + p.formatting = :Italic + p.children += val[1] + result = p + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 415) + def _reduce_61(val, _values, result) + list = ListAST.new(@ast_index, @ast_length) + list.list_type = :Bulleted + list.children << val[1] + list.children += val[2] + result = list + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 425) + def _reduce_62(val, _values, result) + list = ListAST.new(@ast_index, @ast_length) + list.list_type = :Numbered + list.children << val[1] + list.children += val[2] + result = list + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 434) + def _reduce_63(val, _values, result) + result = [] + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 437) + def _reduce_64(val, _values, result) + result << val[1] + result += val[2] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 441) + def _reduce_65(val, _values, result) + result = [] + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 447) + def _reduce_66(val, _values, result) + result = ListItemAST.new(@ast_index, @ast_length) + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 451) + def _reduce_67(val, _values, result) + li = ListItemAST.new(@ast_index, @ast_length) + li.children += val[1] + result = li + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 460) + def _reduce_68(val, _values, result) + result = [val[1]] + result += val[2] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 465) + def _reduce_69(val, _values, result) + result = val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 472) + def _reduce_70(val, _values, result) + result = ListTermAST.new(@ast_index, @ast_length) + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 476) + def _reduce_71(val, _values, result) + term = ListTermAST.new(@ast_index, @ast_length) + term.children += val[1] + result = term + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 484) + def _reduce_72(val, _values, result) + result = [val[0]] + result += val[1] if val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 489) + def _reduce_73(val, _values, result) + result = [] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 495) + def _reduce_74(val, _values, result) + result = ListDefinitionAST.new(@ast_index, @ast_length) + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 499) + def _reduce_75(val, _values, result) + term = ListDefinitionAST.new(@ast_index, @ast_length) + term.children += val[1] + result = term + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 506) + def _reduce_76(val, _values, result) + p = PreformattedAST.new(@ast_index, @ast_length) + p.children += val[1] + result = p + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 512) + def _reduce_77(val, _values, result) + p = PreformattedAST.new(@ast_index, @ast_length) + p.indented = true + p.children += val[1] + result = p + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 520) + def _reduce_78(val, _values, result) + result = [val[1], val[0].length] + s = SectionAST.new(@ast_index, @ast_length) + s.children = val[1] + s.level = val[0].length + result = s + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 530) + def _reduce_79(val, _values, result) + t = TemplateAST.new(@ast_index, @ast_length) + t.template_name = val[1] + t.children = val[2] unless val[2].nil? or val[2].empty? + result = t + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 539) + def _reduce_80(val, _values, result) + result = nil + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 543) + def _reduce_81(val, _values, result) + p = TemplateParameterAST.new(@ast_index, @ast_length) + p.parameter_value = val[1] + result = [p] + result += val[2] if val[2] + + result + end +.,., + +module_eval(<<'.,.,', 'mediacloth.y', 550) + def _reduce_82(val, _values, result) + p = TemplateParameterAST.new(@ast_index, @ast_length) + p.children << val[1] + result = [p] + result += val[2] if val[2] + + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] +end + +end # class MediaWikiParser diff --git a/test/regress/mof.out b/test/regress/mof.out new file mode 100644 index 00000000..a3366abc --- /dev/null +++ b/test/regress/mof.out @@ -0,0 +1,211 @@ +Parsing grammar file... +Generating and resolving LALR states... +Creating parser file... + +Warning: Useless terminal "*" does not appear on the right side of any rule + +Warning: Useless terminal "/" does not appear on the right side of any rule + +Warning: Useless terminal "+" does not appear on the right side of any rule + +Warning: Useless terminal "-" does not appear on the right side of any rule + +Warning: This rule will never be used due to low precedence: +mof.y:429: namespace_opt + : /* empty */ + +When the next token is IDENTIFIER, it is overridden by this higher-precedence rule: +mof.y:434: namespaceHandle + : IDENTIFIER + +Warning: Shift/reduce conflict on QUALIFIER, at the beginning of the parse. + +The following rule directs me to shift: +mof.y:469: qualifierDeclaration +... +mof.y:471:  : QUALIFIER qualifierName qualifierType scope defaultFlavor_opt ";" + { result = CIM::QualifierDeclaration.new( val[1], val[2][0], val[2][1], val[3], val[4]) } +The following rule directs me to reduce: +mof.y:40: mofSpecification +... +mof.y:42:  { result = Hash.new } + +After shifting QUALIFIER, one path to a successful parse would be: +IDENTIFIER (reduce to qualifierName) ":" DT_UINT8 (reduce to dataType) (reduce to array_opt) (reduce to defaultValue_opt) (reduce to qualifierType) "," SCOPE "(" SCHEMA (reduce to metaElement) (reduce to metaElements) ")" (reduce to scope) (reduce to defaultFlavor_opt) ";" (reduce to qualifierDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +After reducing to mofSpecification, one path to a successful parse would be: +QUALIFIER IDENTIFIER (reduce to qualifierName) ":" DT_UINT8 (reduce to dataType) (reduce to array_opt) (reduce to defaultValue_opt) (reduce to qualifierType) "," SCOPE "(" SCHEMA (reduce to metaElement) (reduce to metaElements) ")" (reduce to scope) (reduce to defaultFlavor_opt) ";" (reduce to qualifierDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +Warning: Shift/reduce conflict on "#", at the beginning of the parse. + +The following rules direct me to shift: +mof.y:70: compilerDirective + : "#" PRAGMA INCLUDE pragmaParameters_opt + { raise MOF::Helper::Error.new(@name,@lineno,@line,"Missing filename after '#pragma include'") unless val[3] + open val[3], :pragma + } +mof.y:70: compilerDirective +... +mof.y:75:  | "#" PRAGMA pragmaName pragmaParameters_opt +mof.y:70: compilerDirective +... +mof.y:76:  | "#" INCLUDE pragmaParameters_opt + { raise StyleError.new(@name,@lineno,@line,"Use '#pragma include' instead of '#include'") unless @style == :wmi + raise MOF::Helper::Error.new(@name,@lineno,@line,"Missing filename after '#include'") unless val[2] + open val[2], :pragma + } +The following rule directs me to reduce: +mof.y:40: mofSpecification +... +mof.y:42:  { result = Hash.new } + +After shifting "#", one path to a successful parse would be: +INCLUDE (reduce to pragmaParameters_opt) (reduce to compilerDirective) (reduce to mofProduction) (reduce to mofSpecification) + +After reducing to mofSpecification, one path to a successful parse would be: +"#" INCLUDE (reduce to pragmaParameters_opt) (reduce to compilerDirective) (reduce to mofProduction) (reduce to mofSpecification) + +Warning: Shift/reduce conflict on "[", at the beginning of the parse. + +The following rule directs me to shift: +mof.y:140: qualifierList + : "[" qualifier qualifiers "]" + { result = val[2] + result.unshift val[1] if val[1] } +The following rule directs me to reduce: +mof.y:40: mofSpecification +... +mof.y:42:  { result = Hash.new } + +After shifting "[", one path to a successful parse would be: +IDENTIFIER (reduce to qualifierName) (reduce to qualifierParameter_opt) (reduce to flavor_opt) (reduce to qualifier) (reduce to qualifiers) "]" (reduce to qualifierList) (reduce to qualifierList_opt) CLASS IDENTIFIER (reduce to className) (reduce to alias_opt) (reduce to superClass_opt) "{" (reduce to classFeatures) "}" ";" (reduce to classDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +After reducing to mofSpecification, one path to a successful parse would be: +"[" IDENTIFIER (reduce to qualifierName) (reduce to qualifierParameter_opt) (reduce to flavor_opt) (reduce to qualifier) (reduce to qualifiers) "]" (reduce to qualifierList) (reduce to qualifierList_opt) CLASS IDENTIFIER (reduce to className) (reduce to alias_opt) (reduce to superClass_opt) "{" (reduce to classFeatures) "}" ";" (reduce to classDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +Warning: Reduce/reduce conflict on CLASS, at the beginning of the parse. + +It is possible to reduce by either of these rules: +mof.y:40: mofSpecification +... +mof.y:42:  { result = Hash.new } +mof.y:134: qualifierList_opt + : /* empty */ + +After reducing to mofSpecification, one path to a successful parse would be: +CLASS IDENTIFIER (reduce to className) (reduce to alias_opt) (reduce to superClass_opt) "{" (reduce to classFeatures) "}" ";" (reduce to classDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +After reducing to qualifierList_opt, one path to a successful parse would be: +CLASS IDENTIFIER (reduce to className) (reduce to alias_opt) (reduce to superClass_opt) "{" (reduce to classFeatures) "}" ";" (reduce to classDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +Warning: Reduce/reduce conflict on INSTANCE, at the beginning of the parse. + +It is possible to reduce by either of these rules: +mof.y:40: mofSpecification +... +mof.y:42:  { result = Hash.new } +mof.y:134: qualifierList_opt + : /* empty */ + +After reducing to mofSpecification, one path to a successful parse would be: +INSTANCE OF IDENTIFIER (reduce to className) (reduce to alias_opt) "{" (reduce to qualifierList_opt) IDENTIFIER (reduce to propertyName) (reduce to keyname) ";" (reduce to valueInitializer) (reduce to valueInitializers) "}" (reduce to instance) ";" (reduce to instanceDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +After reducing to qualifierList_opt, one path to a successful parse would be: +INSTANCE OF IDENTIFIER (reduce to className) (reduce to alias_opt) "{" (reduce to qualifierList_opt) IDENTIFIER (reduce to propertyName) (reduce to keyname) ";" (reduce to valueInitializer) (reduce to valueInitializers) "}" (reduce to instance) ";" (reduce to instanceDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +Warning: Shift/reduce conflict on IDENTIFIER, after the following input: +QUALIFIER qualifierName ":" dataType array_opt "=" + +The following rule directs me to shift: +mof.y:434: namespaceHandle + : IDENTIFIER +The following rule directs me to reduce: +mof.y:429: namespace_opt + : /* empty */ + +After shifting IDENTIFIER, one path to a successful parse would be: +(reduce to namespaceHandle) ":" (reduce to namespace_opt) IDENTIFIER (reduce to className) "." IDENTIFIER (reduce to propertyName) (reduce to keyname) "=" binaryValue (reduce to integerValue) (reduce to constantValue) (reduce to initializer) (reduce to keyValuePair) (reduce to keyValuePairs) (reduce to keyValuePairList) (reduce to modelPath) (reduce to objectHandle) (reduce to referenceInitializer) (reduce to initializer) (reduce to defaultValue) (reduce to defaultValue_opt) (reduce to qualifierType) "," SCOPE "(" SCHEMA (reduce to metaElement) (reduce to metaElements) ")" (reduce to scope) (reduce to defaultFlavor_opt) ";" (reduce to qualifierDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +After reducing to namespace_opt, one path to a successful parse would be: +IDENTIFIER (reduce to className) "." IDENTIFIER (reduce to propertyName) (reduce to keyname) "=" binaryValue (reduce to integerValue) (reduce to constantValue) (reduce to initializer) (reduce to keyValuePair) (reduce to keyValuePairs) (reduce to keyValuePairList) (reduce to modelPath) (reduce to objectHandle) (reduce to referenceInitializer) (reduce to initializer) (reduce to defaultValue) (reduce to defaultValue_opt) (reduce to qualifierType) "," SCOPE "(" SCHEMA (reduce to metaElement) (reduce to metaElements) ")" (reduce to scope) (reduce to defaultFlavor_opt) ";" (reduce to qualifierDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +Warning: Reduce/reduce conflict on ";", after the following input: +qualifierList_opt INSTANCE OF className alias_opt "{" qualifierList_opt IDENTIFIER + +It is possible to reduce by either of these rules: +mof.y:259: propertyName + : IDENTIFIER +mof.y:267: referenceName + : IDENTIFIER + +After reducing to propertyName, one path to a successful parse would be: +";" (reduce to valueInitializer) (reduce to valueInitializers) "}" (reduce to instance) ";" (reduce to instanceDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +After reducing to referenceName, one path to a successful parse would be: +";" (reduce to valueInitializer) (reduce to valueInitializers) "}" (reduce to instance) ";" (reduce to instanceDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +Warning: Reduce/reduce conflict on "=", after the following input: +qualifierList_opt INSTANCE OF className alias_opt "{" qualifierList_opt IDENTIFIER + +It is possible to reduce by either of these rules: +mof.y:259: propertyName + : IDENTIFIER +mof.y:267: referenceName + : IDENTIFIER + +After reducing to propertyName, one path to a successful parse would be: +"=" binaryValue (reduce to integerValue) (reduce to constantValue) (reduce to initializer) ";" (reduce to valueInitializer) (reduce to valueInitializers) "}" (reduce to instance) ";" (reduce to instanceDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +After reducing to referenceName, one path to a successful parse would be: +"=" binaryValue (reduce to integerValue) (reduce to constantValue) (reduce to initializer) ";" (reduce to valueInitializer) (reduce to valueInitializers) "}" (reduce to instance) ";" (reduce to instanceDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +Warning: Shift/reduce conflict on IDENTIFIER, after the following input: +qualifierList_opt INSTANCE OF className alias_opt "{" qualifierList_opt keyname "=" + +The following rule directs me to shift: +mof.y:434: namespaceHandle + : IDENTIFIER +The following rule directs me to reduce: +mof.y:429: namespace_opt + : /* empty */ + +After shifting IDENTIFIER, one path to a successful parse would be: +(reduce to namespaceHandle) ":" (reduce to namespace_opt) IDENTIFIER (reduce to className) "." IDENTIFIER (reduce to propertyName) (reduce to keyname) "=" binaryValue (reduce to integerValue) (reduce to constantValue) (reduce to initializer) (reduce to keyValuePair) (reduce to keyValuePairs) (reduce to keyValuePairList) (reduce to modelPath) (reduce to objectHandle) (reduce to referenceInitializer) (reduce to initializer) ";" (reduce to valueInitializer) (reduce to valueInitializers) "}" (reduce to instance) ";" (reduce to instanceDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +After reducing to namespace_opt, one path to a successful parse would be: +IDENTIFIER (reduce to className) "." IDENTIFIER (reduce to propertyName) (reduce to keyname) "=" binaryValue (reduce to integerValue) (reduce to constantValue) (reduce to initializer) (reduce to keyValuePair) (reduce to keyValuePairs) (reduce to keyValuePairList) (reduce to modelPath) (reduce to objectHandle) (reduce to referenceInitializer) (reduce to initializer) ";" (reduce to valueInitializer) (reduce to valueInitializers) "}" (reduce to instance) ";" (reduce to instanceDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +Warning: Shift/reduce conflict on ",", after the following input: +QUALIFIER qualifierName ":" dataType array_opt "=" namespace_opt className "." keyValuePair keyValuePairs + +The following rule directs me to shift: +mof.y:451: keyValuePairs +... +mof.y:453:  | keyValuePairs "," keyValuePair +The following rule directs me to reduce: +mof.y:447: keyValuePairList + : keyValuePair keyValuePairs + +After shifting ",", one path to a successful parse would be: +IDENTIFIER (reduce to propertyName) (reduce to keyname) "=" binaryValue (reduce to integerValue) (reduce to constantValue) (reduce to initializer) (reduce to keyValuePair) (reduce to keyValuePairs) (reduce to keyValuePairList) (reduce to modelPath) (reduce to objectHandle) (reduce to referenceInitializer) (reduce to initializer) (reduce to defaultValue) (reduce to defaultValue_opt) (reduce to qualifierType) "," SCOPE "(" SCHEMA (reduce to metaElement) (reduce to metaElements) ")" (reduce to scope) (reduce to defaultFlavor_opt) ";" (reduce to qualifierDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +After reducing to keyValuePairList, one path to a successful parse would be: +"," SCOPE "(" SCHEMA (reduce to metaElement) (reduce to metaElements) ")" (reduce to scope) (reduce to defaultFlavor_opt) ";" (reduce to qualifierDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +Warning: Shift/reduce conflict on IDENTIFIER, after the following input: +QUALIFIER qualifierName ":" dataType array_opt "=" namespace_opt className "." keyname "=" + +The following rule directs me to shift: +mof.y:434: namespaceHandle + : IDENTIFIER +The following rule directs me to reduce: +mof.y:429: namespace_opt + : /* empty */ + +After shifting IDENTIFIER, one path to a successful parse would be: +(reduce to namespaceHandle) ":" (reduce to namespace_opt) IDENTIFIER (reduce to className) "." IDENTIFIER (reduce to propertyName) (reduce to keyname) "=" binaryValue (reduce to integerValue) (reduce to constantValue) (reduce to initializer) (reduce to keyValuePair) (reduce to keyValuePairs) (reduce to keyValuePairList) (reduce to modelPath) (reduce to objectHandle) (reduce to referenceInitializer) (reduce to initializer) (reduce to keyValuePair) (reduce to keyValuePairs) (reduce to keyValuePairList) (reduce to modelPath) (reduce to objectHandle) (reduce to referenceInitializer) (reduce to initializer) (reduce to defaultValue) (reduce to defaultValue_opt) (reduce to qualifierType) "," SCOPE "(" SCHEMA (reduce to metaElement) (reduce to metaElements) ")" (reduce to scope) (reduce to defaultFlavor_opt) ";" (reduce to qualifierDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +After reducing to namespace_opt, one path to a successful parse would be: +IDENTIFIER (reduce to className) "." IDENTIFIER (reduce to propertyName) (reduce to keyname) "=" binaryValue (reduce to integerValue) (reduce to constantValue) (reduce to initializer) (reduce to keyValuePair) (reduce to keyValuePairs) (reduce to keyValuePairList) (reduce to modelPath) (reduce to objectHandle) (reduce to referenceInitializer) (reduce to initializer) (reduce to keyValuePair) (reduce to keyValuePairs) (reduce to keyValuePairList) (reduce to modelPath) (reduce to objectHandle) (reduce to referenceInitializer) (reduce to initializer) (reduce to defaultValue) (reduce to defaultValue_opt) (reduce to qualifierType) "," SCOPE "(" SCHEMA (reduce to metaElement) (reduce to metaElements) ")" (reduce to scope) (reduce to defaultFlavor_opt) ";" (reduce to qualifierDeclaration) (reduce to mofProduction) (reduce to mofSpecification) + +4 useless terminals, 1 useless rule, 7 shift/reduce conflicts, 4 reduce/reduce conflicts diff --git a/test/regress/mof.rb b/test/regress/mof.rb new file mode 100644 index 00000000..e8f7bdab --- /dev/null +++ b/test/regress/mof.rb @@ -0,0 +1,1298 @@ +# +# DO NOT MODIFY!!!! +# This file was automatically generated by Racc 2.0.0.dev +# (codename: Mecha Oishii) from Racc grammar file "mof.y". +# + +require 'racc/parser.rb' + +Object.module_eval(<<'...end mof.y/module_eval...', 'mof.y', 560) + +# parser.rb - generated by racc + +require 'strscan' +require 'rubygems' +require 'cim' +require File.join(File.dirname(__FILE__), 'result') +require File.join(File.dirname(__FILE__), 'scanner') +require File.join(File.dirname(__FILE__), 'helper') + +...end mof.y/module_eval... +module MOF + class Parser < Racc::Parser + +module_eval(<<'...end mof.y/module_eval...2', 'mof.y', 571) + +# +# Initialize MOF::Parser +# MOF::Parser.new options = {} +# +# options -> Hash of options +# :debug -> boolean +# :includes -> array of include dirs +# :style -> :cim or :wmi +# +def initialize options = {} + @yydebug = options[:debug] + @includes = options[:includes] || [] + @quiet = options[:quiet] + @style = options[:style] || :cim # default to style CIM v2.2 syntax + + @lineno = 1 + @file = nil + @iconv = nil + @eol = "\n" + @fname = nil + @fstack = [] + @in_comment = false + @seen_files = [] + @qualifiers = {} +end + +# +# Make options hash from argv +# +# returns [ files, options ] +# + + def self.argv_handler name, argv + files = [] + options = { :namespace => "" } + while argv.size > 0 + case opt = argv.shift + when "-h" + $stderr.puts "Ruby MOF compiler" + $stderr.puts "#{name} [-h] [-d] [-I ] []" + $stderr.puts "Compiles " + $stderr.puts "\t-d debug" + $stderr.puts "\t-h this help" + $stderr.puts "\t-I include dir" + $stderr.puts "\t-f force" + $stderr.puts "\t-n " + $stderr.puts "\t-o " + $stderr.puts "\t-s + + + + +

State 0 (start state)

+ +

+ +
$start:. sql $end $end

+ + + +

+ + From here, we reduce by stmt_list : regardless of what token + comes next.
+ + (This takes us to 2) + + +

+
+ +

State 1

+ +

+ +
$start:sql . $end $end

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Reduce to sql by:
sql : stmt_list
sql
+

+ +

+ + Action table:
+
Lookahead tokenAction
$endShift and go to state 3
OtherError
+ +

+
+ +

State 2

+ +

+ +
sql:stmt_list .
stmt_list:stmt_list . stmt

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
+

+ +

+ + Action table:
+
Lookahead tokenAction
BEGINShift and go to state 8
IFShift and go to state 9
ANDShift and go to state 12
ORShift and go to state 13
IDENTShift and go to state 10
STRING_LITERALShift and go to state 11
SPACESShift and go to state 14
COMMAShift and go to state 15
LPARENShift and go to state 16
RPARENShift and go to state 17
QUESTIONShift and go to state 18
ACTUAL_COMMENTShift and go to state 19
BIND_VARIABLEShift and go to state 22
PAREN_BIND_VARIABLEShift and go to state 23
EMBED_VARIABLEShift and go to state 24
OtherReduce by sql : stmt_list
(This takes us to 1)
+ +

+
+ +

State 3

+ +

+ +
$start:sql $end . $end

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Reduce to sql by:
sql : stmt_list
sql
Shift $end sql $end
+

+ +

+ + Action table:
+
Lookahead tokenAction
$endShift and go to state 25
OtherError
+ +

+
+ +

State 4

+ +

+ +
stmt_list:stmt_list stmt .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IDENT stmt_list IDENT
Reduce to primary by:
primary : IDENT
stmt_list primary
Reduce to stmt by:
stmt : primary
stmt_list stmt
+

+ +

+ + From here, we reduce by stmt_list : stmt_list stmt regardless of what token + comes next.
+ + (This can take us to 2, 26, 27, 41 or 42) + + +

+
+ +

State 5

+ +

+ +
stmt:primary .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IDENT stmt_list IDENT
Reduce to primary by:
primary : IDENT
stmt_list primary
+

+ +

+ + From here, we reduce by stmt : primary regardless of what token + comes next.
+ + (This takes us to 4) + + +

+
+ +

State 6

+ +

+ +
stmt:if_stmt .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Reduce to stmt_list by:
stmt_list :
stmt_list IF stmt_list
Reduce to sub_stmt by:
sub_stmt : stmt_list
stmt_list IF sub_stmt
Reduce to else_stmt by:
else_stmt :
stmt_list IF sub_stmt else_stmt
Shift END stmt_list IF sub_stmt else_stmt END
Reduce to if_stmt by:
if_stmt : IF sub_stmt else_stmt END
stmt_list if_stmt
+

+ +

+ + From here, we reduce by stmt : if_stmt regardless of what token + comes next.
+ + (This takes us to 4) + + +

+
+ +

State 7

+ +

+ +
stmt:begin_stmt .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift BEGIN stmt_list BEGIN
Reduce to stmt_list by:
stmt_list :
stmt_list BEGIN stmt_list
Shift END stmt_list BEGIN stmt_list END
Reduce to begin_stmt by:
begin_stmt : BEGIN stmt_list END
stmt_list begin_stmt
+

+ +

+ + From here, we reduce by stmt : begin_stmt regardless of what token + comes next.
+ + (This takes us to 4) + + +

+
+ +

State 8

+ +

+ +
begin_stmt:BEGIN . stmt_list END

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift BEGIN stmt_list BEGIN
+

+ +

+ + From here, we reduce by stmt_list : regardless of what token + comes next.
+ + (This takes us to 26) + + +

+
+ +

State 9

+ +

+ +
if_stmt:IF . sub_stmt else_stmt END

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
+

+ +

+ + Action table:
+
Lookahead tokenAction
ANDShift and go to state 31
(Overridden: reduce by stmt_list :)
ORShift and go to state 32
(Overridden: reduce by stmt_list :)
OtherReduce by stmt_list :
(This takes us to 27)
+ +

+
+ +

State 10

+ +

+ +
primary:IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IDENT stmt_list IDENT
+

+ +

+ + From here, we reduce by primary : IDENT regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 11

+ +

+ +
primary:STRING_LITERAL .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift STRING_LITERAL stmt_list STRING_LITERAL
+

+ +

+ + From here, we reduce by primary : STRING_LITERAL regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 12

+ +

+ +
primary:AND .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift AND stmt_list AND
+

+ +

+ + From here, we reduce by primary : AND regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 13

+ +

+ +
primary:OR .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift OR stmt_list OR
+

+ +

+ + From here, we reduce by primary : OR regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 14

+ +

+ +
primary:SPACES .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift SPACES stmt_list SPACES
+

+ +

+ + From here, we reduce by primary : SPACES regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 15

+ +

+ +
primary:COMMA .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift COMMA stmt_list COMMA
+

+ +

+ + From here, we reduce by primary : COMMA regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 16

+ +

+ +
primary:LPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift LPAREN stmt_list LPAREN
+

+ +

+ + From here, we reduce by primary : LPAREN regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 17

+ +

+ +
primary:RPAREN .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift RPAREN stmt_list RPAREN
+

+ +

+ + From here, we reduce by primary : RPAREN regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 18

+ +

+ +
primary:QUESTION .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift QUESTION stmt_list QUESTION
+

+ +

+ + From here, we reduce by primary : QUESTION regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 19

+ +

+ +
primary:ACTUAL_COMMENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift ACTUAL_COMMENT stmt_list ACTUAL_COMMENT
+

+ +

+ + From here, we reduce by primary : ACTUAL_COMMENT regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 20

+ +

+ +
primary:bind_var .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift PAREN_BIND_VARIABLE stmt_list PAREN_BIND_VARIABLE
Reduce to bind_var by:
bind_var : PAREN_BIND_VARIABLE
stmt_list bind_var
+

+ +

+ + From here, we reduce by primary : bind_var regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 21

+ +

+ +
primary:embed_var .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift EMBED_VARIABLE stmt_list EMBED_VARIABLE
Shift IDENT stmt_list EMBED_VARIABLE IDENT
Reduce to embed_var by:
embed_var : EMBED_VARIABLE IDENT
stmt_list embed_var
+

+ +

+ + From here, we reduce by primary : embed_var regardless of what token + comes next.
+ + (This takes us to 5) + + +

+
+ +

State 22

+ +

+ +
bind_var:BIND_VARIABLE . STRING_LITERAL
bind_var:BIND_VARIABLE . SPACES STRING_LITERAL
bind_var:BIND_VARIABLE . IDENT
bind_var:BIND_VARIABLE . SPACES IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift BIND_VARIABLE stmt_list BIND_VARIABLE
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 35
STRING_LITERALShift and go to state 33
SPACESShift and go to state 34
OtherError
+ +

+
+ +

State 23

+ +

+ +
bind_var:PAREN_BIND_VARIABLE .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift PAREN_BIND_VARIABLE stmt_list PAREN_BIND_VARIABLE
+

+ +

+ + From here, we reduce by bind_var : PAREN_BIND_VARIABLE regardless of what token + comes next.
+ + (This takes us to 20) + + +

+
+ +

State 24

+ +

+ +
embed_var:EMBED_VARIABLE . IDENT
embed_var:EMBED_VARIABLE . SPACES IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift EMBED_VARIABLE stmt_list EMBED_VARIABLE
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 36
SPACESShift and go to state 37
OtherError
+ +

+
+ +

State 25 (end state)

+ +

+ +
$start:sql $end $end .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Reduce to sql by:
sql : stmt_list
sql
Shift $end sql $end
Shift $end sql $end $end
+

+ +

+ + From here, we stop parsing and return success regardless of what token + comes next.
+ + +

+
+ +

State 26

+ +

+ +
stmt_list:stmt_list . stmt
begin_stmt:BEGIN stmt_list . END

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift BEGIN stmt_list BEGIN
Reduce to stmt_list by:
stmt_list :
stmt_list BEGIN stmt_list
+

+ +

+ + Action table:
+
Lookahead tokenAction
BEGINShift and go to state 8
ENDShift and go to state 38
IFShift and go to state 9
ANDShift and go to state 12
ORShift and go to state 13
IDENTShift and go to state 10
STRING_LITERALShift and go to state 11
SPACESShift and go to state 14
COMMAShift and go to state 15
LPARENShift and go to state 16
RPARENShift and go to state 17
QUESTIONShift and go to state 18
ACTUAL_COMMENTShift and go to state 19
BIND_VARIABLEShift and go to state 22
PAREN_BIND_VARIABLEShift and go to state 23
EMBED_VARIABLEShift and go to state 24
OtherError
+ +

+
+ +

State 27

+ +

+ +
stmt_list:stmt_list . stmt
sub_stmt:stmt_list .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Reduce to stmt_list by:
stmt_list :
stmt_list IF stmt_list
+

+ +

+ + Action table:
+
Lookahead tokenAction
BEGINShift and go to state 8
IFShift and go to state 9
ANDShift and go to state 12
ORShift and go to state 13
IDENTShift and go to state 10
STRING_LITERALShift and go to state 11
SPACESShift and go to state 14
COMMAShift and go to state 15
LPARENShift and go to state 16
RPARENShift and go to state 17
QUESTIONShift and go to state 18
ACTUAL_COMMENTShift and go to state 19
BIND_VARIABLEShift and go to state 22
PAREN_BIND_VARIABLEShift and go to state 23
EMBED_VARIABLEShift and go to state 24
OtherReduce by sub_stmt : stmt_list
(This can take us to 28 or 47)
+ +

+
+ +

State 28

+ +

+ +
if_stmt:IF sub_stmt . else_stmt END

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Reduce to stmt_list by:
stmt_list :
stmt_list IF stmt_list
Reduce to sub_stmt by:
sub_stmt : stmt_list
stmt_list IF sub_stmt
+

+ +

+ + Action table:
+
Lookahead tokenAction
ELSEShift and go to state 40
OtherReduce by else_stmt :
(This takes us to 39)
+ +

+
+ +

State 29

+ +

+ +
sub_stmt:and_stmt .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Shift AND stmt_list IF AND
Reduce to stmt_list by:
stmt_list :
stmt_list IF AND stmt_list
Reduce to and_stmt by:
and_stmt : AND stmt_list
stmt_list IF and_stmt
+

+ +

+ + From here, we reduce by sub_stmt : and_stmt regardless of what token + comes next.
+ + (This can take us to 28 or 47) + + +

+
+ +

State 30

+ +

+ +
sub_stmt:or_stmt .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Shift OR stmt_list IF OR
Reduce to stmt_list by:
stmt_list :
stmt_list IF OR stmt_list
Reduce to or_stmt by:
or_stmt : OR stmt_list
stmt_list IF or_stmt
+

+ +

+ + From here, we reduce by sub_stmt : or_stmt regardless of what token + comes next.
+ + (This can take us to 28 or 47) + + +

+
+ +

State 31

+ +

+ +
and_stmt:AND . stmt_list

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Shift AND stmt_list IF AND
+

+ +

+ + From here, we reduce by stmt_list : regardless of what token + comes next.
+ + (This takes us to 41) + + +

+
+ +

State 32

+ +

+ +
or_stmt:OR . stmt_list

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Shift OR stmt_list IF OR
+

+ +

+ + From here, we reduce by stmt_list : regardless of what token + comes next.
+ + (This takes us to 42) + + +

+
+ +

State 33

+ +

+ +
bind_var:BIND_VARIABLE STRING_LITERAL .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift BIND_VARIABLE stmt_list BIND_VARIABLE
Shift STRING_LITERAL stmt_list BIND_VARIABLE STRING_LITERAL
+

+ +

+ + From here, we reduce by bind_var : BIND_VARIABLE STRING_LITERAL regardless of what token + comes next.
+ + (This takes us to 20) + + +

+
+ +

State 34

+ +

+ +
bind_var:BIND_VARIABLE SPACES . STRING_LITERAL
bind_var:BIND_VARIABLE SPACES . IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift BIND_VARIABLE stmt_list BIND_VARIABLE
Shift SPACES stmt_list BIND_VARIABLE SPACES
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 44
STRING_LITERALShift and go to state 43
OtherError
+ +

+
+ +

State 35

+ +

+ +
bind_var:BIND_VARIABLE IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift BIND_VARIABLE stmt_list BIND_VARIABLE
Shift IDENT stmt_list BIND_VARIABLE IDENT
+

+ +

+ + From here, we reduce by bind_var : BIND_VARIABLE IDENT regardless of what token + comes next.
+ + (This takes us to 20) + + +

+
+ +

State 36

+ +

+ +
embed_var:EMBED_VARIABLE IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift EMBED_VARIABLE stmt_list EMBED_VARIABLE
Shift IDENT stmt_list EMBED_VARIABLE IDENT
+

+ +

+ + From here, we reduce by embed_var : EMBED_VARIABLE IDENT regardless of what token + comes next.
+ + (This takes us to 21) + + +

+
+ +

State 37

+ +

+ +
embed_var:EMBED_VARIABLE SPACES . IDENT

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift EMBED_VARIABLE stmt_list EMBED_VARIABLE
Shift SPACES stmt_list EMBED_VARIABLE SPACES
+

+ +

+ + Action table:
+
Lookahead tokenAction
IDENTShift and go to state 45
OtherError
+ +

+
+ +

State 38

+ +

+ +
begin_stmt:BEGIN stmt_list END .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift BEGIN stmt_list BEGIN
Reduce to stmt_list by:
stmt_list :
stmt_list BEGIN stmt_list
Shift END stmt_list BEGIN stmt_list END
+

+ +

+ + From here, we reduce by begin_stmt : BEGIN stmt_list END regardless of what token + comes next.
+ + (This takes us to 7) + + +

+
+ +

State 39

+ +

+ +
if_stmt:IF sub_stmt else_stmt . END

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Reduce to stmt_list by:
stmt_list :
stmt_list IF stmt_list
Reduce to sub_stmt by:
sub_stmt : stmt_list
stmt_list IF sub_stmt
Reduce to else_stmt by:
else_stmt :
stmt_list IF sub_stmt else_stmt
+

+ +

+ + Action table:
+
Lookahead tokenAction
ENDShift and go to state 46
OtherError
+ +

+
+ +

State 40

+ +

+ +
else_stmt:ELSE . sub_stmt

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Reduce to stmt_list by:
stmt_list :
stmt_list IF stmt_list
Reduce to sub_stmt by:
sub_stmt : stmt_list
stmt_list IF sub_stmt
Shift ELSE stmt_list IF sub_stmt ELSE
+

+ +

+ + Action table:
+
Lookahead tokenAction
ANDShift and go to state 31
(Overridden: reduce by stmt_list :)
ORShift and go to state 32
(Overridden: reduce by stmt_list :)
OtherReduce by stmt_list :
(This takes us to 27)
+ +

+
+ +

State 41

+ +

+ +
stmt_list:stmt_list . stmt
and_stmt:AND stmt_list .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Shift AND stmt_list IF AND
Reduce to stmt_list by:
stmt_list :
stmt_list IF AND stmt_list
+

+ +

+ + Action table:
+
Lookahead tokenAction
BEGINShift and go to state 8
IFShift and go to state 9
ANDShift and go to state 12
ORShift and go to state 13
IDENTShift and go to state 10
STRING_LITERALShift and go to state 11
SPACESShift and go to state 14
COMMAShift and go to state 15
LPARENShift and go to state 16
RPARENShift and go to state 17
QUESTIONShift and go to state 18
ACTUAL_COMMENTShift and go to state 19
BIND_VARIABLEShift and go to state 22
PAREN_BIND_VARIABLEShift and go to state 23
EMBED_VARIABLEShift and go to state 24
OtherReduce by and_stmt : AND stmt_list
(This takes us to 29)
+ +

+
+ +

State 42

+ +

+ +
stmt_list:stmt_list . stmt
or_stmt:OR stmt_list .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Shift OR stmt_list IF OR
Reduce to stmt_list by:
stmt_list :
stmt_list IF OR stmt_list
+

+ +

+ + Action table:
+
Lookahead tokenAction
BEGINShift and go to state 8
IFShift and go to state 9
ANDShift and go to state 12
ORShift and go to state 13
IDENTShift and go to state 10
STRING_LITERALShift and go to state 11
SPACESShift and go to state 14
COMMAShift and go to state 15
LPARENShift and go to state 16
RPARENShift and go to state 17
QUESTIONShift and go to state 18
ACTUAL_COMMENTShift and go to state 19
BIND_VARIABLEShift and go to state 22
PAREN_BIND_VARIABLEShift and go to state 23
EMBED_VARIABLEShift and go to state 24
OtherReduce by or_stmt : OR stmt_list
(This takes us to 30)
+ +

+
+ +

State 43

+ +

+ +
bind_var:BIND_VARIABLE SPACES STRING_LITERAL .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift BIND_VARIABLE stmt_list BIND_VARIABLE
Shift SPACES stmt_list BIND_VARIABLE SPACES
Shift STRING_LITERAL stmt_list BIND_VARIABLE SPACES STRING_LITERAL
+

+ +

+ + From here, we reduce by bind_var : BIND_VARIABLE SPACES STRING_LITERAL regardless of what token + comes next.
+ + (This takes us to 20) + + +

+
+ +

State 44

+ +

+ +
bind_var:BIND_VARIABLE SPACES IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift BIND_VARIABLE stmt_list BIND_VARIABLE
Shift SPACES stmt_list BIND_VARIABLE SPACES
Shift IDENT stmt_list BIND_VARIABLE SPACES IDENT
+

+ +

+ + From here, we reduce by bind_var : BIND_VARIABLE SPACES IDENT regardless of what token + comes next.
+ + (This takes us to 20) + + +

+
+ +

State 45

+ +

+ +
embed_var:EMBED_VARIABLE SPACES IDENT .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift EMBED_VARIABLE stmt_list EMBED_VARIABLE
Shift SPACES stmt_list EMBED_VARIABLE SPACES
Shift IDENT stmt_list EMBED_VARIABLE SPACES IDENT
+

+ +

+ + From here, we reduce by embed_var : EMBED_VARIABLE SPACES IDENT regardless of what token + comes next.
+ + (This takes us to 21) + + +

+
+ +

State 46

+ +

+ +
if_stmt:IF sub_stmt else_stmt END .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Reduce to stmt_list by:
stmt_list :
stmt_list IF stmt_list
Reduce to sub_stmt by:
sub_stmt : stmt_list
stmt_list IF sub_stmt
Reduce to else_stmt by:
else_stmt :
stmt_list IF sub_stmt else_stmt
Shift END stmt_list IF sub_stmt else_stmt END
+

+ +

+ + From here, we reduce by if_stmt : IF sub_stmt else_stmt END regardless of what token + comes next.
+ + (This takes us to 6) + + +

+
+ +

State 47

+ +

+ +
else_stmt:ELSE sub_stmt .

+ +

+ This state can be reached from the start state by:
+
Action:Stack:
Reduce to stmt_list by:
stmt_list :
stmt_list
Shift IF stmt_list IF
Reduce to stmt_list by:
stmt_list :
stmt_list IF stmt_list
Reduce to sub_stmt by:
sub_stmt : stmt_list
stmt_list IF sub_stmt
Shift ELSE stmt_list IF sub_stmt ELSE
Reduce to stmt_list by:
stmt_list :
stmt_list IF sub_stmt ELSE stmt_list
Reduce to sub_stmt by:
sub_stmt : stmt_list
stmt_list IF sub_stmt ELSE sub_stmt
+

+ +

+ + From here, we reduce by else_stmt : ELSE sub_stmt regardless of what token + comes next.
+ + (This takes us to 39) + + +

+
+ + + + diff --git a/test/regress/twowaysql.rb b/test/regress/twowaysql.rb new file mode 100644 index 00000000..bb52708d --- /dev/null +++ b/test/regress/twowaysql.rb @@ -0,0 +1,538 @@ +# +# DO NOT MODIFY!!!! +# This file was automatically generated by Racc 2.0.0.dev +# (codename: Mecha Oishii) from Racc grammar file "twowaysql.y". +# + +require 'racc/parser.rb' +module TwoWaySQL + class Parser < Racc::Parser + +module_eval(<<'...end twowaysql.y/module_eval...', 'twowaysql.y', 148) + +require 'strscan' + +def initialize(opts={}) + opts = { + :debug => false, + :preserve_space => true, + :preserve_comment => false + }.merge(opts) + @yydebug = opts[:debug] + @preserve_space = opts[:preserve_space] + @preserve_comment = opts[:preserve_comment] + @num_questions = 0 +end + + +PAREN_EXAMPLE = '\([^\)]+\)' +BEGIN_BIND_VARIABLE = '(\/|\#)\*([^\*]+)\*\1' +BIND_VARIABLE_PATTERN = /\A#{BEGIN_BIND_VARIABLE}\s*/ +PAREN_BIND_VARIABLE_PATTERN = /\A#{BEGIN_BIND_VARIABLE}\s*#{PAREN_EXAMPLE}/ +EMBED_VARIABLE_PATTERN = /\A(\/|\#)\*\$([^\*]+)\*\1\s*/ + +CONDITIONAL_PATTERN = /\A(\/|\#)\*(IF)\s+([^\*]+)\s*\*\1/ +BEGIN_END_PATTERN = /\A(\/|\#)\*(BEGIN|END)\s*\*\1/ +STRING_LITERAL_PATTERN = /\A(\'(?:[^\']+|\'\')*\')/ ## quoted string +SPLIT_TOKEN_PATTERN = /\A(\S+?)(?=\s*(?:(?:\/|\#)\*|-{2,}|\(|\)|\,))/ ## stop on delimiters --,/*,#*,',',(,) +LITERAL_PATTERN = /\A([^;\s]+)/ +SPACES_PATTERN = /\A(\s+)/ +QUESTION_PATTERN = /\A\?/ +COMMA_PATTERN = /\A\,/ +LPAREN_PATTERN = /\A\(/ +RPAREN_PATTERN = /\A\)/ +ACTUAL_COMMENT_PATTERN = /\A(\/|\#)\*(\s{1,}(?:.*?))\*\1/m ## start with spaces +SEMICOLON_AT_INPUT_END_PATTERN = /\A\;\s*\Z/ +UNMATCHED_COMMENT_START_PATTERN = /\A(?:(?:\/|\#)\*)/ + +#TODO: remove trailing spaces for S2Dao compatibility, but this spec sometimes causes SQL bugs... +ELSE_PATTERN = /\A\-{2,}\s*ELSE\s*/ +AND_PATTERN = /\A(\ *AND)\b/i +OR_PATTERN = /\A(\ *OR)\b/i + + +def parse( io ) + @q = [] + io.each_line(nil) do |whole| + @s = StringScanner.new(whole) + end + scan_str + + # @q.push [ false, nil ] + @q.push [ false, [@s.pos, nil] ] + + ## call racc's private parse method + do_parse +end + + +## called by racc +def next_token + @q.shift +end + + +def scan_str + until @s.eos? do + case + when @s.scan(AND_PATTERN) + @q.push [ :AND, [@s.pos, @s[1]] ] + when @s.scan(OR_PATTERN) + @q.push [ :OR, [@s.pos, @s[1]] ] + when @s.scan(SPACES_PATTERN) + @q.push [ :SPACES, [@s.pos, @s[1]] ] + when @s.scan(QUESTION_PATTERN) + @q.push [ :QUESTION, [@s.pos, nil] ] + when @s.scan(COMMA_PATTERN) + @q.push [ :COMMA, [@s.pos, ','] ] + when @s.scan(LPAREN_PATTERN) + @q.push [ :LPAREN, [@s.pos, '('] ] + when @s.scan(RPAREN_PATTERN) + @q.push [ :RPAREN, [@s.pos, ')'] ] + when @s.scan(ELSE_PATTERN) + @q.push [ :ELSE, [@s.pos, nil] ] + when @s.scan(ACTUAL_COMMENT_PATTERN) + @q.push [ :ACTUAL_COMMENT, [@s.pos, @s[1], @s[2]] ] if @preserve_comment + when @s.scan(BEGIN_END_PATTERN) + @q.push [ @s[2].intern, [@s.pos, nil] ] + when @s.scan(CONDITIONAL_PATTERN) + @q.push [ @s[2].intern, [@s.pos, @s[3]] ] + when @s.scan(EMBED_VARIABLE_PATTERN) + @q.push [ :EMBED_VARIABLE, [@s.pos, @s[2]] ] + when @s.scan(PAREN_BIND_VARIABLE_PATTERN) + @q.push [ :PAREN_BIND_VARIABLE, [@s.pos, @s[2]] ] + when @s.scan(BIND_VARIABLE_PATTERN) + @q.push [ :BIND_VARIABLE, [@s.pos, @s[2]] ] + when @s.scan(STRING_LITERAL_PATTERN) + @q.push [ :STRING_LITERAL, [@s.pos, @s[1]] ] + when @s.scan(SPLIT_TOKEN_PATTERN) + @q.push [ :IDENT, [@s.pos, @s[1]] ] + when @s.scan(UNMATCHED_COMMENT_START_PATTERN) ## unmatched comment start, '/*','#*' + raise Racc::ParseError, "unmatched comment. line:[#{line_no(@s.pos)}], str:[#{@s.rest}]" + when @s.scan(LITERAL_PATTERN) ## other string token + @q.push [ :IDENT, [@s.pos, @s[1]] ] + when @s.scan(SEMICOLON_AT_INPUT_END_PATTERN) + #drop semicolon at input end + else + raise Racc::ParseError, "syntax error at or near line:[#{line_no(@s.pos)}], str:[#{@s.rest}]" + end + end +end + + +## override racc's default on_error method +def on_error(t, v, vstack) + ## cursor in value-stack is an array of two items, + ## that have position value as 0th item. like [731, "ctx[:limit] "] + cursor = vstack.find do |tokens| + tokens.size == 2 and tokens[0].kind_of?(Fixnum) + end + pos = cursor[0] + line = line_no(pos) + rest = @s.string[pos .. -1] + raise Racc::ParseError, "syntax error at or near line:[#{line}], str:[#{rest}]" +end + + +def line_no(pos) + lines = 0 + scanned = @s.string[0..(pos)] + scanned.each_line { lines += 1 } + lines +end +...end twowaysql.y/module_eval... +##### State transition tables begin ### + +racc_action_table = [ +8, 36, 9, 37, 12, 13, 10, 11, 14, 15, 16, 17, 18, 19, 22, +23, 24, 8, 38, 9, 3, 12, 13, 10, 11, 14, 15, 16, 17, 18, +19, 22, 23, 24, 8, 25, 9, 40, 12, 13, 10, 11, 14, 15, 16, +17, 18, 19, 22, 23, 24, 8, 45, 9, 46, 12, 13, 10, 11, 14, +15, 16, 17, 18, 19, 22, 23, 24, 8, nil, 9, nil, 12, 13, 10, +11, 14, 15, 16, 17, 18, 19, 22, 23, 24, 35, 33, 34, 31, 32, +44, 43, 31, 32] + +racc_action_check = [ +2, 24, 2, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +2, 2, 26, 26, 26, 1, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 3, 27, 28, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 41, 37, 41, 39, 41, 41, 41, 41, 41, +41, 41, 41, 41, 41, 41, 41, 41, 42, nil, 42, nil, 42, 42, 42, +42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 22, 22, 22, 9, 9, +34, 34, 40, 40] + +racc_action_pointer = [nil, 20, - +2, 35, nil, nil, nil, nil, nil, 82, nil, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, 77, nil, - +7, nil, 15, 32, 32, nil, nil, nil, nil, nil, 82, nil, nil, 44, nil, +51, 86, 49, 66, nil, nil, nil, nil, nil] + +racc_action_default = [-2, -35, -1, -35, -3, -4, -5, -6, -2, -2, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25, -26, -27, -35, -32, -35, 48, -35, -13, -10, -11, -12, -2, -2, -28, -35, -30, -33, -35, -7, -35, -2, -14, -15, -29, -31, -34, -8, -9] + +racc_goto_table = [ +2, 1, 28, 39, nil, nil, nil, nil, 26, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, 41, 42, 47] + +racc_goto_check = [ +2, 1, 7, 8, nil, nil, nil, nil, 2, nil, nil, nil, nil, nil, nil, +nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, +nil, 2, 2, 7] + +racc_goto_pointer = [nil, 1, 0, nil, nil, nil, nil, -7, -25, nil, nil, nil, nil] + +racc_goto_default = [nil, nil, 27, 4, 5, 6, 7, nil, nil, 29, 30, 20, 21] + +racc_reduce_table = [ + 0, 0, :racc_error, + 1, 20, :_reduce_1, + 0, 21, :_reduce_2, + 2, 21, :_reduce_3, + 1, 22, :_reduce_none, + 1, 22, :_reduce_none, + 1, 22, :_reduce_none, + 3, 25, :_reduce_7, + 4, 24, :_reduce_8, + 2, 27, :_reduce_9, + 0, 27, :_reduce_10, + 1, 26, :_reduce_none, + 1, 26, :_reduce_none, + 1, 26, :_reduce_none, + 2, 28, :_reduce_14, + 2, 29, :_reduce_15, + 1, 23, :_reduce_16, + 1, 23, :_reduce_17, + 1, 23, :_reduce_18, + 1, 23, :_reduce_19, + 1, 23, :_reduce_20, + 1, 23, :_reduce_21, + 1, 23, :_reduce_22, + 1, 23, :_reduce_23, + 1, 23, :_reduce_24, + 1, 23, :_reduce_25, + 1, 23, :_reduce_none, + 1, 23, :_reduce_none, + 2, 30, :_reduce_28, + 3, 30, :_reduce_29, + 2, 30, :_reduce_30, + 3, 30, :_reduce_31, + 1, 30, :_reduce_32, + 2, 31, :_reduce_33, + 3, 31, :_reduce_34 ] + +racc_reduce_n = 35 + +racc_shift_n = 48 + +racc_token_table = { + false => 0, + :error => 1, + :BEGIN => 2, + :END => 3, + :IF => 4, + :ELSE => 5, + :AND => 6, + :OR => 7, + :IDENT => 8, + :STRING_LITERAL => 9, + :SPACES => 10, + :COMMA => 11, + :LPAREN => 12, + :RPAREN => 13, + :QUESTION => 14, + :ACTUAL_COMMENT => 15, + :BIND_VARIABLE => 16, + :PAREN_BIND_VARIABLE => 17, + :EMBED_VARIABLE => 18 } + +racc_nt_base = 19 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ + "$end", + "error", + "BEGIN", + "END", + "IF", + "ELSE", + "AND", + "OR", + "IDENT", + "STRING_LITERAL", + "SPACES", + "COMMA", + "LPAREN", + "RPAREN", + "QUESTION", + "ACTUAL_COMMENT", + "BIND_VARIABLE", + "PAREN_BIND_VARIABLE", + "EMBED_VARIABLE", + "$start", + "sql", + "stmt_list", + "stmt", + "primary", + "if_stmt", + "begin_stmt", + "sub_stmt", + "else_stmt", + "and_stmt", + "or_stmt", + "bind_var", + "embed_var" ] + +Racc_debug_parser = false + +##### State transition tables end ##### + +# reduce 0 omitted + +module_eval(<<'.,.,', 'twowaysql.y', 20) + def _reduce_1(val, _values, result) + result = RootNode.new( val[0] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 25) + def _reduce_2(val, _values, result) + result = [] + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 29) + def _reduce_3(val, _values, result) + result.push val[1] + + result + end +.,., + +# reduce 4 omitted + +# reduce 5 omitted + +# reduce 6 omitted + +module_eval(<<'.,.,', 'twowaysql.y', 38) + def _reduce_7(val, _values, result) + result = BeginNode.new( val[1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 43) + def _reduce_8(val, _values, result) + result = IfNode.new( val[0][1], val[1], val[2] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 48) + def _reduce_9(val, _values, result) + result = val[1] + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 52) + def _reduce_10(val, _values, result) + result = nil + + result + end +.,., + +# reduce 11 omitted + +# reduce 12 omitted + +# reduce 13 omitted + +module_eval(<<'.,.,', 'twowaysql.y', 61) + def _reduce_14(val, _values, result) + result = SubStatementNode.new( val[0][1], val[1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 66) + def _reduce_15(val, _values, result) + result = SubStatementNode.new( val[0][1], val[1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 71) + def _reduce_16(val, _values, result) + result = LiteralNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 75) + def _reduce_17(val, _values, result) + result = LiteralNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 79) + def _reduce_18(val, _values, result) + result = LiteralNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 83) + def _reduce_19(val, _values, result) + result = LiteralNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 87) + def _reduce_20(val, _values, result) + result = WhiteSpaceNode.new( val[0][1], @preserve_space ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 91) + def _reduce_21(val, _values, result) + result = LiteralNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 95) + def _reduce_22(val, _values, result) + result = LiteralNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 99) + def _reduce_23(val, _values, result) + result = LiteralNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 103) + def _reduce_24(val, _values, result) + @num_questions += 1 + result = QuestionNode.new( @num_questions ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 108) + def _reduce_25(val, _values, result) + result = ActualCommentNode.new( val[0][1] , val[0][2] ) + + result + end +.,., + +# reduce 26 omitted + +# reduce 27 omitted + +module_eval(<<'.,.,', 'twowaysql.y', 115) + def _reduce_28(val, _values, result) + result = BindVariableNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 119) + def _reduce_29(val, _values, result) + result = BindVariableNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 123) + def _reduce_30(val, _values, result) + result = BindVariableNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 127) + def _reduce_31(val, _values, result) + result = BindVariableNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 131) + def _reduce_32(val, _values, result) + result = ParenBindVariableNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 136) + def _reduce_33(val, _values, result) + result = EmbedVariableNode.new( val[0][1] ) + + result + end +.,., + +module_eval(<<'.,.,', 'twowaysql.y', 140) + def _reduce_34(val, _values, result) + result = EmbedVariableNode.new( val[0][1] ) + + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] +end + + end # class Parser + end # module TwoWaySQL diff --git a/test/run_tests.sh b/test/run_tests.sh new file mode 100755 index 00000000..b308aefb --- /dev/null +++ b/test/run_tests.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# as of 2019-05, Travis Rubies 2.4 and later have RubyGems 3.0.3 or later installed + +set -eux + +test_frozen_strings=$(ruby -e 'puts ((RUBY_ENGINE == "ruby" || RUBY_ENGINE == "jruby") && RUBY_VERSION > "2.4")') + +if [[ $test_frozen_strings == "true" ]] ; then + echo "NOTE: enabling frozen string literals" + export RUBYOPT="--enable-frozen-string-literal --debug=frozen-string-literal" +fi + +# Workaround for JRuby builds seeming to not generate this ragel machine +bundle exec rake lib/racc/grammar_file_scanner.rb + +# Unset this variable because it adds a warning to JVM startup +unset _JAVA_OPTIONS + +# Speed up JRuby startup for subprocess tests +export JRUBY_OPTS='--disable-gems --dev' + +bundle exec rake test +bundle exec rake test_pure diff --git a/test/scandata/blockcomment b/test/scandata/blockcomment new file mode 100644 index 00000000..d7f62e79 --- /dev/null +++ b/test/scandata/blockcomment @@ -0,0 +1,9 @@ +$LOAD_PATH.unshift(File.dirname(__FILE__)+'/lib') + +=begin +some code here }}} +this doesn't count if it isn't at the start of the line: + =end +=end this is also commented here + +require 'parser/current' diff --git a/test/scandata/brace b/test/scandata/brace index f6c84385..9e3a9ff3 100644 --- a/test/scandata/brace +++ b/test/scandata/brace @@ -1,7 +1,6 @@ -{ { - } { } { - { { { } } } - { { { {} } } } - {} {} {} - } +method { self.call { + }; { }; { + a { b { c { } } } => + d { e { f { {} => {} } } } + }; {}; {}; {}; } diff --git a/test/scandata/comment_at_eof b/test/scandata/comment_at_eof new file mode 100644 index 00000000..13dbf0d5 --- /dev/null +++ b/test/scandata/comment_at_eof @@ -0,0 +1 @@ +# this caused problems with an earlier version of the scanner \ No newline at end of file diff --git a/test/scandata/dynstr b/test/scandata/dynstr new file mode 100644 index 00000000..18282ff3 --- /dev/null +++ b/test/scandata/dynstr @@ -0,0 +1,11 @@ +line "#{name} = #{lines.join("\n")}" + +"#{"#{"#{1}"}"}" + +"#{array.join(' ')}" + +# we must also be able to deal with \#{ +"#{configuration[:scope].to_s} = \#{#{configuration[:scope].to_s}}" + +# and nested interpolations which contain strings of a different type +"Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found.#{SQLCounter.log.size == 0 ? '' : "\nQueries:\n#{SQLCounter.log.join("\n")}"}" \ No newline at end of file diff --git a/test/scandata/escapednl b/test/scandata/escapednl new file mode 100644 index 00000000..5506ea92 --- /dev/null +++ b/test/scandata/escapednl @@ -0,0 +1,6 @@ +puts 1 + \ +2 + +class \ +<< self +end diff --git a/test/scandata/gvar b/test/scandata/gvar index 50528ce9..cd2d6f3b 100644 --- a/test/scandata/gvar +++ b/test/scandata/gvar @@ -1 +1 @@ -{ $' $" $& $-a $/ $\ $( $1 $2 $3 $? $-i } +$' + $" + $& + $-a + $/ + $\ + $1 + $2 + $3 + $? + $-i diff --git a/test/scandata/heredocs b/test/scandata/heredocs new file mode 100644 index 00000000..adfb2550 --- /dev/null +++ b/test/scandata/heredocs @@ -0,0 +1,44 @@ +<>>\n#{ok}----\n#{val}<<<" - - $stderr.puts 'ok' - rescue => err - $stderr.puts 'fail (' + err.type.to_s + ')' - $stderr.puts err.message - $stderr.puts err.backtrace - $stderr.puts - end -end diff --git a/web/racc.en.rhtml b/web/racc.en.rhtml deleted file mode 100644 index 269011b4..00000000 --- a/web/racc.en.rhtml +++ /dev/null @@ -1,42 +0,0 @@ -% require 'makefile' -% version = Makefile.get_parameter('Makefile', 'version') -

Racc

-

-$Id$ -

- - - - - - - -
Version<%= version %>
TypeParser Generator
FormatRuby script + Ruby extention
Requirementruby (>=1.6)
LicenseLGPL
-

--- Download (.tar.gz) --- Old Versions --- Online Manual --- -

- -

-Racc (Ruby yACC) is a LALR(1) parser generator for Ruby. -Version 1.4.x is stable release. -

-

-Parsers generated by Racc requires "Racc Runtime Module". -Ruby 1.8.x comes with this runtime. -If you want to run your parsers with ruby 1.6.x, -use "racc -E" command. For details, see online manual. -

- -

Anonymous CVS

-

-You can true latest version of Racc via anonymous CVS. -To check out working copy, type: -

-
-$ cvs -d :pserver:anonymous@cvs.loveruby.net:/src login
-Password: (Just hit [Enter])
-$ cvs -d :pserver:anonymous@cvs.loveruby.net:/src co racc
-
diff --git a/web/racc.ja.rhtml b/web/racc.ja.rhtml deleted file mode 100644 index 92e5459b..00000000 --- a/web/racc.ja.rhtml +++ /dev/null @@ -1,51 +0,0 @@ -% require 'makefile' -% version = Makefile.get_parameter('Makefile', 'version') -

Racc

-

-$Id$ -

- - - - - - -
ǿ<%= version %>
parser generator
ruby script, ruby extention
ɬ״Ķruby (>=1.6)
۾LGPL
- -

-

-Ruby Ѥ LALR(1) ѡͥ졼Ǥ -ѡϤʤ˹®ưޤ -

-

-Racc ѡư˥󥿥⥸塼뤬ɬפǤ -Ruby 1.8 ˤϤΥ󥿥बǽ餫źդƤΤ -ͤʤפǤRuby 1.6 оݤˤȤ -racc -E ǥѡɬפޤ -

-

-ʤRacc 1.4.x Υ󥿥 Ruby 1.8 źդ Racc 󥿥ϡ -ɾǤ̯˰㤤ޤ˸ߴޤ -

- -

-

-⤦ŪʬϸϤƤϤǤ -TODO ϤޤĤޤ¾ˤäƤΤ -ʬ礭ѹĤϤޤ -

- -

CVS ݥȥ

-

-CVS Ȥ Racc οκǿǤǤޤ -ޥɥ饤ǼΤ褦ǤäƤ -

-
-$ cvs -d :pserver:anonymous@cvs.loveruby.net:/src login
-Password: (EnterǤ)
-$ cvs -d :pserver:anonymous@cvs.loveruby.net:/src co racc
-