From: bdemsky Date: Fri, 3 Feb 2006 01:15:48 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: preEdgeChange~1004 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=IRC.git;a=commitdiff_plain;h=6252e70d2488b82f1848be20647246e5c1bd45d1 *** empty log message *** --- diff --git a/Robust/JavaGrammar/COPYING b/Robust/JavaGrammar/COPYING new file mode 100644 index 00000000..a43ea212 --- /dev/null +++ b/Robust/JavaGrammar/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies 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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +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) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Robust/JavaGrammar/Makefile b/Robust/JavaGrammar/Makefile new file mode 100644 index 00000000..758243e1 --- /dev/null +++ b/Robust/JavaGrammar/Makefile @@ -0,0 +1,89 @@ +# Makefile to create simple test framework for the java parsers. +# Copyright (C) 1998 C. Scott Ananian +# Released under the terms of the GPL with NO WARRANTY. See COPYING. + +# java environment. +JAVA=java +JAVAC=javac +JFLAGS=-g +#CUPFLAGS=-dump_states + +# list the available java grammar versions +JAVA_GRAMMARS=10 11 12 14 15 + +all: $(foreach j,$(JAVA_GRAMMARS),Parse/Grm$(j).class) \ + Lex/Lex.class Main/Main.class + +# Feed the appropriate CUP specification to javaCUP. +Parse/Grm%.java Parse/Sym%.java: Parse/java%.cup + cd Parse && \ + ${JAVA} java_cup.Main ${CUPFLAGS} -parser Grm$* -symbols Sym$* \ + < java$*.cup 2>Grm$*.err && tail Grm$*.err + +# Compile the java source for the parser. +Parse/Grm%.class: Parse/Lexer.java Parse/Grm%.java Parse/Sym%.java + ${JAVAC} ${JFLAGS} $^ + +# Make the lexer symbols from the parser symbols. +Lex/Sym.java: $(foreach j,$(JAVA_GRAMMARS),Parse/Sym$(j).java) +# verify that these are all identical! + @if cat $^ | sed -e 's/Sym[0-9][0-9]/Sym/g' | sort | uniq -c | \ + egrep -v '^[ ]*[0-9]*[05] ' | grep -v "^[ ]*[0-9]*[ ]*//"\ + ; then \ + echo $^ "are not identical;" ;\ + echo "we won't be able to build a single lexer for all of these." ;\ + exit 1;\ + fi +# now make a generic version. + sed -e "s/package Parse/package Lex/" -e "s/Sym10/Sym/g" \ + < Parse/Sym10.java > $@ + +# Compile the java source for the (unified) lexer. +Lex/Lex.class: Lex/*.java Lex/Sym.java + ${JAVAC} ${JFLAGS} Lex/*.java + +# Compile the java source for the driver. +Main/Main.class: Main/Main.java + ${JAVAC} ${JFLAGS} Main/*.java + +# run some quick tests. +test: Parse/Lexer.java Parse/Grm14.java all phony + for n in 1 2 3 4 5; do \ + ( ${JAVA} Main.Main Parse/Lexer.java $$n && \ + ${JAVA} Main.Main Parse/Grm14.java $$n && \ + ${JAVA} Main.Main tests/Escape.java) || exit 1; \ + done + for n in 2 3 4 5; do \ + ${JAVA} Main.Main tests/Eric.java $$n || exit 1; \ + done + ${JAVA} Main.Main tests/TestJSR201.java 5 + ${JAVA} Main.Main tests/Test15.java 5 + ${JAVA} Main.Main tests/Eric15.java 5 +# always run the test. +phony: + +# target to make the distributed files. +dist: + -$(RM) -rf JavaGrammar javagrm.tar.gz javagrm.zip + cvs -d `cat CVS/Root` co -A -P JavaGrammar + find JavaGrammar -type d -name CVS | xargs $(RM) -rf + tar czvf javagrm.tar.gz JavaGrammar + zip -r javagrm.zip JavaGrammar + cp javagrm.tar.gz `date +javagrm-%d-%b-%Y.tar.gz` + cp README javagrm-README.txt + $(RM) -rf JavaGrammar +upload: dist + chmod a+r javagrm* + scp javagrm* shades.cs.princeton.edu:/u/appel/public_html/modern/java/CUP + +# clean up after ourselves. +clean: + $(RM) Lex/Sym.java \ + $(foreach j,$(JAVA_GRAMMARS),Parse/Grm$(j).err) \ + $(foreach j,$(JAVA_GRAMMARS),Parse/Grm$(j).java) \ + $(foreach j,$(JAVA_GRAMMARS),Parse/Sym$(j).java) \ + Parse/parser.java Parse/sym.java \ + */*.class + +veryclean: clean + $(RM) *~ */*~ javagrm* diff --git a/Robust/JavaGrammar/README b/Robust/JavaGrammar/README new file mode 100644 index 00000000..62edac60 --- /dev/null +++ b/Robust/JavaGrammar/README @@ -0,0 +1,146 @@ +This package contains CUP grammars for the Java programming language. + +Copyright (C) 2002 C. Scott Ananian +This code is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. See the file COPYING for more details. + +Directory structure: + Parse/ contains the Java grammars. + java10.cup contains a Java 1.0 grammar. + java11.cup contains a Java 1.1 grammar. + java12.cup contains a Java 1.2 grammar. [added 11-feb-1999] + java14.cup contains a Java 1.4 grammar. [added 10-apr-2002] + java15.cup contains a Java 1.5 Java grammar. [added 12-apr-2002] + [last updated 28-jul-2003; Java 1.5 spec not yet final.] + Lexer.java interface description for a lexer. + + Lex/ contains a simple but complete Java lexer. + Lex.java main class + Sym.java a copy of Parse/Sym.java containing symbolic constants. + + Main/ + Main.java a simple testing skeleton for the parser/lexer. + +The grammar in Parse/ should be processed by CUP into Grm.java. +There are much better ways to write lexers for java, but the +implementation in Lex/ seemed to be the easiest at the time. The +lexer implemented here may not be as efficient as a table-driven lexer, +but adheres to the java specification exactly. + + -- C. Scott Ananian 3-Apr-1998 + [revised 12-apr-2002] + [revised 28-jul-2003] + +UPDATE: Fixed a lexer bug: '5.2' is a double, not a float. Thanks to +Ben Walter for spotting this. + + -- C. Scott Ananian 14-Jul-1998 + +UPDATE: Fixed a couple of minor bugs. +1) Lex.EscapedUnicodeReader wasn't actually parsing unicode escape sequences + properly because we didn't implement read(char[], int, int). +2) Grammar fixes: int[].class, Object[].class and all array class + literals were not being parsed. Also special void.class literal + inadvertantly omitted from the grammar. +Both these problems have been fixed. + + -- C. Scott Ananian 11-Feb-1999 + +UPDATE: Fixed another lexer bug: Large integer constants such as +0xFFFF0000 were being incorrectly flagged as 'too large for an int'. +Also, by the Java Language Specification, "\477" is a valid string +literal (it is the same as "\0477": the character '\047' followed by +the character '7'). The lexer handles this case correctly now. + +Created java12.cup with grammar updated to Java 1.2. Features +added include the 'strictfp' keyword and the various new inner class +features at http://java.sun.com/docs/books/jls/nested-class-clarify.html. + +Also added slightly better position/error reporting to all parsers. + + -- C. Scott Ananian 11-Feb-1999 + +UPDATE: fixed some buglets with symbol/error position reporting. + + -- C. Scott Ananian 13-Sep-1999 + +UPDATE: multi-line comments were causing incorrect character position +reporting. If you were using the character-position-to-line-number +code in Lexer, you would never have noticed this problem. Thanks to +William Young for pointing this out. + + -- C. Scott Ananian 27-Oct-1999 + +UPDATE: extended grammar to handle the 'assert' statement added in +Java 1.4. Also fixed an oversight: a single SEMICOLON is a valid +ClassBodyDeclaration; this was added to allow trailing semicolons +uniformly on class declarations. This wasn't part of the original +JLS, but was revised in to conform with the actual behavior of the +javac compiler. I've added this to all the grammars from 1.0-1.4 +to conform to javac behavior; let me know if you've got a good +reason why this production shouldn't be in early grammars. + +Also futzed with the Makefile some to allow building a 'universal' +driver which will switch between java 1.0/1.1/1.2/1.4 on demand. +This helps me test the separate grammars; maybe you'll find a +use for this behavior too. + + -- C. Scott Ananian 10-Apr-2002 + +NEW: added a grammar for the JSR-14 "Adding Generics to the Java +Programming Language" Java variant. Calling this java15.cup, since +this JSR currently seems to be destined for inclusion in Java 1.5. +This grammar is very very tricky! I need to use a lexer trick to +handle type casts to parameterized types, which otherwise do not +seem to be LALR(1). + -- C. Scott Ananian 12-Apr-2002 + +UPDATE: various bug fixes to all grammars, in reponse to bugs reported +by Eric Blake and others. + a) TWEAK: added 'String' type to IDENTIFIER terminal to match Number types + given to numeric literals. (all grammars) + b) BUG FIX: added SEMICOLON production to interface_member_declaration to + allow optional trailing semicolons, in accordance with the JLS (for + java 1.2-and-later grammars) and Sun practice (for earlier grammars). + The 10-Apr-2002 release did not address this problem completely, due + to an oversight. (all grammars) + c) BUG FIX: '.this(...);' is not a legal production; + '.super(...);' and '.new (...' ought to be. + In particular, plain identifiers ought to be able to qualify instance + creation and explicit constructor invocation. + (fix due to Eric Blake; java 1.2 grammar and following) + d) BUG FIX: parenthesized variables on the left-hand-side of an assignment + ought to be legal, according to JLS2. For example, this code is + legal: + class Foo { void m(int i) { (i) = 1; } } + (fix due to Eric Blake; java 1.2 grammar and following) + e) BUG FIX: array access of anonymous arrays ought to be legal, according + to JLS2. For example, this is legal code: + class Foo { int i = new int[]{0}[0]; } + (fix due to Eric Blake; java 1.2 grammar and following) + f) BUG FIX: nested parameterized types ought to be legal, for example: + class A { class B { } A.B c; } + (bug found by Eric Blake; jsr-14 grammar only) + g) TWEAK: test cases were added for these issues. + +In addition, it should be clarified that the 'java15.cup' grammar is +really only for java 1.4 + jsr-14; recent developments at Sun indicate +that "Java 1.5" is likely to include several additional language changes +in addition to JSR-14 parameterized types; see JSR-201 for more details. +I will endeavor to add these features to 'java15.cup' as soon as their +syntax is nailed down. + -- C. Scott Ananian 13-Apr-2003 + +UPDATE: Updated the 'java15.cup' grammar to match the latest specifications +(and their corrections) for Java 1.5. This grammar matches the 2.2 +prototype of JSR-14 + JSR-201 capabilities, with some corrections for +mistakes in the released specification and expected future features of +Java 1.5 (in particular, arrays of parameterized types bounded by +wildcards). Reimplemented java15.cup to use a refactoring originally +due to Eric Blake which eliminates our previous need for "lexer lookahead" +(see release notes for 12-April-2002). Added new 'enum' and '...' tokens +to the lexer to accomodate Java 1.5. New test cases added for the +additional language features. + -- C. Scott Ananian 28-Jul-2003 diff --git a/Robust/cup/java_cup/runtime/Scanner.class b/Robust/cup/java_cup/runtime/Scanner.class new file mode 100644 index 00000000..29ef66b2 Binary files /dev/null and b/Robust/cup/java_cup/runtime/Scanner.class differ diff --git a/Robust/cup/java_cup/runtime/Scanner.java b/Robust/cup/java_cup/runtime/Scanner.java new file mode 100644 index 00000000..32335516 --- /dev/null +++ b/Robust/cup/java_cup/runtime/Scanner.java @@ -0,0 +1,25 @@ +package java_cup.runtime; + +/** + * Defines the Scanner interface, which CUP uses in the default + * implementation of lr_parser.scan(). Integration + * of scanners implementing Scanner is facilitated. + * + * @version last updated 23-Jul-1999 + * @author David MacMahon + */ + +/* ************************************************* + Interface Scanner + + Declares the next_token() method that should be + implemented by scanners. This method is typically + called by lr_parser.scan(). End-of-file can be + indicated either by returning + new Symbol(lr_parser.EOF_sym()) or + null. + ***************************************************/ +public interface Scanner { + /** Return the next token, or null on end-of-file. */ + public Symbol next_token() throws java.lang.Exception; +} diff --git a/Robust/cup/java_cup/runtime/Symbol.class b/Robust/cup/java_cup/runtime/Symbol.class new file mode 100644 index 00000000..4831d12d Binary files /dev/null and b/Robust/cup/java_cup/runtime/Symbol.class differ diff --git a/Robust/cup/java_cup/runtime/Symbol.java b/Robust/cup/java_cup/runtime/Symbol.java new file mode 100644 index 00000000..eeb6a0b4 --- /dev/null +++ b/Robust/cup/java_cup/runtime/Symbol.java @@ -0,0 +1,105 @@ +package java_cup.runtime; + +/** + * Defines the Symbol class, which is used to represent all terminals + * and nonterminals while parsing. The lexer should pass CUP Symbols + * and CUP returns a Symbol. + * + * @version last updated: 7/3/96 + * @author Frank Flannery + */ + +/* **************************************************************** + Class Symbol + what the parser expects to receive from the lexer. + the token is identified as follows: + sym: the symbol type + parse_state: the parse state. + value: is the lexical value of type Object + left : is the left position in the original input file + right: is the right position in the original input file +******************************************************************/ + +public class Symbol { + +/******************************* + Constructor for l,r values + *******************************/ + + public Symbol(int id, int l, int r, Object o) { + this(id); + left = l; + right = r; + value = o; + } + +/******************************* + Constructor for no l,r values +********************************/ + + public Symbol(int id, Object o) { + this(id, -1, -1, o); + } + +/***************************** + Constructor for no value + ***************************/ + + public Symbol(int id, int l, int r) { + this(id, l, r, null); + } + +/*********************************** + Constructor for no value or l,r +***********************************/ + + public Symbol(int sym_num) { + this(sym_num, -1); + left = -1; + right = -1; + value = null; + } + +/*********************************** + Constructor to give a start state +***********************************/ + Symbol(int sym_num, int state) + { + sym = sym_num; + parse_state = state; + } + +/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The symbol number of the terminal or non terminal being represented */ + public int sym; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The parse state to be recorded on the parse stack with this symbol. + * This field is for the convenience of the parser and shouldn't be + * modified except by the parser. + */ + public int parse_state; + /** This allows us to catch some errors caused by scanners recycling + * symbols. For the use of the parser only. [CSA, 23-Jul-1999] */ + boolean used_by_parser = false; + +/******************************* + The data passed to parser + *******************************/ + + public int left, right; + public Object value; + + /***************************** + Printing this token out. (Override for pretty-print). + ****************************/ + public String toString() { return "#"+sym; } +} + + + + + + diff --git a/Robust/cup/java_cup/runtime/lr_parser.class b/Robust/cup/java_cup/runtime/lr_parser.class new file mode 100644 index 00000000..3edd4973 Binary files /dev/null and b/Robust/cup/java_cup/runtime/lr_parser.class differ diff --git a/Robust/cup/java_cup/runtime/lr_parser.java b/Robust/cup/java_cup/runtime/lr_parser.java new file mode 100644 index 00000000..3c8335cb --- /dev/null +++ b/Robust/cup/java_cup/runtime/lr_parser.java @@ -0,0 +1,1238 @@ + +package java_cup.runtime; + +import java.util.Stack; + +/** This class implements a skeleton table driven LR parser. In general, + * LR parsers are a form of bottom up shift-reduce parsers. Shift-reduce + * parsers act by shifting input onto a parse stack until the Symbols + * matching the right hand side of a production appear on the top of the + * stack. Once this occurs, a reduce is performed. This involves removing + * the Symbols corresponding to the right hand side of the production + * (the so called "handle") and replacing them with the non-terminal from + * the left hand side of the production.

