Filewatcher File Search
FTP Search
  
Directory (beta)
  
Content Search (beta)
   
pkg://java_cup-0.10-0.k.1jpp.src.rpm:195092/java_cup_v10k.tar.gz  info  downloads

./ 40750  31676    763           0  6765374656  11001 5ustar  cananiancananianINSTALL100750  31676    763        5276  6746333567  12002 0ustar  cananiancananian#!/bin/csh -f
#
# Cup install and test script
# Scott Hudson 8/31/95
#  
# Last revision 7/3/96 (for v0.10a)
# By Frank Flannery
#
# Last revision 11/16/96 (for v0.10b)
# By Daniel Wang
#
# Updated version number 7/24/99 for 0.10k
# By C. Scott Ananian
echo 
echo "================================"
echo "Installing and testing Cup v0.10k"
echo "================================"
echo

# check for this directory in CLASSPATH 
#
set cwd = `pwd`
set c_path = `printenv CLASSPATH`
if ($c_path !~ "*$cwd*") then
  echo " "
  echo "WARNING:"
  echo "WARNING: The current directory does not appear in your CLASSPATH"
  echo "WARNING: it will be added for this install/test only"
  echo "WARNING:"
  echo " "
  setenv CLASSPATH $cwd':'$c_path
  echo "CLASSPATH now set to " 
  printenv CLASSPATH
endif
  
# change to the demo directory
#
echo " "
echo "changing to simple_calc subdirectory..."
echo "cd java_cup/simple_calc"
cd java_cup/simple_calc 

# remove old copies of parser.java and sym.java
#
echo " "
echo "removing any old copies of parser.java and sym.java..."
echo "rm -f parser.java sym.java"
rm -f parser.java sym.java

# compile java_cup and run it against the demo program
#   the -cs (for "checksource") option here will force the 
#   java_cup and java_cup.runtime source to be compiled prior 
#   to running it.
#
echo " "
echo "compiling java_cup then generating demo program..."
echo "java -cs java_cup.Main < parser.cup"
java -cs java_cup.Main < parser.cup 

# make sure parser.java and sym.java now exist
#
if ( ! -e parser.java) then
  echo " "
  echo "ERROR: for some reason parser.java was not created"
  echo "ERROR: install was not successful"
  exit 1
endif
if ( ! -e sym.java) then
  echo " "
  echo "ERROR: for some reason sym.java was not created"
  echo "ERROR: install was not successful"
  exit 1
endif

# run the demo
#  again, the -cs option will cause compilation of all the parts 
#  of the demo program (including parser.java and sym.java that 
#  should have been generated in the previous step).
#
echo "removing old test results..."
echo "rm -f test_results"
rm -f test_results
echo " "
echo "executing the demo program..."
echo "echo '1*-2+2;' | java -cs java_cup.simple_calc.Main >& test_results"
echo '1*-2+2;' | java -cs java_cup.simple_calc.Main >& test_results

# compare with standard results 
#
set res = `tail -1 test_results`
if ("$res" !~ "= 0") then
  echo "ERROR: test program produced the wrong results"
  echo "ERROR: output was:"
  cat test_results
  echo "ERROR: install was not successful"
  rm -f test_results
  exit 2
endif
  
# all is well
#
rm -f test_results
echo " "
echo "=============================="
echo "Install and test was successful"
echo "=============================="
exit 0
README100640  31676    763        4062  6746333612  11606 0ustar  cananiancananianThis directory contains the CUP v0.10k release in source form.  You should
find the following files and subdirectories in this release:

  README            This file.
  INSTALL.QUICK     Quick installation instruction.
  CHANGELOG         A brief overview of the changes in v0.10k
  java_cup          A subdirectory containing CUP, runtime, and test sources.
  cup_logo.gif      A logo image used by the manual.
  manual.html       A user's manual in HTML format. (OLD)
  INSTALL           A shell script to install and test the system

To get started quickly, read INSTALL.QUICK.  If you are on a Windows
platform, you might want to look in the winnt subdirectory.
For complete installation information, keep reading.