+ * + * To control the decision of whether to shift or reduce at any given point, + * the parser uses a state machine (the "viable prefix recognition machine" + * built by the parser generator). The current state of the machine is placed + * on top of the parse stack (stored as part of a Symbol object representing + * a terminal or non terminal). The parse action table is consulted + * (using the current state and the current lookahead Symbol as indexes) to + * determine whether to shift or to reduce. When the parser shifts, it + * changes to a new state by pushing a new Symbol (containing a new state) + * onto the stack. When the parser reduces, it pops the handle (right hand + * side of a production) off the stack. This leaves the parser in the state + * it was in before any of those Symbols were matched. Next the reduce-goto + * table is consulted (using the new state and current lookahead Symbol as + * indexes) to determine a new state to go to. The parser then shifts to + * this goto state by pushing the left hand side Symbol of the production + * (also containing the new state) onto the stack.

+ * + * This class actually provides four LR parsers. The methods parse() and + * debug_parse() provide two versions of the main parser (the only difference + * being that debug_parse() emits debugging trace messages as it parses). + * In addition to these main parsers, the error recovery mechanism uses two + * more. One of these is used to simulate "parsing ahead" in the input + * without carrying out actions (to verify that a potential error recovery + * has worked), and the other is used to parse through buffered "parse ahead" + * input in order to execute all actions and re-synchronize the actual parser + * configuration.

+ * + * This is an abstract class which is normally filled out by a subclass + * generated by the JavaCup parser generator. In addition to supplying + * the actual parse tables, generated code also supplies methods which + * invoke various pieces of user supplied code, provide access to certain + * special Symbols (e.g., EOF and error), etc. Specifically, the following + * abstract methods are normally supplied by generated code: + *

+ *
short[][] production_table() + *
Provides a reference to the production table (indicating the index of + * the left hand side non terminal and the length of the right hand side + * for each production in the grammar). + *
short[][] action_table() + *
Provides a reference to the parse action table. + *
short[][] reduce_table() + *
Provides a reference to the reduce-goto table. + *
int start_state() + *
Indicates the index of the start state. + *
int start_production() + *
Indicates the index of the starting production. + *
int EOF_sym() + *
Indicates the index of the EOF Symbol. + *
int error_sym() + *
Indicates the index of the error Symbol. + *
Symbol do_action() + *
Executes a piece of user supplied action code. This always comes at + * the point of a reduce in the parse, so this code also allocates and + * fills in the left hand side non terminal Symbol object that is to be + * pushed onto the stack for the reduce. + *
void init_actions() + *
Code to initialize a special object that encapsulates user supplied + * actions (this object is used by do_action() to actually carry out the + * actions). + *
+ * + * In addition to these routines that must be supplied by the + * generated subclass there are also a series of routines that may + * be supplied. These include: + *
+ *
Symbol scan() + *
Used to get the next input Symbol from the scanner. + *
Scanner getScanner() + *
Used to provide a scanner for the default implementation of + * scan(). + *
int error_sync_size() + *
This determines how many Symbols past the point of an error + * must be parsed without error in order to consider a recovery to + * be valid. This defaults to 3. Values less than 2 are not + * recommended. + *
void report_error(String message, Object info) + *
This method is called to report an error. The default implementation + * simply prints a message to System.err and where the error occurred. + * This method is often replaced in order to provide a more sophisticated + * error reporting mechanism. + *
void report_fatal_error(String message, Object info) + *
This method is called when a fatal error that cannot be recovered from + * is encountered. In the default implementation, it calls + * report_error() to emit a message, then throws an exception. + *
void syntax_error(Symbol cur_token) + *
This method is called as soon as syntax error is detected (but + * before recovery is attempted). In the default implementation it + * invokes: report_error("Syntax error", null); + *
void unrecovered_syntax_error(Symbol cur_token) + *
This method is called if syntax error recovery fails. In the default + * implementation it invokes:
+ * report_fatal_error("Couldn't repair and continue parse", null); + *
+ * + * @see java_cup.runtime.Symbol + * @see java_cup.runtime.Symbol + * @see java_cup.runtime.virtual_parse_stack + * @version last updated: 7/3/96 + * @author Frank Flannery + */ + +public abstract class lr_parser { + + /*-----------------------------------------------------------*/ + /*--- Constructor(s) ----------------------------------------*/ + /*-----------------------------------------------------------*/ + + /** Simple constructor. */ + public lr_parser() + { + /* nothing to do here */ + } + + /** Constructor that sets the default scanner. [CSA/davidm] */ + public lr_parser(Scanner s) { + this(); /* in case default constructor someday does something */ + setScanner(s); + } + + /*-----------------------------------------------------------*/ + /*--- (Access to) Static (Class) Variables ------------------*/ + /*-----------------------------------------------------------*/ + + /** The default number of Symbols after an error we much match to consider + * it recovered from. + */ + protected final static int _error_sync_size = 3; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The number of Symbols after an error we much match to consider it + * recovered from. + */ + protected int error_sync_size() {return _error_sync_size; } + + /*-----------------------------------------------------------*/ + /*--- (Access to) Instance Variables ------------------------*/ + /*-----------------------------------------------------------*/ + + /** Table of production information (supplied by generated subclass). + * This table contains one entry per production and is indexed by + * the negative-encoded values (reduce actions) in the action_table. + * Each entry has two parts, the index of the non-terminal on the + * left hand side of the production, and the number of Symbols + * on the right hand side. + */ + public abstract short[][] production_table(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The action table (supplied by generated subclass). This table is + * indexed by state and terminal number indicating what action is to + * be taken when the parser is in the given state (i.e., the given state + * is on top of the stack) and the given terminal is next on the input. + * States are indexed using the first dimension, however, the entries for + * a given state are compacted and stored in adjacent index, value pairs + * which are searched for rather than accessed directly (see get_action()). + * The actions stored in the table will be either shifts, reduces, or + * errors. Shifts are encoded as positive values (one greater than the + * state shifted to). Reduces are encoded as negative values (one less + * than the production reduced by). Error entries are denoted by zero. + * + * @see java_cup.runtime.lr_parser#get_action + */ + public abstract short[][] action_table(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The reduce-goto table (supplied by generated subclass). This + * table is indexed by state and non-terminal number and contains + * state numbers. States are indexed using the first dimension, however, + * the entries for a given state are compacted and stored in adjacent + * index, value pairs which are searched for rather than accessed + * directly (see get_reduce()). When a reduce occurs, the handle + * (corresponding to the RHS of the matched production) is popped off + * the stack. The new top of stack indicates a state. This table is + * then indexed by that state and the LHS of the reducing production to + * indicate where to "shift" to. + * + * @see java_cup.runtime.lr_parser#get_reduce + */ + public abstract short[][] reduce_table(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The index of the start state (supplied by generated subclass). */ + public abstract int start_state(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The index of the start production (supplied by generated subclass). */ + public abstract int start_production(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The index of the end of file terminal Symbol (supplied by generated + * subclass). + */ + public abstract int EOF_sym(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The index of the special error Symbol (supplied by generated subclass). */ + public abstract int error_sym(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Internal flag to indicate when parser should quit. */ + protected boolean _done_parsing = false; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** This method is called to indicate that the parser should quit. This is + * normally called by an accept action, but can be used to cancel parsing + * early in other circumstances if desired. + */ + public void done_parsing() + { + _done_parsing = true; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + /* Global parse state shared by parse(), error recovery, and + * debugging routines */ + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Indication of the index for top of stack (for use by actions). */ + protected int tos; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The current lookahead Symbol. */ + protected Symbol cur_token; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** The parse stack itself. */ + protected Stack stack = new Stack(); + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Direct reference to the production table. */ + protected short[][] production_tab; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Direct reference to the action table. */ + protected short[][] action_tab; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Direct reference to the reduce-goto table. */ + protected short[][] reduce_tab; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** This is the scanner object used by the default implementation + * of scan() to get Symbols. To avoid name conflicts with existing + * code, this field is private. [CSA/davidm] */ + private Scanner _scanner; + + /** + * Simple accessor method to set the default scanner. + */ + public void setScanner(Scanner s) { _scanner = s; } + + /** + * Simple accessor method to get the default scanner. + */ + public Scanner getScanner() { return _scanner; } + + /*-----------------------------------------------------------*/ + /*--- General Methods ---------------------------------------*/ + /*-----------------------------------------------------------*/ + + /** Perform a bit of user supplied action code (supplied by generated + * subclass). Actions are indexed by an internal action number assigned + * at parser generation time. + * + * @param act_num the internal index of the action to be performed. + * @param parser the parser object we are acting for. + * @param stack the parse stack of that object. + * @param top the index of the top element of the parse stack. + */ + public abstract Symbol do_action( + int act_num, + lr_parser parser, + Stack stack, + int top) + throws java.lang.Exception; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** User code for initialization inside the parser. Typically this + * initializes the scanner. This is called before the parser requests + * the first Symbol. Here this is just a placeholder for subclasses that + * might need this and we perform no action. This method is normally + * overridden by the generated code using this contents of the "init with" + * clause as its body. + */ + public void user_init() throws java.lang.Exception { } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Initialize the action object. This is called before the parser does + * any parse actions. This is filled in by generated code to create + * an object that encapsulates all action code. + */ + protected abstract void init_actions() throws java.lang.Exception; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Get the next Symbol from the input (supplied by generated subclass). + * Once end of file has been reached, all subsequent calls to scan + * should return an EOF Symbol (which is Symbol number 0). By default + * this method returns getScanner().next_token(); this implementation + * can be overriden by the generated parser using the code declared in + * the "scan with" clause. Do not recycle objects; every call to + * scan() should return a fresh object. + */ + public Symbol scan() throws java.lang.Exception { + Symbol sym = getScanner().next_token(); + return (sym!=null) ? sym : new Symbol(EOF_sym()); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Report a fatal error. This method takes a message string and an + * additional object (to be used by specializations implemented in + * subclasses). Here in the base class a very simple implementation + * is provided which reports the error then throws an exception. + * + * @param message an error message. + * @param info an extra object reserved for use by specialized subclasses. + */ + public void report_fatal_error( + String message, + Object info) + throws java.lang.Exception + { + /* stop parsing (not really necessary since we throw an exception, but) */ + done_parsing(); + + /* use the normal error message reporting to put out the message */ + report_error(message, info); + + /* throw an exception */ + throw new Exception("Can't recover from previous error(s)"); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Report a non fatal error (or warning). This method takes a message + * string and an additional object (to be used by specializations + * implemented in subclasses). Here in the base class a very simple + * implementation is provided which simply prints the message to + * System.err. + * + * @param message an error message. + * @param info an extra object reserved for use by specialized subclasses. + */ + public void report_error(String message, Object info) + { + System.err.print(message); + if (info instanceof Symbol) + if (((Symbol)info).left != -1) + System.err.println(" at character " + ((Symbol)info).left + + " of input"); + else System.err.println(""); + else System.err.println(""); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** This method is called when a syntax error has been detected and recovery + * is about to be invoked. Here in the base class we just emit a + * "Syntax error" error message. + * + * @param cur_token the current lookahead Symbol. + */ + public void syntax_error(Symbol cur_token) + { + report_error("Syntax error", cur_token); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** This method is called if it is determined that syntax error recovery + * has been unsuccessful. Here in the base class we report a fatal error. + * + * @param cur_token the current lookahead Symbol. + */ + public void unrecovered_syntax_error(Symbol cur_token) + throws java.lang.Exception + { + report_fatal_error("Couldn't repair and continue parse", cur_token); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Fetch an action from the action table. The table is broken up into + * rows, one per state (rows are indexed directly by state number). + * Within each row, a list of index, value pairs are given (as sequential + * entries in the table), and the list is terminated by a default entry + * (denoted with a Symbol index of -1). To find the proper entry in a row + * we do a linear or binary search (depending on the size of the row). + * + * @param state the state index of the action being accessed. + * @param sym the Symbol index of the action being accessed. + */ + protected final short get_action(int state, int sym) + { + short tag; + int first, last, probe; + short[] row = action_tab[state]; + + /* linear search if we are < 10 entries */ + if (row.length < 20) + for (probe = 0; probe < row.length; probe++) + { + /* is this entry labeled with our Symbol or the default? */ + tag = row[probe++]; + if (tag == sym || tag == -1) + { + /* return the next entry */ + return row[probe]; + } + } + /* otherwise binary search */ + else + { + first = 0; + last = (row.length-1)/2 - 1; /* leave out trailing default entry */ + while (first <= last) + { + probe = (first+last)/2; + if (sym == row[probe*2]) + return row[probe*2+1]; + else if (sym > row[probe*2]) + first = probe+1; + else + last = probe-1; + } + + /* not found, use the default at the end */ + return row[row.length-1]; + } + + /* shouldn't happened, but if we run off the end we return the + default (error == 0) */ + return 0; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Fetch a state from the reduce-goto table. The table is broken up into + * rows, one per state (rows are indexed directly by state number). + * Within each row, a list of index, value pairs are given (as sequential + * entries in the table), and the list is terminated by a default entry + * (denoted with a Symbol index of -1). To find the proper entry in a row + * we do a linear search. + * + * @param state the state index of the entry being accessed. + * @param sym the Symbol index of the entry being accessed. + */ + protected final short get_reduce(int state, int sym) + { + short tag; + short[] row = reduce_tab[state]; + + /* if we have a null row we go with the default */ + if (row == null) + return -1; + + for (int probe = 0; probe < row.length; probe++) + { + /* is this entry labeled with our Symbol or the default? */ + tag = row[probe++]; + if (tag == sym || tag == -1) + { + /* return the next entry */ + return row[probe]; + } + } + /* if we run off the end we return the default (error == -1) */ + return -1; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** This method provides the main parsing routine. It returns only when + * done_parsing() has been called (typically because the parser has + * accepted, or a fatal error has been reported). See the header + * documentation for the class regarding how shift/reduce parsers operate + * and how the various tables are used. + */ + public Symbol parse() throws java.lang.Exception + { + /* the current action code */ + int act; + + /* the Symbol/stack element returned by a reduce */ + Symbol lhs_sym = null; + + /* information about production being reduced with */ + short handle_size, lhs_sym_num; + + /* set up direct reference to tables to drive the parser */ + + production_tab = production_table(); + action_tab = action_table(); + reduce_tab = reduce_table(); + + /* initialize the action encapsulation object */ + init_actions(); + + /* do user initialization */ + user_init(); + + /* get the first token */ + cur_token = scan(); + + /* push dummy Symbol with start state to get us underway */ + stack.removeAllElements(); + stack.push(new Symbol(0, start_state())); + tos = 0; + + /* continue until we are told to stop */ + for (_done_parsing = false; !_done_parsing; ) + { + /* Check current token for freshness. */ + if (cur_token.used_by_parser) + throw new Error("Symbol recycling detected (fix your scanner)."); + + /* current state is always on the top of the stack */ + + /* look up action out of the current state with the current input */ + act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); + + /* decode the action -- > 0 encodes shift */ + if (act > 0) + { + /* shift to the encoded state by pushing it on the stack */ + cur_token.parse_state = act-1; + cur_token.used_by_parser = true; + stack.push(cur_token); + tos++; + + /* advance to the next Symbol */ + cur_token = scan(); + } + /* if its less than zero, then it encodes a reduce action */ + else if (act < 0) + { + /* perform the action for the reduce */ + lhs_sym = do_action((-act)-1, this, stack, tos); + + /* look up information about the production */ + lhs_sym_num = production_tab[(-act)-1][0]; + handle_size = production_tab[(-act)-1][1]; + + /* pop the handle off the stack */ + for (int i = 0; i < handle_size; i++) + { + stack.pop(); + tos--; + } + + /* look up the state to go to from the one popped back to */ + act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); + + /* shift to that state */ + lhs_sym.parse_state = act; + lhs_sym.used_by_parser = true; + stack.push(lhs_sym); + tos++; + } + /* finally if the entry is zero, we have an error */ + else if (act == 0) + { + /* call user syntax error reporting routine */ + syntax_error(cur_token); + + /* try to error recover */ + if (!error_recovery(false)) + { + /* if that fails give up with a fatal syntax error */ + unrecovered_syntax_error(cur_token); + + /* just in case that wasn't fatal enough, end parse */ + done_parsing(); + } else { + lhs_sym = (Symbol)stack.peek(); + } + } + } + return lhs_sym; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Write a debugging message to System.err for the debugging version + * of the parser. + * + * @param mess the text of the debugging message. + */ + public void debug_message(String mess) + { + System.err.println(mess); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Dump the parse stack for debugging purposes. */ + public void dump_stack() + { + if (stack == null) + { + debug_message("# Stack dump requested, but stack is null"); + return; + } + + debug_message("============ Parse Stack Dump ============"); + + /* dump the stack */ + for (int i=0; i"); + if ((i%3)==2 || (i==(stack.size()-1))) { + debug_message(sb.toString()); + sb = new StringBuffer(" "); + } + } + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Perform a parse with debugging output. This does exactly the + * same things as parse(), except that it calls debug_shift() and + * debug_reduce() when shift and reduce moves are taken by the parser + * and produces various other debugging messages. + */ + public Symbol debug_parse() + throws java.lang.Exception + { + /* the current action code */ + int act; + + /* the Symbol/stack element returned by a reduce */ + Symbol lhs_sym = null; + + /* information about production being reduced with */ + short handle_size, lhs_sym_num; + + /* set up direct reference to tables to drive the parser */ + production_tab = production_table(); + action_tab = action_table(); + reduce_tab = reduce_table(); + + debug_message("# Initializing parser"); + + /* initialize the action encapsulation object */ + init_actions(); + + /* do user initialization */ + user_init(); + + /* the current Symbol */ + cur_token = scan(); + + debug_message("# Current Symbol is #" + cur_token.sym); + + /* push dummy Symbol with start state to get us underway */ + stack.removeAllElements(); + stack.push(new Symbol(0, start_state())); + tos = 0; + + /* continue until we are told to stop */ + for (_done_parsing = false; !_done_parsing; ) + { + /* Check current token for freshness. */ + if (cur_token.used_by_parser) + throw new Error("Symbol recycling detected (fix your scanner)."); + + /* current state is always on the top of the stack */ + //debug_stack(); + + /* look up action out of the current state with the current input */ + act = get_action(((Symbol)stack.peek()).parse_state, cur_token.sym); + + /* decode the action -- > 0 encodes shift */ + if (act > 0) + { + /* shift to the encoded state by pushing it on the stack */ + cur_token.parse_state = act-1; + cur_token.used_by_parser = true; + debug_shift(cur_token); + stack.push(cur_token); + tos++; + + /* advance to the next Symbol */ + cur_token = scan(); + debug_message("# Current token is " + cur_token); + } + /* if its less than zero, then it encodes a reduce action */ + else if (act < 0) + { + /* perform the action for the reduce */ + lhs_sym = do_action((-act)-1, this, stack, tos); + + /* look up information about the production */ + lhs_sym_num = production_tab[(-act)-1][0]; + handle_size = production_tab[(-act)-1][1]; + + debug_reduce((-act)-1, lhs_sym_num, handle_size); + + /* pop the handle off the stack */ + for (int i = 0; i < handle_size; i++) + { + stack.pop(); + tos--; + } + + /* look up the state to go to from the one popped back to */ + act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); + debug_message("# Reduce rule: top state " + + ((Symbol)stack.peek()).parse_state + + ", lhs sym " + lhs_sym_num + " -> state " + act); + + /* shift to that state */ + lhs_sym.parse_state = act; + lhs_sym.used_by_parser = true; + stack.push(lhs_sym); + tos++; + + debug_message("# Goto state #" + act); + } + /* finally if the entry is zero, we have an error */ + else if (act == 0) + { + /* call user syntax error reporting routine */ + syntax_error(cur_token); + + /* try to error recover */ + if (!error_recovery(true)) + { + /* if that fails give up with a fatal syntax error */ + unrecovered_syntax_error(cur_token); + + /* just in case that wasn't fatal enough, end parse */ + done_parsing(); + } else { + lhs_sym = (Symbol)stack.peek(); + } + } + } + return lhs_sym; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + /* Error recovery code */ + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Attempt to recover from a syntax error. This returns false if recovery + * fails, true if it succeeds. Recovery happens in 4 steps. First we + * pop the parse stack down to a point at which we have a shift out + * of the top-most state on the error Symbol. This represents the + * initial error recovery configuration. If no such configuration is + * found, then we fail. Next a small number of "lookahead" or "parse + * ahead" Symbols are read into a buffer. The size of this buffer is + * determined by error_sync_size() and determines how many Symbols beyond + * the error must be matched to consider the recovery a success. Next, + * we begin to discard Symbols in attempt to get past the point of error + * to a point where we can continue parsing. After each Symbol, we attempt + * to "parse ahead" though the buffered lookahead Symbols. The "parse ahead" + * process simulates that actual parse, but does not modify the real + * parser's configuration, nor execute any actions. If we can parse all + * the stored Symbols without error, then the recovery is considered a + * success. Once a successful recovery point is determined, we do an + * actual parse over the stored input -- modifying the real parse + * configuration and executing all actions. Finally, we return the the + * normal parser to continue with the overall parse. + * + * @param debug should we produce debugging messages as we parse. + */ + protected boolean error_recovery(boolean debug) + throws java.lang.Exception + { + if (debug) debug_message("# Attempting error recovery"); + + /* first pop the stack back into a state that can shift on error and + do that shift (if that fails, we fail) */ + if (!find_recovery_config(debug)) + { + if (debug) debug_message("# Error recovery fails"); + return false; + } + + /* read ahead to create lookahead we can parse multiple times */ + read_lookahead(); + + /* repeatedly try to parse forward until we make it the required dist */ + for (;;) + { + /* try to parse forward, if it makes it, bail out of loop */ + if (debug) debug_message("# Trying to parse ahead"); + if (try_parse_ahead(debug)) + { + break; + } + + /* if we are now at EOF, we have failed */ + if (lookahead[0].sym == EOF_sym()) + { + if (debug) debug_message("# Error recovery fails at EOF"); + return false; + } + + /* otherwise, we consume another Symbol and try again */ + // BUG FIX by Bruce Hutton + // Computer Science Department, University of Auckland, + // Auckland, New Zealand. + // It is the first token that is being consumed, not the one + // we were up to parsing + if (debug) + debug_message("# Consuming Symbol #" + lookahead[ 0 ].sym); + restart_lookahead(); + } + + /* we have consumed to a point where we can parse forward */ + if (debug) debug_message("# Parse-ahead ok, going back to normal parse"); + + /* do the real parse (including actions) across the lookahead */ + parse_lookahead(debug); + + /* we have success */ + return true; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Determine if we can shift under the special error Symbol out of the + * state currently on the top of the (real) parse stack. + */ + protected boolean shift_under_error() + { + /* is there a shift under error Symbol */ + return get_action(((Symbol)stack.peek()).parse_state, error_sym()) > 0; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Put the (real) parse stack into error recovery configuration by + * popping the stack down to a state that can shift on the special + * error Symbol, then doing the shift. If no suitable state exists on + * the stack we return false + * + * @param debug should we produce debugging messages as we parse. + */ + protected boolean find_recovery_config(boolean debug) + { + Symbol error_token; + int act; + + if (debug) debug_message("# Finding recovery state on stack"); + + /* Remember the right-position of the top symbol on the stack */ + int right_pos = ((Symbol)stack.peek()).right; + int left_pos = ((Symbol)stack.peek()).left; + + /* pop down until we can shift under error Symbol */ + while (!shift_under_error()) + { + /* pop the stack */ + if (debug) + debug_message("# Pop stack by one, state was # " + + ((Symbol)stack.peek()).parse_state); + left_pos = ((Symbol)stack.pop()).left; + tos--; + + /* if we have hit bottom, we fail */ + if (stack.empty()) + { + if (debug) debug_message("# No recovery state found on stack"); + return false; + } + } + + /* state on top of the stack can shift under error, find the shift */ + act = get_action(((Symbol)stack.peek()).parse_state, error_sym()); + if (debug) + { + debug_message("# Recover state found (#" + + ((Symbol)stack.peek()).parse_state + ")"); + debug_message("# Shifting on error to state #" + (act-1)); + } + + /* build and shift a special error Symbol */ + error_token = new Symbol(error_sym(), left_pos, right_pos); + error_token.parse_state = act-1; + error_token.used_by_parser = true; + stack.push(error_token); + tos++; + + return true; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Lookahead Symbols used for attempting error recovery "parse aheads". */ + protected Symbol lookahead[]; + + /** Position in lookahead input buffer used for "parse ahead". */ + protected int lookahead_pos; + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Read from input to establish our buffer of "parse ahead" lookahead + * Symbols. + */ + protected void read_lookahead() throws java.lang.Exception + { + /* create the lookahead array */ + lookahead = new Symbol[error_sync_size()]; + + /* fill in the array */ + for (int i = 0; i < error_sync_size(); i++) + { + lookahead[i] = cur_token; + cur_token = scan(); + } + + /* start at the beginning */ + lookahead_pos = 0; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Return the current lookahead in our error "parse ahead" buffer. */ + protected Symbol cur_err_token() { return lookahead[lookahead_pos]; } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Advance to next "parse ahead" input Symbol. Return true if we have + * input to advance to, false otherwise. + */ + protected boolean advance_lookahead() + { + /* advance the input location */ + lookahead_pos++; + + /* return true if we didn't go off the end */ + return lookahead_pos < error_sync_size(); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Reset the parse ahead input to one Symbol past where we started error + * recovery (this consumes one new Symbol from the real input). + */ + protected void restart_lookahead() throws java.lang.Exception + { + /* move all the existing input over */ + for (int i = 1; i < error_sync_size(); i++) + lookahead[i-1] = lookahead[i]; + + /* read a new Symbol into the last spot */ + // BUG Fix by Bruce Hutton + // Computer Science Department, University of Auckland, + // Auckland, New Zealand. [applied 5-sep-1999 by csa] + // The following two lines were out of order!! + lookahead[error_sync_size()-1] = cur_token; + cur_token = scan(); + + /* reset our internal position marker */ + lookahead_pos = 0; + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Do a simulated parse forward (a "parse ahead") from the current + * stack configuration using stored lookahead input and a virtual parse + * stack. Return true if we make it all the way through the stored + * lookahead input without error. This basically simulates the action of + * parse() using only our saved "parse ahead" input, and not executing any + * actions. + * + * @param debug should we produce debugging messages as we parse. + */ + protected boolean try_parse_ahead(boolean debug) + throws java.lang.Exception + { + int act; + short lhs, rhs_size; + + /* create a virtual stack from the real parse stack */ + virtual_parse_stack vstack = new virtual_parse_stack(stack); + + /* parse until we fail or get past the lookahead input */ + for (;;) + { + /* look up the action from the current state (on top of stack) */ + act = get_action(vstack.top(), cur_err_token().sym); + + /* if its an error, we fail */ + if (act == 0) return false; + + /* > 0 encodes a shift */ + if (act > 0) + { + /* push the new state on the stack */ + vstack.push(act-1); + + if (debug) debug_message("# Parse-ahead shifts Symbol #" + + cur_err_token().sym + " into state #" + (act-1)); + + /* advance simulated input, if we run off the end, we are done */ + if (!advance_lookahead()) return true; + } + /* < 0 encodes a reduce */ + else + { + /* if this is a reduce with the start production we are done */ + if ((-act)-1 == start_production()) + { + if (debug) debug_message("# Parse-ahead accepts"); + return true; + } + + /* get the lhs Symbol and the rhs size */ + lhs = production_tab[(-act)-1][0]; + rhs_size = production_tab[(-act)-1][1]; + + /* pop handle off the stack */ + for (int i = 0; i < rhs_size; i++) + vstack.pop(); + + if (debug) + debug_message("# Parse-ahead reduces: handle size = " + + rhs_size + " lhs = #" + lhs + " from state #" + vstack.top()); + + /* look up goto and push it onto the stack */ + vstack.push(get_reduce(vstack.top(), lhs)); + if (debug) + debug_message("# Goto state #" + vstack.top()); + } + } + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Parse forward using stored lookahead Symbols. In this case we have + * already verified that parsing will make it through the stored lookahead + * Symbols and we are now getting back to the point at which we can hand + * control back to the normal parser. Consequently, this version of the + * parser performs all actions and modifies the real parse configuration. + * This returns once we have consumed all the stored input or we accept. + * + * @param debug should we produce debugging messages as we parse. + */ + protected void parse_lookahead(boolean debug) + throws java.lang.Exception + { + /* the current action code */ + int act; + + /* the Symbol/stack element returned by a reduce */ + Symbol lhs_sym = null; + + /* information about production being reduced with */ + short handle_size, lhs_sym_num; + + /* restart the saved input at the beginning */ + lookahead_pos = 0; + + if (debug) + { + debug_message("# Reparsing saved input with actions"); + debug_message("# Current Symbol is #" + cur_err_token().sym); + debug_message("# Current state is #" + + ((Symbol)stack.peek()).parse_state); + } + + /* continue until we accept or have read all lookahead input */ + while(!_done_parsing) + { + /* current state is always on the top of the stack */ + + /* look up action out of the current state with the current input */ + act = + get_action(((Symbol)stack.peek()).parse_state, cur_err_token().sym); + + /* decode the action -- > 0 encodes shift */ + if (act > 0) + { + /* shift to the encoded state by pushing it on the stack */ + cur_err_token().parse_state = act-1; + cur_err_token().used_by_parser = true; + if (debug) debug_shift(cur_err_token()); + stack.push(cur_err_token()); + tos++; + + /* advance to the next Symbol, if there is none, we are done */ + if (!advance_lookahead()) + { + if (debug) debug_message("# Completed reparse"); + + /* scan next Symbol so we can continue parse */ + // BUGFIX by Chris Harris : + // correct a one-off error by commenting out + // this next line. + /*cur_token = scan();*/ + + /* go back to normal parser */ + return; + } + + if (debug) + debug_message("# Current Symbol is #" + cur_err_token().sym); + } + /* if its less than zero, then it encodes a reduce action */ + else if (act < 0) + { + /* perform the action for the reduce */ + lhs_sym = do_action((-act)-1, this, stack, tos); + + /* look up information about the production */ + lhs_sym_num = production_tab[(-act)-1][0]; + handle_size = production_tab[(-act)-1][1]; + + if (debug) debug_reduce((-act)-1, lhs_sym_num, handle_size); + + /* pop the handle off the stack */ + for (int i = 0; i < handle_size; i++) + { + stack.pop(); + tos--; + } + + /* look up the state to go to from the one popped back to */ + act = get_reduce(((Symbol)stack.peek()).parse_state, lhs_sym_num); + + /* shift to that state */ + lhs_sym.parse_state = act; + lhs_sym.used_by_parser = true; + stack.push(lhs_sym); + tos++; + + if (debug) debug_message("# Goto state #" + act); + + } + /* finally if the entry is zero, we have an error + (shouldn't happen here, but...)*/ + else if (act == 0) + { + report_fatal_error("Syntax error", lhs_sym); + return; + } + } + + + } + + /*-----------------------------------------------------------*/ + + /** Utility function: unpacks parse tables from strings */ + protected static short[][] unpackFromStrings(String[] sa) + { + // Concatanate initialization strings. + StringBuffer sb = new StringBuffer(sa[0]); + for (int i=1; i= real_stack.size()) return; + + /* get a copy of the first Symbol we have not transfered */ + stack_sym = (Symbol)real_stack.elementAt(real_stack.size()-1-real_next); + + /* record the transfer */ + real_next++; + + /* put the state number from the Symbol onto the virtual stack */ + vstack.push(new Integer(stack_sym.parse_state)); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Indicate whether the stack is empty. */ + public boolean empty() + { + /* if vstack is empty then we were unable to transfer onto it and + the whole thing is empty. */ + return vstack.empty(); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Return value on the top of the stack (without popping it). */ + public int top() throws java.lang.Exception + { + if (vstack.empty()) + throw new Exception( + "Internal parser error: top() called on empty virtual stack"); + + return ((Integer)vstack.peek()).intValue(); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Pop the stack. */ + public void pop() throws java.lang.Exception + { + if (vstack.empty()) + throw new Exception( + "Internal parser error: pop from empty virtual stack"); + + /* pop it */ + vstack.pop(); + + /* if we are now empty transfer an element (if there is one) */ + if (vstack.empty()) + get_from_real(); + } + + /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/ + + /** Push a state number onto the stack. */ + public void push(int state_num) + { + vstack.push(new Integer(state_num)); + } + + /*-----------------------------------------------------------*/ + +} diff --git a/Robust/cup/java_cup/simple_calc/CUP$parser$actions.class b/Robust/cup/java_cup/simple_calc/CUP$parser$actions.class new file mode 100644 index 00000000..5758ef55 Binary files /dev/null and b/Robust/cup/java_cup/simple_calc/CUP$parser$actions.class differ diff --git a/Robust/cup/java_cup/simple_calc/Main.class b/Robust/cup/java_cup/simple_calc/Main.class new file mode 100644 index 00000000..aa2cc953 Binary files /dev/null and b/Robust/cup/java_cup/simple_calc/Main.class differ diff --git a/Robust/cup/java_cup/simple_calc/Main.java b/Robust/cup/java_cup/simple_calc/Main.java new file mode 100644 index 00000000..21ff5aa5 --- /dev/null +++ b/Robust/cup/java_cup/simple_calc/Main.java @@ -0,0 +1,32 @@ +// Driver for parser + +package java_cup.simple_calc; + +import java_cup.simple_calc.parser; +import java_cup.runtime.Symbol; + +class Main { + + static boolean do_debug_parse = false; + + static public void main(String[] args) throws java.io.IOException { + + /* create a parsing object */ + parser parser_obj = new parser(new scanner()); + + /* open input files, etc. here */ + Symbol parse_tree = null; + + try { + if (do_debug_parse) + parse_tree = parser_obj.debug_parse(); + else + parse_tree = parser_obj.parse(); + } catch (Exception e) { + /* do cleanup here -- possibly rethrow e */ + } finally { + /* do close out here */ + } + } +} + diff --git a/Robust/cup/java_cup/simple_calc/parser.class b/Robust/cup/java_cup/simple_calc/parser.class new file mode 100644 index 00000000..05da56ab Binary files /dev/null and b/Robust/cup/java_cup/simple_calc/parser.class differ diff --git a/Robust/cup/java_cup/simple_calc/parser.cup b/Robust/cup/java_cup/simple_calc/parser.cup new file mode 100644 index 00000000..a88d9007 --- /dev/null +++ b/Robust/cup/java_cup/simple_calc/parser.cup @@ -0,0 +1,55 @@ +// JavaCup specification for a simple expression evaluator (w/ actions) + +package java_cup.simple_calc; + +import java_cup.runtime.*; + +/* Terminals (tokens returned by the scanner). */ +terminal SEMI, PLUS, MINUS, TIMES, DIVIDE, MOD; +terminal UMINUS, LPAREN, RPAREN; +terminal Integer NUMBER; + +/* Non terminals */ +non terminal Object expr_list, expr_part; +non terminal Integer expr; + +/* Precedences */ +precedence left PLUS, MINUS; +precedence left TIMES, DIVIDE, MOD; +precedence left UMINUS, LPAREN; + +/* The grammar */ +expr_list ::= expr_list expr_part + | + expr_part; + +expr_part ::= expr:e + {: System.out.println("= " + e); :} + SEMI + ; + +expr ::= expr:e1 PLUS expr:e2 + {: RESULT = new Integer(e1.intValue() + e2.intValue()); :} + | + expr:e1 MINUS expr:e2 + {: RESULT = new Integer(e1.intValue() - e2.intValue()); :} + | + expr:e1 TIMES expr:e2 + {: RESULT = new Integer(e1.intValue() * e2.intValue()); :} + | + expr:e1 DIVIDE expr:e2 + {: RESULT = new Integer(e1.intValue() / e2.intValue()); :} + | + expr:e1 MOD expr:e2 + {: RESULT = new Integer(e1.intValue() % e2.intValue()); :} + | + NUMBER:n + {: RESULT = n; :} + | + MINUS expr:e + {: RESULT = new Integer(0 - e.intValue()); :} + %prec UMINUS + | + LPAREN expr:e RPAREN + {: RESULT = e; :} + ; diff --git a/Robust/cup/java_cup/simple_calc/parser.java b/Robust/cup/java_cup/simple_calc/parser.java new file mode 100644 index 00000000..d6003c72 --- /dev/null +++ b/Robust/cup/java_cup/simple_calc/parser.java @@ -0,0 +1,318 @@ + +//---------------------------------------------------- +// The following code was generated by CUP v0.10k +// Sun Jul 25 13:36:02 EDT 1999 +//---------------------------------------------------- + +package java_cup.simple_calc; + +import java_cup.runtime.*; + +/** CUP v0.10k generated parser. + * @version Sun Jul 25 13:36:02 EDT 1999 + */ +public class parser extends java_cup.runtime.lr_parser { + + /** Default constructor. */ + public parser() {super();} + + /** Constructor which sets the default scanner. */ + public parser(java_cup.runtime.Scanner s) {super(s);} + + /** Production table. */ + protected static final short _production_table[][] = + unpackFromStrings(new String[] { + "\000\015\000\002\003\004\000\002\002\004\000\002\003" + + "\003\000\002\006\002\000\002\004\005\000\002\005\005" + + "\000\002\005\005\000\002\005\005\000\002\005\005\000" + + "\002\005\005\000\002\005\003\000\002\005\004\000\002" + + "\005\005" }); + + /** Access to production table. */ + public short[][] production_table() {return _production_table;} + + /** Parse-action table. */ + protected static final short[][] _action_table = + unpackFromStrings(new String[] { + "\000\030\000\010\006\004\013\011\015\005\001\002\000" + + "\010\006\004\013\011\015\005\001\002\000\020\004\ufff7" + + "\005\ufff7\006\ufff7\007\ufff7\010\ufff7\011\ufff7\014\ufff7\001" + + "\002\000\012\002\uffff\006\uffff\013\uffff\015\uffff\001\002" + + "\000\016\004\ufffe\005\016\006\014\007\020\010\017\011" + + "\013\001\002\000\012\002\027\006\004\013\011\015\005" + + "\001\002\000\010\006\004\013\011\015\005\001\002\000" + + "\016\005\016\006\014\007\020\010\017\011\013\014\015" + + "\001\002\000\010\006\004\013\011\015\005\001\002\000" + + "\010\006\004\013\011\015\005\001\002\000\020\004\ufff5" + + "\005\ufff5\006\ufff5\007\ufff5\010\ufff5\011\ufff5\014\ufff5\001" + + "\002\000\010\006\004\013\011\015\005\001\002\000\010" + + "\006\004\013\011\015\005\001\002\000\010\006\004\013" + + "\011\015\005\001\002\000\020\004\ufffa\005\ufffa\006\ufffa" + + "\007\ufffa\010\ufffa\011\ufffa\014\ufffa\001\002\000\020\004" + + "\ufff9\005\ufff9\006\ufff9\007\ufff9\010\ufff9\011\ufff9\014\ufff9" + + "\001\002\000\020\004\ufffc\005\ufffc\006\ufffc\007\020\010" + + "\017\011\013\014\ufffc\001\002\000\020\004\ufffb\005\ufffb" + + "\006\ufffb\007\020\010\017\011\013\014\ufffb\001\002\000" + + "\020\004\ufff8\005\ufff8\006\ufff8\007\ufff8\010\ufff8\011\ufff8" + + "\014\ufff8\001\002\000\012\002\001\006\001\013\001\015" + + "\001\001\002\000\004\002\000\001\002\000\004\004\031" + + "\001\002\000\012\002\ufffd\006\ufffd\013\ufffd\015\ufffd\001" + + "\002\000\020\004\ufff6\005\ufff6\006\ufff6\007\ufff6\010\ufff6" + + "\011\ufff6\014\ufff6\001\002" }); + + /** Access to parse-action table. */ + public short[][] action_table() {return _action_table;} + + /** reduce_goto table. */ + protected static final short[][] _reduce_table = + unpackFromStrings(new String[] { + "\000\030\000\010\003\007\004\005\005\006\001\001\000" + + "\004\005\031\001\001\000\002\001\001\000\002\001\001" + + "\000\004\006\027\001\001\000\006\004\025\005\006\001" + + "\001\000\004\005\011\001\001\000\002\001\001\000\004" + + "\005\024\001\001\000\004\005\023\001\001\000\002\001" + + "\001\000\004\005\022\001\001\000\004\005\021\001\001" + + "\000\004\005\020\001\001\000\002\001\001\000\002\001" + + "\001\000\002\001\001\000\002\001\001\000\002\001\001" + + "\000\002\001\001\000\002\001\001\000\002\001\001\000" + + "\002\001\001\000\002\001\001" }); + + /** Access to reduce_goto table. */ + public short[][] reduce_table() {return _reduce_table;} + + /** Instance of action encapsulation class. */ + protected CUP$parser$actions action_obj; + + /** Action encapsulation object initializer. */ + protected void init_actions() + { + action_obj = new CUP$parser$actions(this); + } + + /** Invoke a user supplied parse action. */ + public java_cup.runtime.Symbol do_action( + int act_num, + java_cup.runtime.lr_parser parser, + java.util.Stack stack, + int top) + throws java.lang.Exception + { + /* call code in generated class */ + return action_obj.CUP$parser$do_action(act_num, parser, stack, top); + } + + /** Indicates start state. */ + public int start_state() {return 0;} + /** Indicates start production. */ + public int start_production() {return 1;} + + /** EOF Symbol index. */ + public int EOF_sym() {return 0;} + + /** error Symbol index. */ + public int error_sym() {return 1;} + +} + +/** Cup generated class to encapsulate user supplied action code.*/ +class CUP$parser$actions { + private final parser parser; + + /** Constructor */ + CUP$parser$actions(parser parser) { + this.parser = parser; + } + + /** Method with the actual generated action code. */ + public final java_cup.runtime.Symbol CUP$parser$do_action( + int CUP$parser$act_num, + java_cup.runtime.lr_parser CUP$parser$parser, + java.util.Stack CUP$parser$stack, + int CUP$parser$top) + throws java.lang.Exception + { + /* Symbol object for return from actions */ + java_cup.runtime.Symbol CUP$parser$result; + + /* select the action based on the action number */ + switch (CUP$parser$act_num) + { + /*. . . . . . . . . . . . . . . . . . . .*/ + case 12: // expr ::= LPAREN expr RPAREN + { + Integer RESULT = null; + int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left; + int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right; + Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value; + RESULT = e; + CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 11: // expr ::= MINUS expr + { + Integer RESULT = null; + int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left; + int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right; + Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value; + RESULT = new Integer(0 - e.intValue()); + CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 10: // expr ::= NUMBER + { + Integer RESULT = null; + int nleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left; + int nright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right; + Integer n = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value; + RESULT = n; + CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 9: // expr ::= expr MOD expr + { + Integer RESULT = null; + int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left; + int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right; + Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value; + int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left; + int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right; + Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value; + RESULT = new Integer(e1.intValue() % e2.intValue()); + CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 8: // expr ::= expr DIVIDE expr + { + Integer RESULT = null; + int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left; + int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right; + Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value; + int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left; + int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right; + Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value; + RESULT = new Integer(e1.intValue() / e2.intValue()); + CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 7: // expr ::= expr TIMES expr + { + Integer RESULT = null; + int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left; + int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right; + Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value; + int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left; + int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right; + Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value; + RESULT = new Integer(e1.intValue() * e2.intValue()); + CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 6: // expr ::= expr MINUS expr + { + Integer RESULT = null; + int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left; + int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right; + Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value; + int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left; + int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right; + Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value; + RESULT = new Integer(e1.intValue() - e2.intValue()); + CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 5: // expr ::= expr PLUS expr + { + Integer RESULT = null; + int e1left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left; + int e1right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right; + Integer e1 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value; + int e2left = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left; + int e2right = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right; + Integer e2 = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value; + RESULT = new Integer(e1.intValue() + e2.intValue()); + CUP$parser$result = new java_cup.runtime.Symbol(3/*expr*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 4: // expr_part ::= expr NT$0 SEMI + { + Object RESULT = null; + // propagate RESULT from NT$0 + if ( ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value != null ) + RESULT = (Object) ((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value; + int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left; + int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).right; + Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-2)).value; + + CUP$parser$result = new java_cup.runtime.Symbol(2/*expr_part*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-2)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 3: // NT$0 ::= + { + Object RESULT = null; + int eleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left; + int eright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right; + Integer e = (Integer)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-0)).value; + System.out.println("= " + e); + CUP$parser$result = new java_cup.runtime.Symbol(4/*NT$0*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 2: // expr_list ::= expr_part + { + Object RESULT = null; + + CUP$parser$result = new java_cup.runtime.Symbol(1/*expr_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 1: // $START ::= expr_list EOF + { + Object RESULT = null; + int start_valleft = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left; + int start_valright = ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).right; + Object start_val = (Object)((java_cup.runtime.Symbol) CUP$parser$stack.elementAt(CUP$parser$top-1)).value; + RESULT = start_val; + CUP$parser$result = new java_cup.runtime.Symbol(0/*$START*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + /* ACCEPT */ + CUP$parser$parser.done_parsing(); + return CUP$parser$result; + + /*. . . . . . . . . . . . . . . . . . . .*/ + case 0: // expr_list ::= expr_list expr_part + { + Object RESULT = null; + + CUP$parser$result = new java_cup.runtime.Symbol(1/*expr_list*/, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-1)).left, ((java_cup.runtime.Symbol)CUP$parser$stack.elementAt(CUP$parser$top-0)).right, RESULT); + } + return CUP$parser$result; + + /* . . . . . .*/ + default: + throw new Exception( + "Invalid action number found in internal parse table"); + + } + } +} + diff --git a/Robust/cup/java_cup/simple_calc/scanner.class b/Robust/cup/java_cup/simple_calc/scanner.class new file mode 100644 index 00000000..b24ff03b Binary files /dev/null and b/Robust/cup/java_cup/simple_calc/scanner.class differ diff --git a/Robust/cup/java_cup/simple_calc/scanner.java b/Robust/cup/java_cup/simple_calc/scanner.java new file mode 100644 index 00000000..f8f850ac --- /dev/null +++ b/Robust/cup/java_cup/simple_calc/scanner.java @@ -0,0 +1,63 @@ +// Simple Example Scanner Class + +package java_cup.simple_calc; + +import java_cup.runtime.Symbol; + +public class scanner implements java_cup.runtime.Scanner { + final java.io.InputStream instream; + + public scanner(java.io.InputStream is) throws java.io.IOException { + instream = is; + } + public scanner() throws java.io.IOException { this(System.in); } + + /* single lookahead character */ + protected int next_char = -2; + + /* advance input by one character */ + protected void advance() + throws java.io.IOException + { next_char = instream.read(); } + + /* initialize the scanner */ + private void init() + throws java.io.IOException + { advance(); } + + /* recognize and return the next complete token */ + public Symbol next_token() + throws java.io.IOException + { + if (next_char==-2) init(); // set stuff up first time we are called. + for (;;) + switch (next_char) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + /* parse a decimal integer */ + int i_val = 0; + do { + i_val = i_val * 10 + (next_char - '0'); + advance(); + } while (next_char >= '0' && next_char <= '9'); + return new Symbol(sym.NUMBER, new Integer(i_val)); + + case ';': advance(); return new Symbol(sym.SEMI); + case '+': advance(); return new Symbol(sym.PLUS); + case '-': advance(); return new Symbol(sym.MINUS); + case '*': advance(); return new Symbol(sym.TIMES); + case '/': advance(); return new Symbol(sym.DIVIDE); + case '%': advance(); return new Symbol(sym.MOD); + case '(': advance(); return new Symbol(sym.LPAREN); + case ')': advance(); return new Symbol(sym.RPAREN); + + case -1: return new Symbol(sym.EOF); + + default: + /* in this simple scanner we just ignore everything else */ + advance(); + break; + } + } +}; diff --git a/Robust/cup/java_cup/simple_calc/sym.class b/Robust/cup/java_cup/simple_calc/sym.class new file mode 100644 index 00000000..46aed769 Binary files /dev/null and b/Robust/cup/java_cup/simple_calc/sym.class differ diff --git a/Robust/cup/java_cup/simple_calc/sym.java b/Robust/cup/java_cup/simple_calc/sym.java new file mode 100644 index 00000000..2584f2f0 --- /dev/null +++ b/Robust/cup/java_cup/simple_calc/sym.java @@ -0,0 +1,25 @@ + +//---------------------------------------------------- +// The following code was generated by CUP v0.10k +// Sun Jul 25 13:36:02 EDT 1999 +//---------------------------------------------------- + +package java_cup.simple_calc; + +/** CUP generated class containing symbol constants. */ +public class sym { + /* terminals */ + public static final int SEMI = 2; + public static final int EOF = 0; + public static final int DIVIDE = 6; + public static final int NUMBER = 11; + public static final int error = 1; + public static final int UMINUS = 8; + public static final int MINUS = 4; + public static final int TIMES = 5; + public static final int LPAREN = 9; + public static final int RPAREN = 10; + public static final int MOD = 7; + public static final int PLUS = 3; +} +