To install the release, copy the contents of this directory (if you
haven't done so already) into a "classes" directory accessible to the
java interpreter (i.e., a directory that is listed in the colon
separated list of directories in your CLASSPATH environment variable).
Note: if you have an older version of the system already accessible
from your CLASSPATH you will want to temporarily remove it to avoid
conflicts.

Once files have been copied to an appropriate location, you should be able to
both compile and test the system by executing the INSTALL shell script
(sorry, but non Unix users are still on their own).  Again, be sure that 
you have placed these sources in a directory listed in your CLASSPATH 
environment variable (or changed your CLASSPATH to include this directory).  

A manual page that explains the operation and use of the system can be found
in manual.html and from the CUP home page mentioned below.

Bug reports regarding the installation 
process or the system as a whole should be sent to
<cananian@alumni.princeton.edu> with "JavaCUP" in the subject.

The CUP home page where the latest information regarding CUP can be found 
(e.g., new releases) is:

  http://www.cs.princeton.edu/~appel/modern/java/CUP/

Enjoy,

Scott Hudson
Graphics, Visualization, and Usability Center 
Georgia Institute of Technology
	 
Last updated: 23-Jul-1999 [CSA]
cup_logo.gif100640  31676    763       17566  6746333325  13262 0ustar  cananiancananianGIF89a̻wwwfffUUUDDD333""",pI8ͻ$A q I-rq噮3-D,Ȥrl:Шt3	;_tn|$Cv&xz[g~5tu%Vd<035cY=|	EW(e/^|pU<?2Ǻ]"{/?įY
-q;}A*҄HA#n0KV/2V3jn\H]ȲHLbϐδbϟ@,p.e"zh8+JJNN$Zt
)p@A
@Ԃ."p@ջxIe{=?X.X81P@@G@1xe4hϵxIM6mr^\ Q$^` a\(m }0WvnͲTKH°	fFLN3~Y'8@=`Wu(-80Xh{4v5ptYӜu>7	͍8؍4$}Jo=iC
EeEcWEP@XLbI!p@$#'qix.cwIdBeu-ȒGPt=dgƥ""bXew!]Le}!e|.ĺ6
M(.$^X)]bC7y#t*'V7t)xu9iDB'a(:{htvN@da"JA kbabe6Aggit@TňY)Frw]mР$bz!Xbsg1"cIT)-5E!ҔXDzmLrbJ†ea%`2iy\Qf`>ۡ-A&z 0Dsv<_g-<y. &)Q'?I&0"o[GNpe`cmSiRaB
N%-Ag}-b5wZI'3e38Dj`hFQ9bB\Ug[*;OOZAGyN%Nea.F1Le1
oHݰ4Ub$c2=OL\f"U,Zb(pad.TCars遃ZS9^I3@VqC܀b=8W|#rħe):HLM4eDOT
MXhX&vb2sTJ!pf%L4;=:j 
A&,BHV.!FT\Z2oSk_.p%&JPTeY@01R:K^"R@Q㓛)fg+
n*SX@-D2jrިń2GNSoq(ď.'.9M(sokS2R싍F{xƞUxS=,}&#q;3
Gu#i*Aԅا,eW]UV9UY\[ZD4gA%#&
Lck24(~2[>Unf{C&7Xgl~`|lt8Wmp4dDݙ᱒IJB+)dsUIdp;ŀ:İ>D}G
ǥ&UnsLDW^봙\K!ѭ"`L)kd"}Lwc겢R^]LS2;efDU(R|m

ޢ•k*E:Zfe0r6Ԗ4m-l`SUiF)y7&oj'XBOX
0NkZXi3bë>8,)f|"!ǃ)@
rӡІq"n"YJш<,81нXMx]J+(lYJ0Z
Ͻڀ~„ؚf>S]rM`y̡2#K͔B;8P#5-c,B܍=SK.Re0)R/ۍvSka, NE$ԇ7q@d;b
LL"[	(Х,+WF
wA@1
x[g|- gBQoK;7
Dk
gK>'_ U-BaQŠn
Օozs>̐JBg+#:gzO|$ض0UMp:t1"Siؽww%F%<Pq`y{)U(,j
9t{0F=ٯptIJC>	VKJ$S+X|.BR]~}=q~H8MVV8^xG5z	5.)H3.!86(ٓI*]P@G.KdX+pR%b0Ri`N"tmt 
PCM0;a'HPAM)i)}pT6
hxm4P
gEWq@!E0obz\dxDc/MrV.wx`8	߀j;
XC~uEZzV)2$!>e!C"c!&i!ww9b(5$/MzOv%o3#Q'xԠ11P1A"e#gs*6|>sO\8|Dž?(.a(Sƈ	  :#8B3sg.NPTGc"~>jdP
gSe9akQ)H(u9	P9H[@/s8ՈpW(}J0/65Mq>""a>jd"IG7K(ك:xT!'"9(p	9^)[GW
9jGDXƵ2mcVKRWDdTZ+Qg~uÀ7V$Ϩ瘊	#|\y$n3n^X
SgEԊ4ATK("MJldkAtp|S([žLqylp'~7f)0V
1Kg3˜NQ06N:vL;CSY4 1&DA)j:hO
&nC
gA4fk"qe&PV\J.칛+jqUWh:*!*CƑr0l.&_:m;)3mP!EZ00tᢲ9+v|cYIZJPԹަI1VoD;
9C0F>\;a1hP0 c+hE|ܕǫȤ=y'W8.1x5	>̊vZj9S&}ZCη:X:]5e
tZ4)9`d!"y!$Zez'LiƬHp+w:I.VBeE`)Hgo~J.䳯zve?mJ
@b:n@vTm+(z1*]9I~u(6˱`oPsJkmsHjxz|۷~*LZuaK;|Yh۴4`Q됊cW蟖	<vS[[{K
# H:!if=<Ĺ`\q
Yukmc+[i.G8;;B{[hQǢ@[+ɫK++[Xv6RJtoQC[KLRtpQ˃k| R;q|lc\ZXp#<>T\y:x¶	S !r#C\56\w;2Ҝ`ګwQZRi)C&p#*B4lv,;]X/qH|R	>hl
:ܿL;~õ{YwlrGbuAik',a|ńxt <MW{|5L1G"WX'l,<3,Mx#|*l
<$Az˸l,pY'ˬۋyz~,.PY/ETl'}ܬ؜O
83*bܗzϬ0Ϊ ɧ"mP\HU!۱dXеO%ZNLjl
0΃9ύ!r\N5J[1vu%+a;,}6-ZŒ1j4n3h|4
җRdcMP-̼Y'P1|!\GpWC⢞`_YЪLm-
-
zx[q1Z#!z'=7XD<	eٗzԌ5mEPZˬ~97ٶM._;F)9l=Uc%sMB
Ƹܵ=;]
Tū"m\FFyߜ
nA^(/
 j
.>Rf
~'qt8B}pίp7N]']:*N,*]SK:jڟn䄵"
\aäm,SmgE5-b+g>-<qsaq.,R-Ԉ|4UkCN5M
n9b9.֞-.>J5Q~γб"&o@Nִܶ~Y&hI)d.Pp\:77pK{>텞ZkM5r.툾clCX$)--n
Mon?5á|[m	wr5];c
7!/	%ڑM(/4Oܿ=$C4.5BPӽH⃸.߲GON1yx۳W/	gQ`Myy
@I&^m߱rLx蒟u\
79{ooJ(qw'yӒr?wC_)@ZD>ޑŮZ2vP?	3=x
']?	pW.r`\&lpb[?E 
5P0]0{c2S{Dg@%ZP8$GdRd	%D+fV2ZE"C,\vp^ @!68K3I#5%.O;<VW@;;+"RJcdHBE$SZHmn\+o
8᭕q:PUc!6,@dPZ7:^\x	^ 680`t3`hæ`O4tpē"aIRA,bWQ`z F̠i>:b	2!QIQXկU(EM&sk/nhfW00Wr<	U¡1…K
Za57+6cx`'ʖPPZXM왊zIAn5_ONJٶl(`FMFe	x!oNoNZۻxguMmAc'
8x!h*$Jf#(^`>:	-ڪp	&h:p@P1NŽA0NOo2cF1<0,CLb|2|;!t3`qS#"9:؀&20R7#Ɛ~\
>yG%<fTuUV[Ic4ܸBM%,RF5B.h%8duY@[*%,դC6RQpwETsT`e]x@_,T4lCyK_x`6`wUX;	 ;7^+^=VhrudKV%?L}P[آ;Gk?1
geU>Zئ5L0o1H-j-/:Le6lV{mna\/&'bLfuo|p'obnyP#N|\arг$nK6CW=VtQ{k	/ }cvtދoZwe]y#ճw1~R=e~
t:{%
qcϾӗM2n+y1m??["`
x@&\M	aa%`zI@"`HvQf%Ђ$JXꂰ@X3TT7ZM;a}O@#1L 
pI
%pBдaE
BJ().rIpF8⦴!)TL	r1h)a1a3X@;@whp"(@J~<e ]y1NPi$IyJF¿N ɂ
ãkԵfe"0F`E䈉\ycY5]pъ@AHw@F)O
zA(OE'@^b$yE	&v;' r	@;
4`Rb1vAF;V
NݢJ9FaM<'	x[dgAR9Ar0$IUNh3HaCߙx.JbED9Qp3kŝhН;R(;gSRBO \t)~ 0'"axU*RI`ZOB1f=e%¶!\|p+Md`iN2&~Ť>qVH	 Z%nCctSd'?IYRڌNt.lC,2@2X[JdDAO&'=qH!y"	xy1pghaNNlG0	[᫿̪0fAr%S-k?*'GT.aŶ
Ej,fpQbO8=<*z`O^)k*8Myo%,FxR"H,JG0S(}bxYHV+͹cc'kiOB!fvpk;`
`eBt%`r75	JMGRb
4ddLn

,˓W2,&AM Ȱ%?k|4`6&ZT{tCGI3دb8X*!.k07"ocvW%tpZ(1q!r cov3ֽg\|!7q\#'yO!MACGCon 1Written by GIFConverter 2.3.7 of Jan 29, 1994;java_cup/ 40750  31676    763           0  6763606050  12414 5ustar  cananiancananianjava_cup/Main.java100640  31676    763       74030  6746336313  14270 0ustar  cananiancananian
package java_cup;

import java.util.Enumeration; 
import java.io.*;

/** This class serves as the main driver for the JavaCup system.
 *  It accepts user options and coordinates overall control flow.
 *  The main flow of control includes the following activities: 
 *  <ul>
 *    <li> Parse user supplied arguments and options.
 *    <li> Open output files.
 *    <li> Parse the specification from standard input.
 *    <li> Check for unused terminals, non-terminals, and productions.
 *    <li> Build the state machine, tables, etc.
 *    <li> Output the generated code.
 *    <li> Close output files.
 *    <li> Print a summary if requested.
 *  </ul>
 *
 *  Options to the main program include: <dl>
 *   <dt> -package name  
 *   <dd> specify package generated classes go in [default none]
 *   <dt> -parser name   
 *   <dd> specify parser class name [default "parser"]
 *   <dt> -symbols name  
 *   <dd> specify name for symbol constant class [default "sym"]
 *   <dt> -interface
 *   <dd> emit symbol constant <i>interface</i>, rather than class
 *   <dt> -nonterms      
 *   <dd> put non terminals in symbol constant class
 *   <dt> -expect #      
 *   <dd> number of conflicts expected/allowed [default 0]
 *   <dt> -compact_red   
 *   <dd> compact tables by defaulting to most frequent reduce
 *   <dt> -nowarn        
 *   <dd> don't warn about useless productions, etc.
 *   <dt> -nosummary     
 *   <dd> don't print the usual summary of parse states, etc.
 *   <dt> -progress      
 *   <dd> print messages to indicate progress of the system
 *   <dt> -time          
 *   <dd> print time usage summary
 *   <dt> -dump_grammar  
 *   <dd> produce a dump of the symbols and grammar
 *   <dt> -dump_states   
 *   <dd> produce a dump of parse state machine
 *   <dt> -dump_tables   
 *   <dd> produce a dump of the parse tables
 *   <dt> -dump          
 *   <dd> produce a dump of all of the above
 *   <dt> -debug         
 *   <dd> turn on debugging messages within JavaCup 
 *   <dt> -nopositions
 *   <dd> don't generate the positions code
 *   <dt> -noscanner
 *   <dd> don't refer to java_cup.runtime.Scanner in the parser
 *        (for compatibility with old runtimes)
 *   <dt> -version
 *   <dd> print version information for JavaCUP and halt.
 *   </dl>
 *
 * @version last updated: 7/3/96
 * @author  Frank Flannery
 */

public class Main {

  /*-----------------------------------------------------------*/
  /*--- Constructor(s) ----------------------------------------*/
  /*-----------------------------------------------------------*/
  /** Only constructor is private, so we do not allocate any instances of this
      class. */
  private Main() { }

  /*-------------------------*/
  /* Options set by the user */
  /*-------------------------*/
  /** User option -- do we print progress messages. */
  protected static boolean print_progress   = true;
  /** User option -- do we produce a dump of the state machine */
  protected static boolean opt_dump_states  = false;
  /** User option -- do we produce a dump of the parse tables */
  protected static boolean opt_dump_tables  = false;
  /** User option -- do we produce a dump of the grammar */
  protected static boolean opt_dump_grammar = false;
  /** User option -- do we show timing information as a part of the summary */
  protected static boolean opt_show_timing  = false;
  /** User option -- do we run produce extra debugging messages */
  protected static boolean opt_do_debug     = false;
  /** User option -- do we compact tables by making most common reduce the 
      default action */
  protected static boolean opt_compact_red  = false;
  /** User option -- should we include non terminal symbol numbers in the 
      symbol constant class. */
  protected static boolean include_non_terms = false;
  /** User option -- do not print a summary. */
  protected static boolean no_summary = false;
  /** User option -- number of conflicts to expect */
  protected static int expect_conflicts = 0;

  /* frankf added this 6/18/96 */
  /** User option -- should generator generate code for left/right values? */
  protected static boolean lr_values = true;

  /** User option -- should symbols be put in a class or an interface? [CSA]*/
  protected static boolean sym_interface = false;

  /** User option -- should generator suppress references to
   *  java_cup.runtime.Scanner for compatibility with old runtimes? */
  protected static boolean suppress_scanner = false;

  /*----------------------------------------------------------------------*/
  /* Timing data (not all of these time intervals are mutually exclusive) */
  /*----------------------------------------------------------------------*/
  /** Timing data -- when did we start */
  protected static long start_time       = 0;
  /** Timing data -- when did we end preliminaries */
  protected static long prelim_end       = 0;
  /** Timing data -- when did we end parsing */
  protected static long parse_end        = 0;
  /** Timing data -- when did we end checking */
  protected static long check_end        = 0;
  /** Timing data -- when did we end dumping */
  protected static long dump_end         = 0;
  /** Timing data -- when did we end state and table building */
  protected static long build_end        = 0;
  /** Timing data -- when did we end nullability calculation */
  protected static long nullability_end  = 0;
  /** Timing data -- when did we end first set calculation */
  protected static long first_end        = 0;
  /** Timing data -- when did we end state machine construction */
  protected static long machine_end      = 0;
  /** Timing data -- when did we end table construction */
  protected static long table_end        = 0;
  /** Timing data -- when did we end checking for non-reduced productions */
  protected static long reduce_check_end = 0;
  /** Timing data -- when did we finish emitting code */
  protected static long emit_end         = 0;
  /** Timing data -- when were we completely done */
  protected static long final_time       = 0;

  /* Additional timing information is also collected in emit */

  /*-----------------------------------------------------------*/
  /*--- Main Program ------------------------------------------*/
  /*-----------------------------------------------------------*/

  /** The main driver for the system. 
   * @param argv an array of strings containing command line arguments.
   */
  public static void main(String argv[]) 
    throws internal_error, java.io.IOException, java.lang.Exception
    {
      boolean did_output = false;

      start_time = System.currentTimeMillis();

      /* process user options and arguments */
      parse_args(argv);

      /* frankf 6/18/96
	 hackish, yes, but works */
      emit.set_lr_values(lr_values);
      /* open output files */
      if (print_progress) System.err.println("Opening files...");
      /* use a buffered version of standard input */
      input_file = new BufferedInputStream(System.in);

      prelim_end = System.currentTimeMillis();

      /* parse spec into internal data structures */
      if (print_progress) 
	System.err.println("Parsing specification from standard input...");
      parse_grammar_spec();

      parse_end = System.currentTimeMillis();

      /* don't proceed unless we are error free */
      if (lexer.error_count == 0)
	{
	  /* check for unused bits */
          if (print_progress) System.err.println("Checking specification...");
          check_unused();

          check_end = System.currentTimeMillis();

	  /* build the state machine and parse tables */
          if (print_progress) System.err.println("Building parse tables...");
          build_parser();

          build_end = System.currentTimeMillis();

	  /* output the generated code, if # of conflicts permits */
	  if (lexer.error_count != 0) {
	      // conflicts! don't emit code, don't dump tables.
	      opt_dump_tables = false;
	  } else { // everything's okay, emit parser.
	      if (print_progress) System.err.println("Writing parser...");
	      open_files();
	      emit_parser();
	      did_output = true;
	  }
	}
      /* fix up the times to make the summary easier */
      emit_end = System.currentTimeMillis();

      /* do requested dumps */
      if (opt_dump_grammar) dump_grammar();
      if (opt_dump_states)  dump_machine(); 
      if (opt_dump_tables)  dump_tables(); 

      dump_end = System.currentTimeMillis();

      /* close input/output files */
      if (print_progress) System.err.println("Closing files...");
      close_files();

      /* produce a summary if desired */
      if (!no_summary) emit_summary(did_output);

      /* If there were errors during the run,
       * exit with non-zero status (makefile-friendliness). --CSA */
      if (lexer.error_count != 0)
	  System.exit(100);
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Print a "usage message" that described possible command line options, 
   *  then exit.
   * @param message a specific error message to preface the usage message by.
   */
  protected static void usage(String message)
    {
      System.err.println();
      System.err.println(message);
      System.err.println();
      System.err.println(
"Usage: " + version.program_name + " [options] [filename]\n" +
"  and expects a specification file on standard input if no filename is given.\n" +
"  Legal options include:\n" +
"    -package name  specify package generated classes go in [default none]\n" +
"    -parser name   specify parser class name [default \"parser\"]\n" +
"    -symbols name  specify name for symbol constant class [default \"sym\"]\n"+
"    -interface     put symbols in an interface, rather than a class\n" +
"    -nonterms      put non terminals in symbol constant class\n" + 
"    -expect #      number of conflicts expected/allowed [default 0]\n" + 
"    -compact_red   compact tables by defaulting to most frequent reduce\n" +
"    -nowarn        don't warn about useless productions, etc.\n" +
"    -nosummary     don't print the usual summary of parse states, etc.\n" +
"    -nopositions   don't propagate the left and right token position values\n" +
"    -noscanner     don't refer to java_cup.runtime.Scanner\n" +
"    -progress      print messages to indicate progress of the system\n" +
"    -time          print time usage summary\n" +
"    -dump_grammar  produce a human readable dump of the symbols and grammar\n"+
"    -dump_states   produce a dump of parse state machine\n"+
"    -dump_tables   produce a dump of the parse tables\n"+
"    -dump          produce a dump of all of the above\n"+
"    -version       print the version information for CUP and exit\n"
      );
      System.exit(1);
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Parse command line options and arguments to set various user-option
   *  flags and variables. 
   * @param argv the command line arguments to be parsed.
   */
  protected static void parse_args(String argv[])
    {
      int len = argv.length;
      int i;

      /* parse the options */
      for (i=0; i<len; i++)
	{
	  /* try to get the various options */
	  if (argv[i].equals("-package"))
	    {
	      /* must have an arg */
	      if (++i >= len || argv[i].startsWith("-") || 
				argv[i].endsWith(".cup")) 
		usage("-package must have a name argument");

	      /* record the name */
	      emit.package_name = argv[i];
	    }
	  else if (argv[i].equals("-parser"))
	    {
	      /* must have an arg */
	      if (++i >= len || argv[i].startsWith("-") || 
				argv[i].endsWith(".cup")) 
		usage("-parser must have a name argument");

	      /* record the name */
	      emit.parser_class_name = argv[i];
	    }
	  else if (argv[i].equals("-symbols"))
	    {
	      /* must have an arg */
	      if (++i >= len || argv[i].startsWith("-") || 
				argv[i].endsWith(".cup")) 
		usage("-symbols must have a name argument");

	      /* record the name */
	      emit.symbol_const_class_name = argv[i];
	    }
	  else if (argv[i].equals("-nonterms"))
	    {
	      include_non_terms = true;
	    }
	  else if (argv[i].equals("-expect"))
	    {
	      /* must have an arg */
	      if (++i >= len || argv[i].startsWith("-") || 
				argv[i].endsWith(".cup")) 
		usage("-expect must have a name argument");

	      /* record the number */
	      try {
	        expect_conflicts = Integer.parseInt(argv[i]);
	      } catch (NumberFormatException e) {
		usage("-expect must be followed by a decimal integer");
	      }
	    }
	  else if (argv[i].equals("-compact_red"))  opt_compact_red = true;
	  else if (argv[i].equals("-nosummary"))    no_summary = true;
	  else if (argv[i].equals("-nowarn"))       emit.nowarn = true;
	  else if (argv[i].equals("-dump_states"))  opt_dump_states = true;
	  else if (argv[i].equals("-dump_tables"))  opt_dump_tables = true; 
	  else if (argv[i].equals("-progress"))     print_progress = true;
	  else if (argv[i].equals("-dump_grammar")) opt_dump_grammar = true;
	  else if (argv[i].equals("-dump")) 
	        opt_dump_states = opt_dump_tables = opt_dump_grammar = true; 
	  else if (argv[i].equals("-time"))         opt_show_timing = true; 
	  else if (argv[i].equals("-debug"))        opt_do_debug = true;
	  /* frankf 6/18/96 */
	  else if (argv[i].equals("-nopositions"))  lr_values = false;
	  /* CSA 12/21/97 */
	  else if (argv[i].equals("-interface"))    sym_interface = true;
	  /* CSA 23-Jul-1999 */
	  else if (argv[i].equals("-noscanner"))    suppress_scanner = true;
	  /* CSA 23-Jul-1999 */
	  else if (argv[i].equals("-version")) {
	      System.out.println(version.title_str);
	      System.exit(1);
	  }
	  /* CSA 24-Jul-1999; suggestion by Jean Vaucher */
	  else if (!argv[i].startsWith("-") && i==len-1) {
	      /* use input from file. */
	      try {
		  System.setIn(new FileInputStream(argv[i]));
	      } catch (java.io.FileNotFoundException e) {
		  usage("Unable to open \"" + argv[i] +"\" for input");
	      }
	  }
	  else
	    {
	      usage("Unrecognized option \"" + argv[i] + "\"");
	    }
	}
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /*-------*/
  /* Files */
  /*-------*/

  /** Input file.  This is a buffered version of System.in. */
  protected static BufferedInputStream input_file;

  /** Output file for the parser class. */
  protected static PrintWriter parser_class_file;

  /** Output file for the symbol constant class. */
  protected static PrintWriter symbol_class_file;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Open various files used by the system. */
  protected static void open_files()
    {
      File fil;
      String out_name;

      /* open each of the output files */

      /* parser class */
      out_name = emit.parser_class_name + ".java";
      fil = new File(out_name);
      try {
        parser_class_file = new PrintWriter(
		 new BufferedOutputStream(new FileOutputStream(fil), 4096));
      } catch(Exception e) {
	System.err.println("Can't open \"" + out_name + "\" for output");
	System.exit(3);
      }

      /* symbol constants class */
      out_name = emit.symbol_const_class_name + ".java";
      fil = new File(out_name);
      try {
        symbol_class_file = new PrintWriter(
		 new BufferedOutputStream(new FileOutputStream(fil), 4096));
      } catch(Exception e) {
	System.err.println("Can't open \"" + out_name + "\" for output");
	System.exit(4);
      }
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Close various files used by the system. */
  protected static void close_files() throws java.io.IOException
    {
      if (input_file != null) input_file.close();
      if (parser_class_file != null) parser_class_file.close();
      if (symbol_class_file != null) symbol_class_file.close();
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Parse the grammar specification from standard input.  This produces
   *  sets of terminal, non-terminals, and productions which can be accessed
   *  via static variables of the respective classes, as well as the setting
   *  of various variables (mostly in the emit class) for small user supplied
   *  items such as the code to scan with.
   */
  protected static void parse_grammar_spec() throws java.lang.Exception
    {
      parser parser_obj;

      /* create a parser and parse with it */
      parser_obj = new parser();
      try {
	if (opt_do_debug)
          parser_obj.debug_parse();
	else
          parser_obj.parse();
      } catch (Exception e)
      {
	/* something threw an exception.  catch it and emit a message so we 
	   have a line number to work with, then re-throw it */
	lexer.emit_error("Internal error: Unexpected exception");
	throw e;
      }
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Check for unused symbols.  Unreduced productions get checked when
   *  tables are created.
   */
  protected static void check_unused()
    {
      terminal term;
      non_terminal nt;

      /* check for unused terminals */
      for (Enumeration t = terminal.all(); t.hasMoreElements(); )
	{
	  term = (terminal)t.nextElement();

	  /* don't issue a message for EOF */
	  if (term == terminal.EOF) continue;

	  /* or error */
	  if (term == terminal.error) continue;

	  /* is this one unused */
	  if (term.use_count() == 0)
	    {
	      /* count it and warn if we are doing warnings */
	      emit.unused_term++;
	      if (!emit.nowarn) 
		{
		  System.err.println("Warning: Terminal \"" + term.name() + 
				     "\" was declared but never used");
		  lexer.warning_count++;
		}
	    }
	}

      /* check for unused non terminals */
      for (Enumeration n = non_terminal.all(); n.hasMoreElements(); )
	{
	  nt = (non_terminal)n.nextElement();

	  /* is this one unused */
	  if (nt.use_count() == 0)
	    {
	      /* count and warn if we are doing warnings */
	      emit.unused_term++;
	      if (!emit.nowarn) 
		{
		  System.err.println("Warning: Non terminal \"" + nt.name() + 
				     "\" was declared but never used");
		  lexer.warning_count++;
		}
	    }
	}

    }

  /* . . . . . . . . . . . . . . . . . . . . . . . . .*/
  /* . . Internal Results of Generating the Parser . .*/
  /* . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Start state in the overall state machine. */
  protected static lalr_state start_state;

  /** Resulting parse action table. */
  protected static parse_action_table action_table;

  /** Resulting reduce-goto table. */
  protected static parse_reduce_table reduce_table;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Build the (internal) parser from the previously parsed specification.
   *  This includes:<ul>
   *    <li> Computing nullability of non-terminals.
   *    <li> Computing first sets of non-terminals and productions.
   *    <li> Building the viable prefix recognizer machine.
   *    <li> Filling in the (internal) parse tables.
   *    <li> Checking for unreduced productions.
   *  </ul>
   */
  protected static void build_parser() throws internal_error
    {
      /* compute nullability of all non terminals */
      if (opt_do_debug || print_progress) 
	System.err.println("  Computing non-terminal nullability...");
      non_terminal.compute_nullability();

      nullability_end = System.currentTimeMillis();

      /* compute first sets of all non terminals */
      if (opt_do_debug || print_progress) 
	System.err.println("  Computing first sets...");
      non_terminal.compute_first_sets();

      first_end = System.currentTimeMillis();

      /* build the LR viable prefix recognition machine */
      if (opt_do_debug || print_progress) 
	System.err.println("  Building state machine...");
      start_state = lalr_state.build_machine(emit.start_production);

      machine_end = System.currentTimeMillis();

      /* build the LR parser action and reduce-goto tables */
      if (opt_do_debug || print_progress) 
	System.err.println("  Filling in tables...");
      action_table = new parse_action_table();
      reduce_table = new parse_reduce_table();
      for (Enumeration st = lalr_state.all(); st.hasMoreElements(); )
	{
	  lalr_state lst = (lalr_state)st.nextElement();
	  lst.build_table_entries(
			                      action_table, reduce_table);
	}

      table_end = System.currentTimeMillis();

      /* check and warn for non-reduced productions */
      if (opt_do_debug || print_progress) 
	System.err.println("  Checking for non-reduced productions...");
      action_table.check_reductions();

      reduce_check_end = System.currentTimeMillis();

      /* if we have more conflicts than we expected issue a message and die */
      if (emit.num_conflicts > expect_conflicts)
	{
	  System.err.println("*** More conflicts encountered than expected " +
			     "-- parser generation aborted");
	  lexer.error_count++; // indicate the problem.
	  // we'll die on return, after clean up.
	}
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Call the emit routines necessary to write out the generated parser. */
  protected static void emit_parser() throws internal_error
    {
      emit.symbols(symbol_class_file, include_non_terms, sym_interface);
      emit.parser(parser_class_file, action_table, reduce_table, 
		  start_state.index(), emit.start_production, opt_compact_red,
		  suppress_scanner);
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Helper routine to optionally return a plural or non-plural ending. 
   * @param val the numerical value determining plurality.
   */
  protected static String plural(int val)
    {
      if (val == 1)
	return "";
      else
	return "s";
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Emit a long summary message to standard error (System.err) which 
   *  summarizes what was found in the specification, how many states were
   *  produced, how many conflicts were found, etc.  A detailed timing 
   *  summary is also produced if it was requested by the user.
   * @param output_produced did the system get far enough to generate code.
   */
  protected static void emit_summary(boolean output_produced)
    {
      final_time = System.currentTimeMillis();

      if (no_summary) return;

      System.err.println("------- " + version.title_str + 
			 " Parser Generation Summary -------");

      /* error and warning count */
      System.err.println("  " + lexer.error_count + " error" + 
	 plural(lexer.error_count) + " and " + lexer.warning_count + 
	 " warning" + plural(lexer.warning_count));

      /* basic stats */
      System.err.print("  " + terminal.number() + " terminal" + 
			 plural(terminal.number()) + ", ");
      System.err.print(non_terminal.number() + " non-terminal" + 
			 plural(non_terminal.number()) + ", and ");
      System.err.println(production.number() + " production" + 
			 plural(production.number()) + " declared, ");
      System.err.println("  producing " + lalr_state.number() + 
			 " unique parse states.");

      /* unused symbols */
      System.err.println("  " + emit.unused_term + " terminal" + 
			 plural(emit.unused_term) + " declared but not used.");
      System.err.println("  " + emit.unused_non_term + " non-terminal" + 
			 plural(emit.unused_term) + " declared but not used.");

      /* productions that didn't reduce */
      System.err.println("  " + emit.not_reduced + " production" + 
			 plural(emit.not_reduced) + " never reduced.");

      /* conflicts */
      System.err.println("  " + emit.num_conflicts + " conflict" +
			 plural(emit.num_conflicts) + " detected" +
	                 " (" + expect_conflicts + " expected).");

      /* code location */
      if (output_produced)
	System.err.println("  Code written to \"" + emit.parser_class_name + 
	        ".java\", and \"" + emit.symbol_const_class_name + ".java\".");
      else
	System.err.println("  No code produced.");

      if (opt_show_timing) show_times();

      System.err.println(
	"---------------------------------------------------- (" + 
	 version.version_str + ")");
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Produce the optional timing summary as part of an overall summary. */
  protected static void show_times()
    {
      long total_time = final_time - start_time;

      System.err.println(". . . . . . . . . . . . . . . . . . . . . . . . . ");
      System.err.println("  Timing Summary");
      System.err.println("    Total time       "
        + timestr(final_time-start_time, total_time));
      System.err.println("      Startup        "
	+ timestr(prelim_end-start_time, total_time));
      System.err.println("      Parse          "
	+ timestr(parse_end-prelim_end, total_time) );
      if (check_end != 0)
        System.err.println("      Checking       "
	    + timestr(check_end-parse_end, total_time));
      if (check_end != 0 && build_end != 0)
        System.err.println("      Parser Build   "
	    + timestr(build_end-check_end, total_time));
      if (nullability_end != 0 && check_end != 0)
        System.err.println("        Nullability  "
	    + timestr(nullability_end-check_end, total_time));
      if (first_end != 0 && nullability_end != 0)
        System.err.println("        First sets   "
            + timestr(first_end-nullability_end, total_time));
      if (machine_end != 0 && first_end != 0)
        System.err.println("        State build  " 
	    + timestr(machine_end-first_end, total_time)); 
      if (table_end != 0 && machine_end != 0)
        System.err.println("        Table build  " 
	    + timestr(table_end-machine_end, total_time)); 
      if (reduce_check_end != 0 && table_end != 0)
        System.err.println("        Checking     " 
	    + timestr(reduce_check_end-table_end, total_time));
      if (emit_end != 0 && build_end != 0)
        System.err.println("      Code Output    "
	    + timestr(emit_end-build_end, total_time));
      if (emit.symbols_time != 0)
	System.err.println("        Symbols      "
	    + timestr(emit.symbols_time, total_time));
      if (emit.parser_time != 0)
	System.err.println("        Parser class "
	    + timestr(emit.parser_time, total_time));
      if (emit.action_code_time != 0)
	System.err.println("          Actions    "
	    + timestr(emit.action_code_time, total_time));
      if (emit.production_table_time != 0)
	System.err.println("          Prod table "
	    + timestr(emit.production_table_time, total_time));
      if (emit.action_table_time != 0)
	System.err.println("          Action tab "
	    + timestr(emit.action_table_time, total_time));
      if (emit.goto_table_time != 0)
	System.err.println("          Reduce tab "
	    + timestr(emit.goto_table_time, total_time));

      System.err.println("      Dump Output    "
	+ timestr(dump_end-emit_end, total_time));
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Helper routine to format a decimal based display of seconds and
   *  percentage of total time given counts of milliseconds.   Note: this
   *  is broken for use with some instances of negative time (since we don't 
   *  use any negative time here, we let if be for now).
   * @param time_val   the value being formatted (in ms).
   * @param total_time total time percentages are calculated against (in ms).
   */
  protected static String timestr(long time_val, long total_time)
    {
      boolean neg;
      long    ms = 0;
      long    sec = 0;
      long    percent10;
      String  pad;

      /* work with positives only */
      neg = time_val < 0;
      if (neg) time_val = -time_val;

      /* pull out seconds and ms */
      ms = time_val % 1000;
      sec = time_val / 1000;

      /* construct a pad to blank fill seconds out to 4 places */
      if (sec < 10)   
	pad = "   ";
      else if (sec < 100)  
	pad = "  ";
      else if (sec < 1000) 
	pad = " ";
      else
	pad = "";

      /* calculate 10 times the percentage of total */
      percent10 = (time_val*1000)/total_time;

      /* build and return the output string */
      return (neg ? "-" : "") + pad + sec + "." + 
	     ((ms%1000)/100) + ((ms%100)/10) + (ms%10) + "sec" +
	     " (" + percent10/10 + "." + percent10%10 + "%)";
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Produce a human readable dump of the grammar. */
  public static void dump_grammar() throws internal_error
    {
      System.err.println("===== Terminals =====");
      for (int tidx=0, cnt=0; tidx < terminal.number(); tidx++, cnt++)
	{
	  System.err.print("["+tidx+"]"+terminal.find(tidx).name()+" ");
	  if ((cnt+1) % 5 == 0) System.err.println();
	}
      System.err.println();
      System.err.println();

      System.err.println("===== Non terminals =====");
      for (int nidx=0, cnt=0; nidx < non_terminal.number(); nidx++, cnt++)
	{
	  System.err.print("["+nidx+"]"+non_terminal.find(nidx).name()+" ");
	  if ((cnt+1) % 5 == 0) System.err.println();
	}
      System.err.println();
      System.err.println();


      System.err.println("===== Productions =====");
      for (int pidx=0; pidx < production.number(); pidx++)
	{
	  production prod = production.find(pidx);
	  System.err.print("["+pidx+"] "+prod.lhs().the_symbol().name() + " ::= ");
	  for (int i=0; i<prod.rhs_length(); i++)
	    if (prod.rhs(i).is_action())
	      System.err.print("{action} ");
	    else
	      System.err.print(
			 ((symbol_part)prod.rhs(i)).the_symbol().name() + " ");
	  System.err.println();
	}
      System.err.println();
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Produce a (semi-) human readable dump of the complete viable prefix 
   *  recognition state machine. 
   */
  public static void dump_machine()
    {
      lalr_state ordered[] = new lalr_state[lalr_state.number()];

      /* put the states in sorted order for a nicer display */
      for (Enumeration s = lalr_state.all(); s.hasMoreElements(); )
	{
	  lalr_state st = (lalr_state)s.nextElement();
	  ordered[st.index()] = st;
	}

      System.err.println("===== Viable Prefix Recognizer =====");
      for (int i = 0; i<lalr_state.number(); i++)
	{
	  if (ordered[i] == start_state) System.err.print("START ");
          System.err.println(ordered[i]);
	  System.err.println("-------------------");
	}
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Produce a (semi-) human readable dumps of the parse tables */
  public static void dump_tables()
    {
      System.err.println(action_table);
      System.err.println(reduce_table);
    }

  /*-----------------------------------------------------------*/

}

java_cup/action_part.java100640  31676    763        5466  6746333325  15676 0ustar  cananiancananian
package java_cup;

/** 
 * This class represents a part of a production which contains an
 * action.  These are eventually eliminated from productions and converted
 * to trailing actions by factoring out with a production that derives the
 * empty string (and ends with this action).
 *
 * @see java_cup.production
 * @version last update: 11/25/95
 * @author Scott Hudson
 */

public class action_part extends production_part {

  /*-----------------------------------------------------------*/
  /*--- Constructors ------------------------------------------*/
  /*-----------------------------------------------------------*/

  /** Simple constructor. 
   * @param code_str string containing the actual user code.
   */
  public action_part(String code_str)
    {
      super(/* never have a label on code */null);
      _code_string = code_str;
    }

  /*-----------------------------------------------------------*/
  /*--- (Access to) Instance Variables ------------------------*/
  /*-----------------------------------------------------------*/

  /** String containing code for the action in question. */
  protected String _code_string;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** String containing code for the action in question. */
  public String code_string() {return _code_string;}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Set the code string. */
  public void set_code_string(String new_str) {_code_string = new_str;}

  /*-----------------------------------------------------------*/
  /*--- General Methods ---------------------------------------*/
  /*-----------------------------------------------------------*/

  /** Override to report this object as an action. */
  public boolean is_action() { return true; }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Equality comparison for properly typed object. */
  public boolean equals(action_part other)
    {
      /* compare the strings */
      return other != null && super.equals(other) && 
	     other.code_string().equals(code_string());
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Generic equality comparison. */
  public boolean equals(Object other)
    {
      if (!(other instanceof action_part)) 
	return false;
      else
	return equals((action_part)other);
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Produce a hash code. */
  public int hashCode()
    {
      return super.hashCode() ^ 
	     (code_string()==null ? 0 : code_string().hashCode());
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Convert to a string.  */
  public String toString()
    {
      return super.toString() + "{" + code_string() + "}";
    }

  /*-----------------------------------------------------------*/
}
java_cup/action_production.java100640  31676    763        2364  6746333325  17110 0ustar  cananiancananian
package java_cup;

/** A specialized version of a production used when we split an existing
 *  production in order to remove an embedded action.  Here we keep a bit 
 *  of extra bookkeeping so that we know where we came from.
 * @version last updated: 11/25/95
 * @author  Scott Hudson
 */

public class action_production extends production {

  /** Constructor.
   * @param base       the production we are being factored out of.
   * @param lhs_sym    the LHS symbol for this production.
   * @param rhs_parts  array of production parts for the RHS.
   * @param rhs_len    how much of the rhs_parts array is valid.
   * @param action_str the trailing reduce action for this production.
   */ 
  public action_production(
    production      base,
    non_terminal    lhs_sym, 
    production_part rhs_parts[],
    int             rhs_len,
    String          action_str)
    throws internal_error
    {
      super(lhs_sym, rhs_parts, rhs_len, action_str);
      _base_production = base;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** The production we were taken out of. */
  protected production _base_production;

  /** The production we were taken out of. */
  public production base_production() {return _base_production;}
}
java_cup/assoc.java100640  31676    763         610  6746333325  14445 0ustar  cananiancananianpackage java_cup;

/* Defines integers that represent the associativity of terminals
 * @version last updated: 7/3/96
 * @author  Frank Flannery
 */

public class assoc {

  /* various associativities, no_prec being the default value */
  public final static int left = 0;
  public final static int right = 1;
  public final static int nonassoc = 2;
  public final static int no_prec = -1;

}java_cup/emit.java100640  31676    763      100036  6746333325  14356 0ustar  cananiancananianpackage java_cup;

import java.io.PrintWriter;
import java.util.Stack;
import java.util.Enumeration;
import java.util.Date;

/** 
 * This class handles emitting generated code for the resulting parser.
 * The various parse tables must be constructed, etc. before calling any 
 * routines in this class.<p>  
 *
 * Three classes are produced by this code:
 *   <dl>
 *   <dt> symbol constant class
 *   <dd>   this contains constant declarations for each terminal (and 
 *          optionally each non-terminal).
 *   <dt> action class
 *   <dd>   this non-public class contains code to invoke all the user actions 
 *          that were embedded in the parser specification.
 *   <dt> parser class
 *   <dd>   the specialized parser class consisting primarily of some user 
 *          supplied general and initialization code, and the parse tables.
 *   </dl><p>
 *
 *  Three parse tables are created as part of the parser class:
 *    <dl>
 *    <dt> production table
 *    <dd>   lists the LHS non terminal number, and the length of the RHS of 
 *           each production.
 *    <dt> action table
 *    <dd>   for each state of the parse machine, gives the action to be taken
 *           (shift, reduce, or error) under each lookahead symbol.<br>
 *    <dt> reduce-goto table
 *    <dd>   when a reduce on a given production is taken, the parse stack is 
 *           popped back a number of elements corresponding to the RHS of the 
 *           production.  This reveals a prior state, which we transition out 
 *           of under the LHS non terminal symbol for the production (as if we
 *           had seen the LHS symbol rather than all the symbols matching the 
 *           RHS).  This table is indexed by non terminal numbers and indicates 
 *           how to make these transitions. 
 *    </dl><p>
 * 
 * In addition to the method interface, this class maintains a series of 
 * public global variables and flags indicating how misc. parts of the code 
 * and other output is to be produced, and counting things such as number of 
 * conflicts detected (see the source code and public variables below for
 * more details).<p> 
 *
 * This class is "static" (contains only static data and methods).<p> 
 *
 * @see java_cup.main
 * @version last update: 11/25/95
 * @author Scott Hudson
 */

/* Major externally callable routines here include:
     symbols               - emit the symbol constant class 
     parser                - emit the parser class

   In addition the following major internal routines are provided:
     emit_package          - emit a package declaration
     emit_action_code      - emit the class containing the user's actions 
     emit_production_table - emit declaration and init for the production table
     do_action_table       - emit declaration and init for the action table
     do_reduce_table       - emit declaration and init for the reduce-goto table

   Finally, this class uses a number of public instance variables to communicate
   optional parameters and flags used to control how code is generated,
   as well as to report counts of various things (such as number of conflicts
   detected).  These include:

   prefix                  - a prefix string used to prefix names that would 
			     otherwise "pollute" someone else's name space.
   package_name            - name of the package emitted code is placed in 
			     (or null for an unnamed package.
   symbol_const_class_name - name of the class containing symbol constants.
   parser_class_name       - name of the class for the resulting parser.
   action_code             - user supplied declarations and other code to be 
			     placed in action class.
   parser_code             - user supplied declarations and other code to be 
			     placed in parser class.
   init_code               - user supplied code to be executed as the parser 
			     is being initialized.
   scan_code               - user supplied code to get the next Symbol.
   start_production        - the start production for the grammar.
   import_list             - list of imports for use with action class.
   num_conflicts           - number of conflicts detected. 
   nowarn                  - true if we are not to issue warning messages.
   not_reduced             - count of number of productions that never reduce.
   unused_term             - count of unused terminal symbols.
   unused_non_term         - count of unused non terminal symbols.
   *_time                  - a series of symbols indicating how long various
			     sub-parts of code generation took (used to produce
			     optional time reports in main).
*/

public class emit {

  /*-----------------------------------------------------------*/
  /*--- Constructor(s) ----------------------------------------*/
  /*-----------------------------------------------------------*/

  /** Only constructor is private so no instances can be created. */
  private emit() { }

  /*-----------------------------------------------------------*/
  /*--- Static (Class) Variables ------------------------------*/
  /*-----------------------------------------------------------*/

  /** The prefix placed on names that pollute someone else's name space. */
  public static String prefix = "CUP$";

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Package that the resulting code goes into (null is used for unnamed). */
  public static String package_name = null;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Name of the generated class for symbol constants. */
  public static String symbol_const_class_name = "sym";

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Name of the generated parser class. */
  public static String parser_class_name = "parser";

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** User declarations for direct inclusion in user action class. */
  public static String action_code = null;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** User declarations for direct inclusion in parser class. */
  public static String parser_code = null;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** User code for user_init() which is called during parser initialization. */
  public static String init_code = null;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** User code for scan() which is called to get the next Symbol. */
  public static String scan_code = null;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** The start production of the grammar. */
  public static production start_production = null;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** List of imports (Strings containing class names) to go with actions. */
  public static Stack import_list = new Stack();

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Number of conflict found while building tables. */
  public static int num_conflicts = 0;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Do we skip warnings? */
  public static boolean nowarn = false;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Count of the number on non-reduced productions found. */
  public static int not_reduced = 0;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Count of unused terminals. */
  public static int unused_term = 0;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Count of unused non terminals. */
  public static int unused_non_term = 0;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /* Timing values used to produce timing report in main.*/

  /** Time to produce symbol constant class. */
  public static long symbols_time          = 0;

  /** Time to produce parser class. */
  public static long parser_time           = 0;

  /** Time to produce action code class. */
  public static long action_code_time      = 0;

  /** Time to produce the production table. */
  public static long production_table_time = 0;

  /** Time to produce the action table. */
  public static long action_table_time     = 0;

  /** Time to produce the reduce-goto table. */
  public static long goto_table_time       = 0;

  /* frankf 6/18/96 */
  protected static boolean _lr_values;

  /** whether or not to emit code for left and right values */
  public static boolean lr_values() {return _lr_values;}
  protected static void set_lr_values(boolean b) { _lr_values = b;}

  /*-----------------------------------------------------------*/
  /*--- General Methods ---------------------------------------*/
  /*-----------------------------------------------------------*/

  /** Build a string with the standard prefix. 
   * @param str string to prefix.
   */
  protected static String pre(String str) {
    return prefix + parser_class_name + "$" + str;
  }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Emit a package spec if the user wants one. 
   * @param out stream to produce output on.
   */
  protected static void emit_package(PrintWriter out)
    {
      /* generate a package spec if we have a name for one */
      if (package_name != null) {
	out.println("package " + package_name + ";"); out.println();
      }
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Emit code for the symbol constant class, optionally including non terms,
   *  if they have been requested.  
   * @param out            stream to produce output on.
   * @param emit_non_terms do we emit constants for non terminals?
   * @param sym_interface  should we emit an interface, rather than a class?
   */
  public static void symbols(PrintWriter out, 
			     boolean emit_non_terms, boolean sym_interface)
    {
      terminal term;
      non_terminal nt;
      String class_or_interface = (sym_interface)?"interface":"class";

      long start_time = System.currentTimeMillis();

      /* top of file */
      out.println();
      out.println("//----------------------------------------------------"); 
      out.println("// The following code was generated by " + 
							   version.title_str);
      out.println("// " + new Date());
      out.println("//----------------------------------------------------"); 
      out.println();
      emit_package(out);

      /* class header */
      out.println("/** CUP generated " + class_or_interface + 
		  " containing symbol constants. */");
      out.println("public " + class_or_interface + " " + 
		  symbol_const_class_name + " {");

      out.println("  /* terminals */");

      /* walk over the terminals */              /* later might sort these */
      for (Enumeration e = terminal.all(); e.hasMoreElements(); )
	{
	  term = (terminal)e.nextElement();

	  /* output a constant decl for the terminal */
	  out.println("  public static final int " + term.name() + " = " + 
		      term.index() + ";");
	}

      /* do the non terminals if they want them (parser doesn't need them) */
      if (emit_non_terms)
	{
          out.println();
          out.println("  /* non terminals */");

          /* walk over the non terminals */       /* later might sort these */
          for (Enumeration e = non_terminal.all(); e.hasMoreElements(); )
	    {
	      nt = (non_terminal)e.nextElement();
    
	      /* output a constant decl for the terminal */
	      out.println("  static final int " + nt.name() + " = " + 
		          nt.index() + ";");
	    }
	}

      /* end of class */
      out.println("}");
      out.println();

      symbols_time = System.currentTimeMillis() - start_time;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Emit code for the non-public class holding the actual action code. 
   * @param out        stream to produce output on.
   * @param start_prod the start production of the grammar.
   */
  protected static void emit_action_code(PrintWriter out, production start_prod)
    throws internal_error
    {
      production prod;

      long start_time = System.currentTimeMillis();

      /* class header */
      out.println();
      out.println(
       "/** Cup generated class to encapsulate user supplied action code.*/"
      );  
      out.println("class " +  pre("actions") + " {");

      /* user supplied code */
      if (action_code != null)
	{
	  out.println();
          out.println(action_code);
	}

      /* field for parser object */
      out.println("  private final "+parser_class_name+" parser;");

      /* constructor */
      out.println();
      out.println("  /** Constructor */");
      out.println("  " + pre("actions") + "("+parser_class_name+" parser) {");
      out.println("    this.parser = parser;");
      out.println("  }");

      /* action method head */
      out.println();
      out.println("  /** Method with the actual generated action code. */");
      out.println("  public final java_cup.runtime.Symbol " + 
		     pre("do_action") + "(");
      out.println("    int                        " + pre("act_num,"));
      out.println("    java_cup.runtime.lr_parser " + pre("parser,"));
      out.println("    java.util.Stack            " + pre("stack,"));
      out.println("    int                        " + pre("top)"));
      out.println("    throws java.lang.Exception");
      out.println("    {");

      /* declaration of result symbol */
      /* New declaration!! now return Symbol
	 6/13/96 frankf */
      out.println("      /* Symbol object for return from actions */");
      out.println("      java_cup.runtime.Symbol " + pre("result") + ";");
      out.println();

      /* switch top */
      out.println("      /* select the action based on the action number */");
      out.println("      switch (" + pre("act_num") + ")");
      out.println("        {");

      /* emit action code for each production as a separate case */
      for (Enumeration p = production.all(); p.hasMoreElements(); )
	{
	  prod = (production)p.nextElement();

	  /* case label */
          out.println("          /*. . . . . . . . . . . . . . . . . . . .*/");
          out.println("          case " + prod.index() + ": // " + 
					  prod.to_simple_string());

	  /* give them their own block to work in */
	  out.println("            {");

	  /* create the result symbol */
	  /*make the variable RESULT which will point to the new Symbol (see below)
	    and be changed by action code
	    6/13/96 frankf */
	  out.println("              " +  prod.lhs().the_symbol().stack_type() +
		      " RESULT = null;");

	  /* Add code to propagate RESULT assignments that occur in
	   * action code embedded in a production (ie, non-rightmost
	   * action code). 24-Mar-1998 CSA
	   */
	  for (int i=0; i<prod.rhs_length(); i++) {
	    // only interested in non-terminal symbols.
	    if (!(prod.rhs(i) instanceof symbol_part)) continue;
	    symbol s = ((symbol_part)prod.rhs(i)).the_symbol();
	    if (!(s instanceof non_terminal)) continue;
	    // skip this non-terminal unless it corresponds to
	    // an embedded action production.
	    if (((non_terminal)s).is_embedded_action == false) continue;
	    // OK, it fits.  Make a conditional assignment to RESULT.
	    int index = prod.rhs_length() - i - 1; // last rhs is on top.
	    out.println("              " + "// propagate RESULT from " +
			s.name());
	    out.println("              " + "if ( " +
	      "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
              + emit.pre("top") + "-" + index + ")).value != null )");
	    out.println("                " + "RESULT = " +
	      "(" + prod.lhs().the_symbol().stack_type() + ") " +
	      "((java_cup.runtime.Symbol) " + emit.pre("stack") + ".elementAt("
              + emit.pre("top") + "-" + index + ")).value;");
	  }

        /* if there is an action string, emit it */
          if (prod.action() != null && prod.action().code_string() != null &&
              !prod.action().equals(""))
            out.println(prod.action().code_string());

	  /* here we have the left and right values being propagated.  
		must make this a command line option.
	     frankf 6/18/96 */

         /* Create the code that assigns the left and right values of
            the new Symbol that the production is reducing to */
	  if (emit.lr_values()) {	    
	    int loffset;
	    String leftstring, rightstring;
	    int roffset = 0;
	    rightstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" + 
	      emit.pre("top") + "-" + roffset + ")).right";	  
	    if (prod.rhs_length() == 0) 
	      leftstring = rightstring;
	    else {
	      loffset = prod.rhs_length() - 1;
	      leftstring = "((java_cup.runtime.Symbol)" + emit.pre("stack") + ".elementAt(" + 
		emit.pre("top") + "-" + loffset + ")).left";	  
	    }
	    out.println("              " + pre("result") + " = new java_cup.runtime.Symbol(" + 
			prod.lhs().the_symbol().index() + "/*" +
			prod.lhs().the_symbol().name() + "*/" + 
			", " + leftstring + ", " + rightstring + ", RESULT);");
	  } else {
	    out.println("              " + pre("result") + " = new java_cup.runtime.Symbol(" + 
			prod.lhs().the_symbol().index() + "/*" +
			prod.lhs().the_symbol().name() + "*/" + 
			", RESULT);");
	  }
	  
	  /* end of their block */
	  out.println("            }");

	  /* if this was the start production, do action for accept */
	  if (prod == start_prod)
	    {
	      out.println("          /* ACCEPT */");
	      out.println("          " + pre("parser") + ".done_parsing();");
	    }

	  /* code to return lhs symbol */
	  out.println("          return " + pre("result") + ";");
	  out.println();
	}

      /* end of switch */
      out.println("          /* . . . . . .*/");
      out.println("          default:");
      out.println("            throw new Exception(");
      out.println("               \"Invalid action number found in " +
				  "internal parse table\");");
      out.println();
      out.println("        }");

      /* end of method */
      out.println("    }");

      /* end of class */
      out.println("}");
      out.println();

      action_code_time = System.currentTimeMillis() - start_time;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Emit the production table. 
   * @param out stream to produce output on.
   */
  protected static void emit_production_table(PrintWriter out)
    {
      production all_prods[];
      production prod;

      long start_time = System.currentTimeMillis();

      /* collect up the productions in order */
      all_prods = new production[production.number()];
      for (Enumeration p = production.all(); p.hasMoreElements(); )
	{
	  prod = (production)p.nextElement();
	  all_prods[prod.index()] = prod;
	}

      // make short[][]
      short[][] prod_table = new short[production.number()][2];
      for (int i = 0; i<production.number(); i++)
	{
	  prod = all_prods[i];
	  // { lhs symbol , rhs size }
	  prod_table[i][0] = (short) prod.lhs().the_symbol().index();
	  prod_table[i][1] = (short) prod.rhs_length();
	}
      /* do the top of the table */
      out.println();
      out.println("  /** Production table. */");
      out.println("  protected static final short _production_table[][] = ");
      out.print  ("    unpackFromStrings(");
      do_table_as_string(out, prod_table);
      out.println(");");

      /* do the public accessor method */
      out.println();
      out.println("  /** Access to production table. */");
      out.println("  public short[][] production_table() " + 
						 "{return _production_table;}");

      production_table_time = System.currentTimeMillis() - start_time;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Emit the action table. 
   * @param out             stream to produce output on.
   * @param act_tab         the internal representation of the action table.
   * @param compact_reduces do we use the most frequent reduce as default?
   */
  protected static void do_action_table(
    PrintWriter        out, 
    parse_action_table act_tab,
    boolean            compact_reduces)
    throws internal_error
    {
      parse_action_row row;
      parse_action     act;
      int              red;

      long start_time = System.currentTimeMillis();

      /* collect values for the action table */
      short[][] action_table = new short[act_tab.num_states()][];
      /* do each state (row) of the action table */
      for (int i = 0; i < act_tab.num_states(); i++)
	{
	  /* get the row */
	  row = act_tab.under_state[i];

	  /* determine the default for the row */
	  if (compact_reduces)
	    row.compute_default();
	  else
	    row.default_reduce = -1;

	  /* make temporary table for the row. */
	  short[] temp_table = new short[2*row.size()];
	  int nentries = 0;

	  /* do each column */
	  for (int j = 0; j < row.size(); j++)
	    {
	      /* extract the action from the table */
	      act = row.under_term[j];

	      /* skip error entries these are all defaulted out */
	      if (act.kind() != parse_action.ERROR)
		{
		  /* first put in the symbol index, then the actual entry */

		  /* shifts get positive entries of state number + 1 */
		  if (act.kind() == parse_action.SHIFT)
		    {
		      /* make entry */
		      temp_table[nentries++] = (short) j;
		      temp_table[nentries++] = (short)
			(((shift_action)act).shift_to().index() + 1);
		    }

		  /* reduce actions get negated entries of production# + 1 */
		  else if (act.kind() == parse_action.REDUCE)
		    {
		      /* if its the default entry let it get defaulted out */
		      red = ((reduce_action)act).reduce_with().index();
		      if (red != row.default_reduce) {
			/* make entry */
			temp_table[nentries++] = (short) j;
			temp_table[nentries++] = (short) (-(red+1));
		      }
		    } else if (act.kind() == parse_action.NONASSOC)
		      {
			/* do nothing, since we just want a syntax error */
		      }
		  /* shouldn't be anything else */
		  else
		    throw new internal_error("Unrecognized action code " + 
					     act.kind() + " found in parse table");
		}
	    }

	  /* now we know how big to make the row */
	  action_table[i] = new short[nentries + 2];
	  System.arraycopy(temp_table, 0, action_table[i], 0, nentries);

	  /* finish off the row with a default entry */
	  action_table[i][nentries++] = -1;
	  if (row.default_reduce != -1)
	    action_table[i][nentries++] = (short) (-(row.default_reduce+1));
	  else
	    action_table[i][nentries++] = 0;
	}

      /* finish off the init of the table */
      out.println();
      out.println("  /** Parse-action table. */");
      out.println("  protected static final short[][] _action_table = "); 
      out.print  ("    unpackFromStrings(");
      do_table_as_string(out, action_table);
      out.println(");");

      /* do the public accessor method */
      out.println();
      out.println("  /** Access to parse-action table. */");
      out.println("  public short[][] action_table() {return _action_table;}");

      action_table_time = System.currentTimeMillis() - start_time;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Emit the reduce-goto table. 
   * @param out     stream to produce output on.
   * @param red_tab the internal representation of the reduce-goto table.
   */
  protected static void do_reduce_table(
    PrintWriter out, 
    parse_reduce_table red_tab)
    {
      lalr_state       goto_st;
      parse_action     act;

      long start_time = System.currentTimeMillis();

      /* collect values for reduce-goto table */
      short[][] reduce_goto_table = new short[red_tab.num_states()][];
      /* do each row of the reduce-goto table */
      for (int i=0; i<red_tab.num_states(); i++)
	{
	  /* make temporary table for the row. */
	  short[] temp_table = new short[2*red_tab.under_state[i].size()];
	  int nentries = 0;
	  /* do each entry in the row */
	  for (int j=0; j<red_tab.under_state[i].size(); j++)
	    {
	      /* get the entry */
	      goto_st = red_tab.under_state[i].under_non_term[j];

	      /* if we have none, skip it */
	      if (goto_st != null)
		{
		  /* make entries for the index and the value */
		  temp_table[nentries++] = (short) j;
		  temp_table[nentries++] = (short) goto_st.index();
		}
	    }
	  /* now we know how big to make the row. */
	  reduce_goto_table[i] = new short[nentries+2];
	  System.arraycopy(temp_table, 0, reduce_goto_table[i], 0, nentries);

	  /* end row with default value */
	  reduce_goto_table[i][nentries++] = -1;
	  reduce_goto_table[i][nentries++] = -1;
	}

      /* emit the table. */
      out.println();
      out.println("  /** <code>reduce_goto</code> table. */");
      out.println("  protected static final short[][] _reduce_table = "); 
      out.print  ("    unpackFromStrings(");
      do_table_as_string(out, reduce_goto_table);
      out.println(");");

      /* do the public accessor method */
      out.println();
      out.println("  /** Access to <code>reduce_goto</code> table. */");
      out.println("  public short[][] reduce_table() {return _reduce_table;}");
      out.println();

      goto_table_time = System.currentTimeMillis() - start_time;
    }

  // print a string array encoding the given short[][] array.
  protected static void do_table_as_string(PrintWriter out, short[][] sa) {
    out.println("new String[] {");
    out.print("    \"");
    int nchar=0, nbytes=0;
    nbytes+=do_escaped(out, (char)(sa.length>>16));
    nchar  =do_newline(out, nchar, nbytes);
    nbytes+=do_escaped(out, (char)(sa.length&0xFFFF));
    nchar  =do_newline(out, nchar, nbytes);
    for (int i=0; i<sa.length; i++) {
	nbytes+=do_escaped(out, (char)(sa[i].length>>16));
	nchar  =do_newline(out, nchar, nbytes);
	nbytes+=do_escaped(out, (char)(sa[i].length&0xFFFF));
	nchar  =do_newline(out, nchar, nbytes);
	for (int j=0; j<sa[i].length; j++) {
	  // contents of string are (value+2) to allow for common -1, 0 cases
	  // (UTF-8 encoding is most efficient for 0<c<0x80)
	  nbytes+=do_escaped(out, (char)(2+sa[i][j]));
	  nchar  =do_newline(out, nchar, nbytes);
	}
    }
    out.print("\" }");
  }
  // split string if it is very long; start new line occasionally for neatness
  protected static int do_newline(PrintWriter out, int nchar, int nbytes) {
    if (nbytes > 65500)  { out.println("\", "); out.print("    \""); }
    else if (nchar > 11) { out.println("\" +"); out.print("    \""); }
    else return nchar+1;
    return 0;
  }
  // output an escape sequence for the given character code.
  protected static int do_escaped(PrintWriter out, char c) {
    StringBuffer escape = new StringBuffer();
    if (c <= 0xFF) {
      escape.append(Integer.toOctalString(c));
      while(escape.length() < 3) escape.insert(0, '0');
    } else {
      escape.append(Integer.toHexString(c));
      while(escape.length() < 4) escape.insert(0, '0');
      escape.insert(0, 'u');
    }
    escape.insert(0, '\\');
    out.print(escape.toString());

    // return number of bytes this takes up in UTF-8 encoding.
    if (c == 0) return 2;
    if (c >= 0x01 && c <= 0x7F) return 1;
    if (c >= 0x80 && c <= 0x7FF) return 2;
    return 3;
  }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Emit the parser subclass with embedded tables. 
   * @param out             stream to produce output on.
   * @param action_table    internal representation of the action table.
   * @param reduce_table    internal representation of the reduce-goto table.
   * @param start_st        start state of the parse machine.
   * @param start_prod      start production of the grammar.
   * @param compact_reduces do we use most frequent reduce as default?
   * @param suppress_scanner should scanner be suppressed for compatibility?
   */
  public static void parser(
    PrintWriter        out, 
    parse_action_table action_table,
    parse_reduce_table reduce_table,
    int                start_st,
    production         start_prod,
    boolean            compact_reduces,
    boolean            suppress_scanner)
    throws internal_error
    {
      long start_time = System.currentTimeMillis();

      /* top of file */
      out.println();
      out.println("//----------------------------------------------------"); 
      out.println("// The following code was generated by " + 
							version.title_str);
      out.println("// " + new Date());
      out.println("//----------------------------------------------------"); 
      out.println();
      emit_package(out);

      /* user supplied imports */
      for (int i = 0; i < import_list.size(); i++)
	out.println("import " + import_list.elementAt(i) + ";");

      /* class header */
      out.println();
      out.println("/** "+version.title_str+" generated parser.");
      out.println("  * @version " + new Date());
      out.println("  */");
      out.println("public class " + parser_class_name + 
		  " extends java_cup.runtime.lr_parser {");

      /* constructors [CSA/davidm, 24-jul-99] */
      out.println();
      out.println("  /** Default constructor. */");
      out.println("  public " + parser_class_name + "() {super();}");
      if (!suppress_scanner) {
	  out.println();
	  out.println("  /** Constructor which sets the default scanner. */");
	  out.println("  public " + parser_class_name + 
		      "(java_cup.runtime.Scanner s) {super(s);}");
      }

      /* emit the various tables */
      emit_production_table(out);
      do_action_table(out, action_table, compact_reduces);
      do_reduce_table(out, reduce_table);

      /* instance of the action encapsulation class */
      out.println("  /** Instance of action encapsulation class. */");
      out.println("  protected " + pre("actions") + " action_obj;");
      out.println();

      /* action object initializer */
      out.println("  /** Action encapsulation object initializer. */");
      out.println("  protected void init_actions()");
      out.println("    {");
      out.println("      action_obj = new " + pre("actions") + "(this);");
      out.println("    }");
      out.println();

      /* access to action code */
      out.println("  /** Invoke a user supplied parse action. */");
      out.println("  public java_cup.runtime.Symbol do_action(");
      out.println("    int                        act_num,");
      out.println("    java_cup.runtime.lr_parser parser,");
      out.println("    java.util.Stack            stack,");
      out.println("    int                        top)");
      out.println("    throws java.lang.Exception");
      out.println("  {");
      out.println("    /* call code in generated class */");
      out.println("    return action_obj." + pre("do_action(") +
                  "act_num, parser, stack, top);");
      out.println("  }");
      out.println("");


      /* method to tell the parser about the start state */
      out.println("  /** Indicates start state. */");
      out.println("  public int start_state() {return " + start_st + ";}");

      /* method to indicate start production */
      out.println("  /** Indicates start production. */");
      out.println("  public int start_production() {return " + 
		     start_production.index() + ";}");
      out.println();

      /* methods to indicate EOF and error symbol indexes */
      out.println("  /** <code>EOF</code> Symbol index. */");
      out.println("  public int EOF_sym() {return " + terminal.EOF.index() + 
					  ";}");
      out.println();
      out.println("  /** <code>error</code> Symbol index. */");
      out.println("  public int error_sym() {return " + terminal.error.index() +
					  ";}");
      out.println();

      /* user supplied code for user_init() */
      if (init_code != null)
	{
          out.println();
	  out.println("  /** User initialization code. */");
	  out.println("  public void user_init() throws java.lang.Exception");
	  out.println("    {");
	  out.println(init_code);
	  out.println("    }");
	}

      /* user supplied code for scan */
      if (scan_code != null)
	{
          out.println();
	  out.println("  /** Scan to get the next Symbol. */");
	  out.println("  public java_cup.runtime.Symbol scan()");
	  out.println("    throws java.lang.Exception");
	  out.println("    {");
	  out.println(scan_code);
	  out.println("    }");
	}

      /* user supplied code */
      if (parser_code != null)
	{
	  out.println();
          out.println(parser_code);
	}

      /* end of class */
      out.println("}");

      /* put out the action code class */
      emit_action_code(out, start_prod);

      parser_time = System.currentTimeMillis() - start_time;
    }

    /*-----------------------------------------------------------*/
}
java_cup/internal_error.java100640  31676    763        1047  6746333325  16407 0ustar  cananiancananian
package java_cup;

/** Exception subclass for reporting internal errors in JavaCup. */
public class internal_error extends Exception
  {
    /** Constructor with a message */
    public internal_error(String msg)
      {
	super(msg);
      }

    /** Method called to do a forced error exit on an internal error
	for cases when we can't actually throw the exception.  */
    public void crash()
      {
	System.err.println("JavaCUP Fatal Internal Error Detected");
	System.err.println(getMessage());
	printStackTrace();
	System.exit(-1);
      }
  }
java_cup/lalr_item.java100640  31676    763       24536  6746333325  15362 0ustar  cananiancananianpackage java_cup;

import java.util.Stack;
import java.util.Enumeration;

/** This class represents an LALR item. Each LALR item consists of 
 *  a production, a "dot" at a position within that production, and
 *  a set of lookahead symbols (terminal).  (The first two of these parts
 *  are provide by the super class).  An item is designed to represent a 
 *  configuration that the parser may be in.  For example, an item of the 
 *  form: <pre>
 *    [A ::= B * C d E  , {a,b,c}]
 *  </pre>
 *  indicates that the parser is in the middle of parsing the production <pre>
 *    A ::= B C d E
 *  </pre>
 *  that B has already been parsed, and that we will expect to see a lookahead 
 *  of either a, b, or c once the complete RHS of this production has been 
 *  found.<p>
 *
 *  Items may initially be missing some items from their lookahead sets.  
 *  Links are maintained from each item to the set of items that would need 
 *  to be updated if symbols are added to its lookahead set.  During 
 *  "lookahead propagation", we add symbols to various lookahead sets and 
 *  propagate these changes across these dependency links as needed. 
 *  
 * @see     java_cup.lalr_item_set
 * @see     java_cup.lalr_state
 * @version last updated: 11/25/95
 * @author  Scott Hudson
 */
public class lalr_item extends lr_item_core {

  /*-----------------------------------------------------------*/
  /*--- Constructor(s) ----------------------------------------*/
  /*-----------------------------------------------------------*/

  /** Full constructor. 
   * @param prod the production for the item.
   * @param pos  the position of the "dot" within the production.
   * @param look the set of lookahead symbols.
   */
  public lalr_item(production prod, int pos, terminal_set look) 
    throws internal_error
    {
      super(prod, pos);
      _lookahead = look;
      _propagate_items = new Stack();
      needs_propagation = true;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Constructor with default position (dot at start). 
   * @param prod the production for the item.
   * @param look the set of lookahead symbols.
   */
  public lalr_item(production prod, terminal_set look) throws internal_error
    {
      this(prod,0,look);
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Constructor with default position and empty lookahead set. 
   * @param prod the production for the item.
   */
  public lalr_item(production prod) throws internal_error
    {
      this(prod,0,new terminal_set());
    }

  /*-----------------------------------------------------------*/
  /*--- (Access to) Instance Variables ------------------------*/
  /*-----------------------------------------------------------*/

  /** The lookahead symbols of the item. */
  protected terminal_set _lookahead;

  /** The lookahead symbols of the item. */
  public terminal_set lookahead() {return _lookahead;}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Links to items that the lookahead needs to be propagated to. */
  protected Stack _propagate_items; 

  /** Links to items that the lookahead needs to be propagated to */
  public Stack propagate_items() {return _propagate_items;}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Flag to indicate that this item needs to propagate its lookahead 
   *  (whether it has changed or not). 
   */
  protected boolean needs_propagation;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Add a new item to the set of items we propagate to. */
  public void add_propagate(lalr_item prop_to)
    {
      _propagate_items.push(prop_to);
      needs_propagation = true;
    }

  /*-----------------------------------------------------------*/
  /*--- General Methods ---------------------------------------*/
  /*-----------------------------------------------------------*/

  /** Propagate incoming lookaheads through this item to others need to 
   *  be changed.
   * @params incoming symbols to potentially be added to lookahead of this item.
   */
  public void propagate_lookaheads(terminal_set incoming) throws internal_error
    {
      boolean change = false;

      /* if we don't need to propagate, then bail out now */
      if (!needs_propagation && (incoming == null || incoming.empty()))
	return;

      /* if we have null incoming, treat as an empty set */
      if (incoming != null)
	{
	  /* add the incoming to the lookahead of this item */
	  change = lookahead().add(incoming);
	}

      /* if we changed or need it anyway, propagate across our links */
      if (change || needs_propagation)
	{
          /* don't need to propagate again */
          needs_propagation = false;

	  /* propagate our lookahead into each item we are linked to */
	  for (int i = 0; i < propagate_items().size(); i++)
	    ((lalr_item)propagate_items().elementAt(i))
					  .propagate_lookaheads(lookahead());
	}
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Produce the new lalr_item that results from shifting the dot one position
   *  to the right. 
   */
  public lalr_item shift() throws internal_error
    {
      lalr_item result;

      /* can't shift if we have dot already at the end */
      if (dot_at_end())
	throw new internal_error("Attempt to shift past end of an lalr_item");

      /* create the new item w/ the dot shifted by one */
      result = new lalr_item(the_production(), dot_pos()+1, 
					    new terminal_set(lookahead()));

      /* change in our lookahead needs to be propagated to this item */
      add_propagate(result);

      return result;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Calculate lookahead representing symbols that could appear after the
   *   symbol that the dot is currently in front of.  Note: this routine must
   *   not be invoked before first sets and nullability has been calculated
   *   for all non terminals. 
   */ 
  public terminal_set calc_lookahead(terminal_set lookahead_after) 
    throws internal_error
    {
      terminal_set    result;
      int             pos;
      production_part part;
      symbol          sym;

      /* sanity check */
      if (dot_at_end())
	throw new internal_error(
	  "Attempt to calculate a lookahead set with a completed item");

      /* start with an empty result */
      result = new terminal_set();

      /* consider all nullable symbols after the one to the right of the dot */
      for (pos = dot_pos()+1; pos < the_production().rhs_length(); pos++) 
	{
	   part = the_production().rhs(pos);

	   /* consider what kind of production part it is -- skip actions */ 
	   if (!part.is_action())
	     {
	       sym = ((symbol_part)part).the_symbol();

	       /* if its a terminal add it in and we are done */
	       if (!sym.is_non_term())
		 {
		   result.add((terminal)sym);
		   return result;
		 }
	       else
		 {
		   /* otherwise add in first set of the non terminal */
		   result.add(((non_terminal)sym).first_set());

		   /* if its nullable we continue adding, if not, we are done */
		   if (!((non_terminal)sym).nullable())
		     return result;
		 }
	     }
	}

      /* if we get here everything past the dot was nullable 
         we add in the lookahead for after the production and we are done */
      result.add(lookahead_after);
      return result;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Determine if everything from the symbol one beyond the dot all the 
   *  way to the  end of the right hand side is nullable.  This would indicate
   *  that the lookahead of this item must be included in the lookaheads of
   *  all items produced as a closure of this item.  Note: this routine should 
   *  not be invoked until after first sets and nullability have been 
   *  calculated for all non terminals. 
   */
  public boolean lookahead_visible() throws internal_error
    {
      production_part part;
      symbol          sym;

      /* if the dot is at the end, we have a problem, but the cleanest thing
	 to do is just return true. */
      if (dot_at_end()) return true;

      /* walk down the rhs and bail if we get a non-nullable symbol */
      for (int pos = dot_pos() + 1; pos < the_production().rhs_length(); pos++)
	{
	  part = the_production().rhs(pos);

	  /* skip actions */
	  if (!part.is_action())
	    {
	      sym = ((symbol_part)part).the_symbol();

	      /* if its a terminal we fail */
	      if (!sym.is_non_term()) return false;

	      /* if its not nullable we fail */
	      if (!((non_terminal)sym).nullable()) return false;
	    }
	}

      /* if we get here its all nullable */
      return true;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Equality comparison -- here we only require the cores to be equal since
   *   we need to do sets of items based only on core equality (ignoring 
   *   lookahead sets). 
   */
  public boolean equals(lalr_item other)
    {
      if (other == null) return false;
      return super.equals(other);
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Generic equality comparison. */
  public boolean equals(Object other)
    {
      if (!(other instanceof lalr_item)) 
	return false;
      else
	return equals((lalr_item)other);
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Return a hash code -- here we only hash the core since we only test core
   *  matching in LALR items. 
   */
  public int hashCode()
    {
      return super.hashCode();
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Convert to string. */
  public String toString()
    {
      String result = "";

      // additional output for debugging:
      // result += "(" + obj_hash() + ")"; 
      result += "[";
      result += super.toString();
      result += ", ";
      if (lookahead() != null)
	{
	  result += "{";
	  for (int t = 0; t < terminal.number(); t++)
	    if (lookahead().contains(t))
	      result += terminal.find(t).name() + " ";
	  result += "}";
	}
      else
	result += "NULL LOOKAHEAD!!";
      result += "]";

      // additional output for debugging:
      // result += " -> ";
      // for (int i = 0; i<propagate_items().size(); i++)
      //   result+=((lalr_item)(propagate_items().elementAt(i))).obj_hash()+" ";
      //
      // if (needs_propagation) result += " NP";

      return result;
    }
    /*-----------------------------------------------------------*/
}
java_cup/lalr_item_set.java100640  31676    763       25375  6746333325  16237 0ustar  cananiancananian
package java_cup;

import java.util.Hashtable;
import java.util.Enumeration;

/** This class represents a set of LALR items.  For purposes of building
 *  these sets, items are considered unique only if they have unique cores
 *  (i.e., ignoring differences in their lookahead sets).<p>
 *
 *  This class provides fairly conventional set oriented operations (union,
 *  sub/super-set tests, etc.), as well as an LALR "closure" operation (see 
 *  compute_closure()).
 *
 * @see     java_cup.lalr_item
 * @see     java_cup.lalr_state
 * @version last updated: 3/6/96
 * @author  Scott Hudson
 */

public class lalr_item_set {

  /*-----------------------------------------------------------*/
  /*--- Constructor(s) ----------------------------------------*/
  /*-----------------------------------------------------------*/

  /** Constructor for an empty set. */
  public lalr_item_set() { }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Constructor for cloning from another set. 
   * @param other indicates set we should copy from.
   */
  public lalr_item_set(lalr_item_set other) 
    throws internal_error
    {
      not_null(other);
      _all = (Hashtable)other._all.clone();
    }

  /*-----------------------------------------------------------*/
  /*--- (Access to) Instance Variables ------------------------*/
  /*-----------------------------------------------------------*/

  /** A hash table to implement the set.  We store the items using themselves
   *  as keys. 
   */
  protected Hashtable _all = new Hashtable(11);

  /** Access to all elements of the set. */
  public Enumeration all() {return _all.elements();}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Cached hashcode for this set. */
  protected Integer hashcode_cache = null;

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Size of the set */
  public int size() {return _all.size();}

  /*-----------------------------------------------------------*/
  /*--- Set Operation Methods ---------------------------------*/
  /*-----------------------------------------------------------*/

  /** Does the set contain a particular item? 
   * @param itm the item in question.
   */
  public boolean contains(lalr_item itm) {return _all.containsKey(itm);}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Return the item in the set matching a particular item (or null if not 
   *  found) 
   *  @param itm the item we are looking for.
   */
  public lalr_item find(lalr_item itm) {return (lalr_item)_all.get(itm);}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Is this set an (improper) subset of another? 
   * @param other the other set in question.
   */
  public boolean is_subset_of(lalr_item_set other) throws internal_error
    {
      not_null(other);

      /* walk down our set and make sure every element is in the other */
      for (Enumeration e = all(); e.hasMoreElements(); )
	if (!other.contains((lalr_item)e.nextElement()))
	  return false;

      /* they were all there */
      return true;
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Is this set an (improper) superset of another? 
   * @param other the other set in question.
   */
  public boolean is_superset_of(lalr_item_set other) throws internal_error
    {
      not_null(other);
      return other.is_subset_of(this);
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Add a singleton item, merging lookahead sets if the item is already 
   *  part of the set.  returns the element of the set that was added or 
   *  merged into.
   * @param itm the item being added.
   */
  public lalr_item add(lalr_item itm) throws internal_error
    {
      lalr_item other;

      not_null(itm); 

      /* see if an item with a matching core is already there */
      other = (lalr_item)_all.get(itm);

      /* if so, merge this lookahead into the original and leave it */
      if (other != null)
	{
	  other.lookahead().add(itm.lookahead());
	  return other;
	}
      /* otherwise we just go in the set */
      else
	{
          /* invalidate cached hashcode */
          hashcode_cache = null;

          _all.put(itm,itm);
	  return itm;
	}
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Remove a single item if it is in the set. 
   * @param itm the item to remove.
   */
  public void remove(lalr_item itm) throws internal_error
    {
      not_null(itm); 

      /* invalidate cached hashcode */
      hashcode_cache = null;

      /* remove it from hash table implementing set */
      _all.remove(itm);
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Add a complete set, merging lookaheads where items are already in 
   *  the set 
   * @param other the set to be added.
   */
  public void add(lalr_item_set other) throws internal_error
    {
      not_null(other);

      /* walk down the other set and do the adds individually */
      for (Enumeration e = other.all(); e.hasMoreElements(); )
	add((lalr_item)e.nextElement());
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Remove (set subtract) a complete set. 
   * @param other the set to remove.
   */
  public void remove(lalr_item_set other) throws internal_error
    {
      not_null(other);

      /* walk down the other set and do the removes individually */
      for (Enumeration e = other.all(); e.hasMoreElements(); )
	remove((lalr_item)e.nextElement());
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Remove and return one item from the set (done in hash order). */
  public lalr_item get_one() throws internal_error
    {
      Enumeration the_set;
      lalr_item result;

      the_set = all();
      if (the_set.hasMoreElements())
	{
          result = (lalr_item)the_set.nextElement();
          remove(result);
	  return result;
	}
      else
	return null;
    }

  /*-----------------------------------------------------------*/
  /*--- General Methods ---------------------------------------*/
  /*-----------------------------------------------------------*/

  /** Helper function for null test.  Throws an interal_error exception if its
   *  parameter is null.
   *  @param obj the object we are testing.
   */
  protected void not_null(Object obj) throws internal_error
    {
      if (obj == null) 
	throw new internal_error("Null object used in set operation");
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Compute the closure of the set using the LALR closure rules.  Basically
   *  for every item of the form: <pre>
   *    [L ::= a *N alpha, l] 
   *  </pre>
   *  (where N is a a non terminal and alpha is a string of symbols) make 
   *  sure there are also items of the form:  <pre>
   *    [N ::= *beta, first(alpha l)] 
   *  </pre>
   *  corresponding to each production of N.  Items with identical cores but 
   *  differing lookahead sets are merged by creating a new item with the same 
   *  core and the union of the lookahead sets (the LA in LALR stands for 
   *  "lookahead merged" and this is where the merger is).  This routine 
   *  assumes that nullability and first sets have been computed for all 
   *  productions before it is called.
   */
  public void compute_closure()
    throws internal_error
    {
      lalr_item_set consider;
      lalr_item     itm, new_itm, add_itm;
      non_terminal  nt;
      terminal_set  new_lookaheads;
      Enumeration   p;
      production    prod;
      boolean       need_prop;



      /* invalidate cached hashcode */
      hashcode_cache = null;

      /* each current element needs to be considered */
      consider = new lalr_item_set(this);

      /* repeat this until there is nothing else to consider */
      while (consider.size() > 0)
	{
	  /* get one item to consider */
	  itm = consider.get_one(); 

	  /* do we have a dot before a non terminal */
	  nt = itm.dot_before_nt();
	  if (nt != null)
	    {
	      /* create the lookahead set based on first after dot */
	      new_lookaheads = itm.calc_lookahead(itm.lookahead());

	      /* are we going to need to propagate our lookahead to new item */
	      need_prop = itm.lookahead_visible();

	      /* create items for each production of that non term */
	      for (p = nt.productions(); p.hasMoreElements(); )
		{
		  prod = (production)p.nextElement();

		  /* create new item with dot at start and that lookahead */
		  new_itm = new lalr_item(prod, 
					     new terminal_set(new_lookaheads));

		  /* add/merge item into the set */
		  add_itm = add(new_itm);
		  /* if propagation is needed link to that item */
		  if (need_prop)
		    itm.add_propagate(add_itm);

		  /* was this was a new item*/
		  if (add_itm == new_itm)
		    {
		      /* that may need further closure, consider it also */ 
		      consider.add(new_itm);
		    } 
		} 
	    } 
	} 
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Equality comparison. */
  public boolean equals(lalr_item_set other)
    {
      if (other == null || other.size() != size()) return false;

      /* once we know they are the same size, then improper subset does test */
      try {
        return is_subset_of(other);
      } catch (internal_error e) {
	/* can't throw error from here (because superclass doesn't) so crash */
	e.crash();
	return false;
      }

    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Generic equality comparison. */
  public boolean equals(Object other)
    {
      if (!(other instanceof lalr_item_set))
	return false;
      else
	return equals((lalr_item_set)other);
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Return hash code. */
  public int hashCode()
    {
      int result = 0;
      Enumeration e;
      int cnt;

      /* only compute a new one if we don't have it cached */
      if (hashcode_cache == null)
	{
          /* hash together codes from at most first 5 elements */
	  //   CSA fix! we'd *like* to hash just a few elements, but
	  //   that means equal sets will have inequal hashcodes, which
	  //   we're not allowed (by contract) to do.  So hash them all.
          for (e = all(), cnt=0 ; e.hasMoreElements() /*&& cnt<5*/; cnt++)
	    result ^= ((lalr_item)e.nextElement()).hashCode();

	  hashcode_cache = new Integer(result);
	}

      return hashcode_cache.intValue();
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Convert to string. */
  public String toString()
    {
      StringBuffer result = new StringBuffer();

      result.append("{\n");
      for (Enumeration e=all(); e.hasMoreElements(); ) 
 	{
 	  result.append("  " + (lalr_item)e.nextElement() + "\n");
 	}
       result.append("}");

       return result.toString();
    }
    /*-----------------------------------------------------------*/
}

java_cup/lalr_state.java100640  31676    763       73753  6746333325  15551 0ustar  cananiancananian
package java_cup;

import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Stack;

/** This class represents a state in the LALR viable prefix recognition machine.
 *  A state consists of an LALR item set and a set of transitions to other 
 *  states under terminal and non-terminal symbols.  Each state represents
 *  a potential configuration of the parser.  If the item set of a state 
 *  includes an item such as: <pre>
 *    [A ::= B * C d E , {a,b,c}]
 *  </pre> 
 *  this indicates that when the parser is in this state it is currently 
 *  looking for an A of the given form, has already seen the B, and would
 *  expect to see an a, b, or c after this sequence is complete.  Note that
 *  the parser is normally looking for several things at once (represented
 *  by several items).  In our example above, the state would also include
 *  items such as: <pre>
 *    [C ::= * X e Z, {d}]
 *    [X ::= * f, {e}]
 *  </pre> 
 *  to indicate that it was currently looking for a C followed by a d (which
 *  would be reduced into a C, matching the first symbol in our production 
 *  above), and the terminal f followed by e.<p>
 *
 *  At runtime, the parser uses a viable prefix recognition machine made up
 *  of these states to parse.  The parser has two operations, shift and reduce.
 *  In a shift, it consumes one Symbol and makes a transition to a new state.
 *  This corresponds to "moving the dot past" a terminal in one or more items
 *  in the state (these new shifted items will then be found in the state at
 *  the end of the transition).  For a reduce operation, the parser is 
 *  signifying that it is recognizing the RHS of some production.  To do this
 *  it first "backs up" by popping a stack of previously saved states.  It 
 *  pops off the same number of states as are found in the RHS of the 
 *  production.  This leaves the machine in the same state is was in when the
 *  parser first attempted to find the RHS.  From this state it makes a 
 *  transition based on the non-terminal on the LHS of the production.  This
 *  corresponds to placing the parse in a configuration equivalent to having 
 *  replaced all the symbols from the the input corresponding to the RHS with 
 *  the symbol on the LHS.
 *
 * @see     java_cup.lalr_item
 * @see     java_cup.lalr_item_set
 * @see     java_cup.lalr_transition
 * @version last updated: 7/3/96
 * @author  Frank Flannery
 *  
 */

public class lalr_state {
  /*-----------------------------------------------------------*/
  /*--- Constructor(s) ----------------------------------------*/
  /*-----------------------------------------------------------*/
       
  /** Constructor for building a state from a set of items.
   * @param itms the set of items that makes up this state.
   */
  public lalr_state(lalr_item_set itms) throws internal_error
   {
     /* don't allow null or duplicate item sets */
     if (itms == null)
       throw new internal_error(
	 "Attempt to construct an LALR state from a null item set");

     if (find_state(itms) != null)
       throw new internal_error(
	 "Attempt to construct a duplicate LALR state");

     /* assign a unique index */
      _index = next_index++;

     /* store the items */
     _items = itms;

     /* add to the global collection, keyed with its item set */
     _all.put(_items,this);
   }

  /*-----------------------------------------------------------*/
  /*--- (Access to) Static (Class) Variables ------------------*/
  /*-----------------------------------------------------------*/

  /** Collection of all states. */
  protected static Hashtable _all = new Hashtable();

  /** Collection of all states. */
  public static Enumeration all() {return _all.elements();}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Indicate total number of states there are. */
  public static int number() {return _all.size();}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Hash table to find states by their kernels (i.e, the original, 
   *  unclosed, set of items -- which uniquely define the state).  This table 
   *  stores state objects using (a copy of) their kernel item sets as keys. 
   */
  protected static Hashtable _all_kernels = new Hashtable();

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Find and return state with a given a kernel item set (or null if not 
   *  found).  The kernel item set is the subset of items that were used to
   *  originally create the state.  These items are formed by "shifting the
   *  dot" within items of other states that have a transition to this one.
   *  The remaining elements of this state's item set are added during closure.
   * @param itms the kernel set of the state we are looking for. 
   */
  public static lalr_state find_state(lalr_item_set itms)
    {
      if (itms == null) 
  	return null;
      else
  	return (lalr_state)_all.get(itms);
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Static counter for assigning unique state indexes. */
  protected static int next_index = 0;

  /*-----------------------------------------------------------*/
  /*--- (Access to) Instance Variables ------------------------*/
  /*-----------------------------------------------------------*/

  /** The item set for this state. */
  protected lalr_item_set _items;

  /** The item set for this state. */
  public lalr_item_set items() {return _items;}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** List of transitions out of this state. */
  protected lalr_transition _transitions = null;

  /** List of transitions out of this state. */
  public lalr_transition transitions() {return _transitions;}

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Index of this state in the parse tables */
  protected int _index;

  /** Index of this state in the parse tables */
  public int index() {return _index;}

  /*-----------------------------------------------------------*/
  /*--- Static Methods ----------------------------------------*/
  /*-----------------------------------------------------------*/

  /** Helper routine for debugging -- produces a dump of the given state
    * onto System.out.
    */
  protected static void dump_state(lalr_state st) throws internal_error
    {
      lalr_item_set itms;
      lalr_item itm;
      production_part part;

      if (st == null) 
	{
	  System.out.println("NULL lalr_state");
	  return;
	}

      System.out.println("lalr_state [" + st.index() + "] {");
      itms = st.items();
      for (Enumeration e = itms.all(); e.hasMoreElements(); )
	{
	  itm = (lalr_item)e.nextElement();
	  System.out.print("  [");
	  System.out.print(itm.the_production().lhs().the_symbol().name());
	  System.out.print(" ::= ");
	  for (int i = 0; i<itm.the_production().rhs_length(); i++)
	    {
	      if (i == itm.dot_pos()) System.out.print("(*) ");
	      part = itm.the_production().rhs(i);
	      if (part.is_action()) 
		System.out.print("{action} ");
	      else
		System.out.print(((symbol_part)part).the_symbol().name() + " ");
	    }
	  if (itm.dot_at_end()) System.out.print("(*) ");
	  System.out.println("]");
	}
      System.out.println("}");
    }

  /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

  /** Propagate lookahead sets through the constructed viable prefix 
   *  recognizer.  When the machine is constructed, each item that results
      in the creation of another such that its lookahead is included in the
      other's will have a propagate link set up for it.  This allows additions
      to the lookahead of one item to be included in other items that it 
      was used to directly or indirectly cr