Преглед на файлове

Added the jay directory, compiler should be okay now.

svn path=/trunk/mcs/; revision=138
Sean MacIsaac преди 24 години
родител
ревизия
d021bf6bad
променени са 26 файла, в които са добавени 7338 реда и са изтрити 5 реда
  1. 1 0
      mcs/class/System/.cvsignore
  2. 1 0
      mcs/class/corlib/.cvsignore
  3. 25 0
      mcs/jay/ACKNOWLEDGEMENTS
  4. 46 0
      mcs/jay/NEW_FEATURES
  5. 9 0
      mcs/jay/NOTES
  6. 55 0
      mcs/jay/README
  7. 295 0
      mcs/jay/closure.c
  8. 308 0
      mcs/jay/defs.h
  9. 11 0
      mcs/jay/depend
  10. 335 0
      mcs/jay/error.c
  11. 120 0
      mcs/jay/jay.1
  12. BIN
      mcs/jay/jay.cygwin
  13. 678 0
      mcs/jay/lalr.c
  14. 637 0
      mcs/jay/lr0.c
  15. 337 0
      mcs/jay/main.c
  16. 10 0
      mcs/jay/makefile
  17. 395 0
      mcs/jay/mkpar.c
  18. 1173 0
      mcs/jay/output.c
  19. 1627 0
      mcs/jay/reader.c
  20. 268 0
      mcs/jay/skeleton
  21. 351 0
      mcs/jay/skeleton.cs
  22. 158 0
      mcs/jay/symtab.c
  23. 366 0
      mcs/jay/verbose.c
  24. 122 0
      mcs/jay/warshall.c
  25. 3 0
      mcs/mcs/.cvsignore
  26. 7 5
      mcs/mcs/makefile

+ 1 - 0
mcs/class/System/.cvsignore

@@ -0,0 +1 @@
+System.dll

+ 1 - 0
mcs/class/corlib/.cvsignore

@@ -0,0 +1 @@
+corlib.dll

+ 25 - 0
mcs/jay/ACKNOWLEDGEMENTS

@@ -0,0 +1,25 @@
+     Berkeley Yacc owes much to the unflagging efforts of Keith Bostic.
+His badgering kept me working on it long after I was ready to quit.
+
+     Berkeley Yacc is based on the excellent algorithm for computing LALR(1)
+lookaheads developed by Tom Pennello and Frank DeRemer.  The algorithm is
+described in their almost impenetrable article in TOPLAS 4,4.
+
+     Finally, much of the credit for the latest version must go to those
+who pointed out deficiencies of my earlier releases.  Among the most
+prolific contributors were
+
+	  Benson I. Margulies
+	  Dave Gentzel
+	  Antoine Verheijen
+	  Peter S. Housel
+	  Dale Smith
+	  Ozan Yigit
+	  John Campbell
+	  Bill Sommerfeld
+	  Paul Hilfinger
+	  Gary Bridgewater
+	  Dave Bakken
+	  Dan Lanciani
+	  Richard Sargent
+	  Parag Patel

+ 46 - 0
mcs/jay/NEW_FEATURES

@@ -0,0 +1,46 @@
+     The -r option has been implemented.  The -r option tells Yacc to
+put the read-only tables in y.tab.c and the code and variables in
+y.code.c.  Keith Bostic asked for this option so that :yyfix could be
+eliminated.
+
+     The -l and -t options have been implemented.  The -l option tells
+Yacc not to include #line directives in the code it produces.  The -t
+option causes debugging code to be included in the compiled parser.
+
+     The code for error recovery has been changed to implement the same
+algorithm as AT&T Yacc.  There will still be differences in the way
+error recovery works because AT&T Yacc uses more default reductions
+than Berkeley Yacc.
+
+     The environment variable TMPDIR determines the directory where
+temporary files will be created.  If TMPDIR is defined, temporary files
+will be created in the directory whose pathname is the value of TMPDIR.
+By default, temporary files are created in /tmp.
+
+     The keywords are now case-insensitive.  For example, %nonassoc,
+%NONASSOC, %NonAssoc, and %nOnAsSoC are all equivalent.
+
+     Commas and semicolons that are not part of C code are treated as
+commentary.
+
+     Line-end comments, as in BCPL, are permitted.  Line-end comments
+begin with // and end at the next end-of-line.  Line-end comments are
+permitted in C code; they are converted to C comments on output.
+
+     The form of y.output files has been changed to look more like
+those produced by AT&T Yacc.
+
+     A new kind of declaration has been added.  The form of the declaration
+is
+
+	  %ident string
+
+where string is a sequence of characters begining with a double quote
+and ending with either a double quote or the next end-of-line, whichever
+comes first.  The declaration will cause a #ident directive to be written
+near the start of the output file.
+
+     If a parser has been compiled with debugging code, that code can be
+enabled by setting an environment variable.  If the environment variable
+YYDEBUG is set to 0, debugging output is suppressed.  If it is set to 1,
+debugging output is written to standard output.

+ 9 - 0
mcs/jay/NOTES

@@ -0,0 +1,9 @@
+Berkeley Yacc reflects its origins.  The reason so many routines
+use exactly six register variables is that Berkeley Yacc was
+developed on a VAX using PCC.  PCC placed at most six variables
+in registers.  I went to considerable effort to find which six
+variables most belonged in registers.  Changes in machines and
+compilers make that effort worthless, perhaps even harmful.
+
+The code contains many instances where address calculations are
+performed in particular ways to optimize the code for the VAX.

+ 55 - 0
mcs/jay/README

@@ -0,0 +1,55 @@
+    This version of Berkeley Yacc was taken from the BSD-Lite CD and targeted
+to Java by
+
+			[email protected]
+
+Makefile -> makefile	removed Berkeleyisms, call it jay
+defs.h			eliminate -dlpr options, %union, output_file, #ident
+			eliminate sekeleton.c references
+error.c			eliminate %union
+main.c			eliminate -dlpr options, %union, output_file
+output.c		eliminate -dlpr options, %union, output_file
+			fix #define, short, -t/yyDebug
+			respell YYERRCODE, YYTABLESIZE, YYFINAL, YYMAXTOKEN
+			output trailer last
+			switch to filter behaviour
+reader.c		eliminate output_file, #ident
+			#line -> // line, pass //
+			yyvsp[] -> yyVals[yyTop], yyval -> yyVal
+skeleton.c -> skeleton	Java skeleton
+test			removed
+yacc.1 -> jay.1		adapted
+yyfix.*			removed
+
+Types: there is a significant difference. yacc uses %union to cast the value
+stack and <tag> to select alternatives. This works for l- and r-values alike.
+jay uses Object as the value stack and <tag> to set a class. l-values must not
+be cast. $n should not be assigned to, but $$ usually is. $n is referenced,
+but $$ usually is not. Consequently jay casts $n and $<tag>$ but not $<>n
+and $$. This makes assignment to $n references to $$ kludgily possible.
+As another kludge, to prevent 'untyped' messages and to avoid unnecessary
+casts, casts to "Object" are not emitted.
+-------------------------------------------------------------------------------
+    Berkeley Yacc is an LALR(1) parser generator.  Berkeley Yacc has been made
+as compatible as possible with AT&T Yacc.  Berkeley Yacc can accept any input
+specification that conforms to the AT&T Yacc documentation.  Specifications
+that take advantage of undocumented features of AT&T Yacc will probably be
+rejected.
+
+    Berkeley Yacc is distributed with no warranty whatever.  The code is certain
+to contain errors.  Neither the author nor any contributor takes responsibility
+for any consequences of its use.
+
+    Berkeley Yacc is in the public domain.  The data structures and algorithms
+used in Berkeley Yacc are all either taken from documents available to the
+general public or are inventions of the author.  Anyone may freely distribute
+source or binary forms of Berkeley Yacc whether unchanged or modified.
+Distributers may charge whatever fees they can obtain for Berkeley Yacc.
+Programs generated by Berkeley Yacc may be distributed freely.
+
+    Please report bugs to
+
+			[email protected]
+
+Include a small example if possible.  Please include the banner string from
+skeleton.c with the bug report.  Do not expect rapid responses.

+ 295 - 0
mcs/jay/closure.c

@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)closure.c	5.3 (Berkeley) 5/24/93";
+#endif /* not lint */
+
+#include "defs.h"
+
+short *itemset;
+short *itemsetend;
+unsigned *ruleset;
+
+static unsigned *first_derives;
+static unsigned *EFF;
+
+
+set_EFF()
+{
+    register unsigned *row;
+    register int symbol;
+    register short *sp;
+    register int rowsize;
+    register int i;
+    register int rule;
+
+    rowsize = WORDSIZE(nvars);
+    EFF = NEW2(nvars * rowsize, unsigned);
+
+    row = EFF;
+    for (i = start_symbol; i < nsyms; i++)
+    {
+	sp = derives[i];
+	for (rule = *sp; rule > 0; rule = *++sp)
+	{
+	    symbol = ritem[rrhs[rule]];
+	    if (ISVAR(symbol))
+	    {
+		symbol -= start_symbol;
+		SETBIT(row, symbol);
+	    }
+	}
+	row += rowsize;
+    }
+
+    reflexive_transitive_closure(EFF, nvars);
+
+#ifdef	DEBUG
+    print_EFF();
+#endif
+}
+
+
+set_first_derives()
+{
+    register unsigned *rrow;
+    register unsigned *vrow;
+    register int j;
+    register unsigned k;
+    register unsigned cword;
+    register short *rp;
+
+    int rule;
+    int i;
+    int rulesetsize;
+    int varsetsize;
+
+    rulesetsize = WORDSIZE(nrules);
+    varsetsize = WORDSIZE(nvars);
+    first_derives = NEW2(nvars * rulesetsize, unsigned) - ntokens * rulesetsize;
+
+    set_EFF();
+
+    rrow = first_derives + ntokens * rulesetsize;
+    for (i = start_symbol; i < nsyms; i++)
+    {
+	vrow = EFF + ((i - ntokens) * varsetsize);
+	k = BITS_PER_WORD;
+	for (j = start_symbol; j < nsyms; k++, j++)
+	{
+	    if (k >= BITS_PER_WORD)
+	    {
+		cword = *vrow++;
+		k = 0;
+	    }
+
+	    if (cword & (1 << k))
+	    {
+		rp = derives[j];
+		while ((rule = *rp++) >= 0)
+		{
+		    SETBIT(rrow, rule);
+		}
+	    }
+	}
+
+	vrow += varsetsize;
+	rrow += rulesetsize;
+    }
+
+#ifdef	DEBUG
+    print_first_derives();
+#endif
+
+    FREE(EFF);
+}
+
+
+closure(nucleus, n)
+short *nucleus;
+int n;
+{
+    register int ruleno;
+    register unsigned word;
+    register unsigned i;
+    register short *csp;
+    register unsigned *dsp;
+    register unsigned *rsp;
+    register int rulesetsize;
+
+    short *csend;
+    unsigned *rsend;
+    int symbol;
+    int itemno;
+
+    rulesetsize = WORDSIZE(nrules);
+    rsp = ruleset;
+    rsend = ruleset + rulesetsize;
+    for (rsp = ruleset; rsp < rsend; rsp++)
+	*rsp = 0;
+
+    csend = nucleus + n;
+    for (csp = nucleus; csp < csend; ++csp)
+    {
+	symbol = ritem[*csp];
+	if (ISVAR(symbol))
+	{
+	    dsp = first_derives + symbol * rulesetsize;
+	    rsp = ruleset;
+	    while (rsp < rsend)
+		*rsp++ |= *dsp++;
+	}
+    }
+
+    ruleno = 0;
+    itemsetend = itemset;
+    csp = nucleus;
+    for (rsp = ruleset; rsp < rsend; ++rsp)
+    {
+	word = *rsp;
+	if (word)
+	{
+	    for (i = 0; i < BITS_PER_WORD; ++i)
+	    {
+		if (word & (1 << i))
+		{
+		    itemno = rrhs[ruleno+i];
+		    while (csp < csend && *csp < itemno)
+			*itemsetend++ = *csp++;
+		    *itemsetend++ = itemno;
+		    while (csp < csend && *csp == itemno)
+			++csp;
+		}
+	    }
+	}
+	ruleno += BITS_PER_WORD;
+    }
+
+    while (csp < csend)
+	*itemsetend++ = *csp++;
+
+#ifdef	DEBUG
+  print_closure(n);
+#endif
+}
+
+
+
+finalize_closure()
+{
+  FREE(itemset);
+  FREE(ruleset);
+  FREE(first_derives + ntokens * WORDSIZE(nrules));
+}
+
+
+#ifdef	DEBUG
+
+print_closure(n)
+int n;
+{
+  register short *isp;
+
+  printf("\n\nn = %d\n\n", n);
+  for (isp = itemset; isp < itemsetend; isp++)
+    printf("   %d\n", *isp);
+}
+
+
+print_EFF()
+{
+    register int i, j;
+    register unsigned *rowp;
+    register unsigned word;
+    register unsigned k;
+
+    printf("\n\nEpsilon Free Firsts\n");
+
+    for (i = start_symbol; i < nsyms; i++)
+    {
+	printf("\n%s", symbol_name[i]);
+	rowp = EFF + ((i - start_symbol) * WORDSIZE(nvars));
+	word = *rowp++;
+
+	k = BITS_PER_WORD;
+	for (j = 0; j < nvars; k++, j++)
+	{
+	    if (k >= BITS_PER_WORD)
+	    {
+		word = *rowp++;
+		k = 0;
+	    }
+
+	    if (word & (1 << k))
+		printf("  %s", symbol_name[start_symbol + j]);
+	}
+    }
+}
+
+
+print_first_derives()
+{
+    register int i;
+    register int j;
+    register unsigned *rp;
+    register unsigned cword;
+    register unsigned k;
+
+    printf("\n\n\nFirst Derives\n");
+
+    for (i = start_symbol; i < nsyms; i++)
+    {
+	printf("\n%s derives\n", symbol_name[i]);
+	rp = first_derives + i * WORDSIZE(nrules);
+	k = BITS_PER_WORD;
+	for (j = 0; j <= nrules; k++, j++)
+        {
+	  if (k >= BITS_PER_WORD)
+	  {
+	      cword = *rp++;
+	      k = 0;
+	  }
+
+	  if (cword & (1 << k))
+	    printf("   %d\n", j);
+	}
+    }
+
+  fflush(stdout);
+}
+
+#endif

+ 308 - 0
mcs/jay/defs.h

@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)defs.h	5.6 (Berkeley) 5/24/93
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+
+
+/*  machine-dependent definitions			*/
+/*  the following definitions are for the Tahoe		*/
+/*  they might have to be changed for other machines	*/
+
+/*  MAXCHAR is the largest unsigned character value	*/
+/*  MAXSHORT is the largest value of a C short		*/
+/*  MINSHORT is the most negative value of a C short	*/
+/*  MAXTABLE is the maximum table size			*/
+/*  BITS_PER_WORD is the number of bits in a C unsigned	*/
+/*  WORDSIZE computes the number of words needed to	*/
+/*	store n bits					*/
+/*  BIT returns the value of the n-th bit starting	*/
+/*	from r (0-indexed)				*/
+/*  SETBIT sets the n-th bit starting from r		*/
+
+#define	MAXCHAR		255
+#define	MAXSHORT	32767
+#define MINSHORT	-32768
+#define MAXTABLE	32500
+#define BITS_PER_WORD	32
+#define	WORDSIZE(n)	(((n)+(BITS_PER_WORD-1))/BITS_PER_WORD)
+#define	BIT(r, n)	((((r)[(n)>>5])>>((n)&31))&1)
+#define	SETBIT(r, n)	((r)[(n)>>5]|=((unsigned)1<<((n)&31)))
+
+
+/*  character names  */
+
+#define	NUL		'\0'    /*  the null character  */
+#define	NEWLINE		'\n'    /*  line feed  */
+#define	SP		' '     /*  space  */
+#define	BS		'\b'    /*  backspace  */
+#define	HT		'\t'    /*  horizontal tab  */
+#define	VT		'\013'  /*  vertical tab  */
+#define	CR		'\r'    /*  carriage return  */
+#define	FF		'\f'    /*  form feed  */
+#define	QUOTE		'\''    /*  single quote  */
+#define	DOUBLE_QUOTE	'\"'    /*  double quote  */
+#define	BACKSLASH	'\\'    /*  backslash  */
+
+
+/* defines for constructing filenames */
+
+#define CODE_SUFFIX	".code.c"
+#define	DEFINES_SUFFIX	".tab.h"
+#define	OUTPUT_SUFFIX	".tab.c"
+#define	VERBOSE_SUFFIX	".output"
+
+
+/* keyword codes */
+
+#define TOKEN 0
+#define LEFT 1
+#define RIGHT 2
+#define NONASSOC 3
+#define MARK 4
+#define TEXT 5
+#define TYPE 6
+#define START 7
+
+
+/*  symbol classes  */
+
+#define UNKNOWN 0
+#define TERM 1
+#define NONTERM 2
+
+
+/*  the undefined value  */
+
+#define UNDEFINED (-1)
+
+
+/*  action codes  */
+
+#define SHIFT 1
+#define REDUCE 2
+
+
+/*  character macros  */
+
+#define IS_IDENT(c)	(isalnum(c) || (c) == '_' || (c) == '.' || (c) == '$')
+#define	IS_OCTAL(c)	((c) >= '0' && (c) <= '7')
+#define	NUMERIC_VALUE(c)	((c) - '0')
+
+
+/*  symbol macros  */
+
+#define ISTOKEN(s)	((s) < start_symbol)
+#define ISVAR(s)	((s) >= start_symbol)
+
+
+/*  storage allocation macros  */
+
+#define CALLOC(k,n)	(calloc((unsigned)(k),(unsigned)(n)))
+#define	FREE(x)		(free((char*)(x)))
+#define MALLOC(n)	(malloc((unsigned)(n)))
+#define	NEW(t)		((t*)allocate(sizeof(t)))
+#define	NEW2(n,t)	((t*)allocate((unsigned)((n)*sizeof(t))))
+#define REALLOC(p,n)	(realloc((char*)(p),(unsigned)(n)))
+
+
+/*  the structure of a symbol table entry  */
+
+typedef struct bucket bucket;
+struct bucket
+{
+    struct bucket *link;
+    struct bucket *next;
+    char *name;
+    char *tag;
+    short value;
+    short index;
+    short prec;
+    char class;
+    char assoc;
+};
+
+
+/*  the structure of the LR(0) state machine  */
+
+typedef struct core core;
+struct core
+{
+    struct core *next;
+    struct core *link;
+    short number;
+    short accessing_symbol;
+    short nitems;
+    short items[1];
+};
+
+
+/*  the structure used to record shifts  */
+
+typedef struct shifts shifts;
+struct shifts
+{
+    struct shifts *next;
+    short number;
+    short nshifts;
+    short shift[1];
+};
+
+
+/*  the structure used to store reductions  */
+
+typedef struct reductions reductions;
+struct reductions
+{
+    struct reductions *next;
+    short number;
+    short nreds;
+    short rules[1];
+};
+
+
+/*  the structure used to represent parser actions  */
+
+typedef struct action action;
+struct action
+{
+    struct action *next;
+    short symbol;
+    short number;
+    short prec;
+    char action_code;
+    char assoc;
+    char suppressed;
+};
+
+
+/* global variables */
+
+extern char tflag;
+extern char vflag;
+
+extern char *myname;
+extern char *cptr;
+extern char *line;
+extern int lineno;
+extern int outline;
+
+extern char *action_file_name;
+extern char *input_file_name;
+extern char *prolog_file_name;
+extern char *local_file_name;
+extern char *verbose_file_name;
+
+extern FILE *action_file;
+extern FILE *input_file;
+extern FILE *prolog_file;
+extern FILE *local_file;
+extern FILE *verbose_file;
+
+extern int nitems;
+extern int nrules;
+extern int nsyms;
+extern int ntokens;
+extern int nvars;
+extern int ntags;
+
+extern char *line_format;
+
+extern int   start_symbol;
+extern char  **symbol_name;
+extern short *symbol_value;
+extern short *symbol_prec;
+extern char  *symbol_assoc;
+
+extern short *ritem;
+extern short *rlhs;
+extern short *rrhs;
+extern short *rprec;
+extern char  *rassoc;
+
+extern short **derives;
+extern char *nullable;
+
+extern bucket *first_symbol;
+extern bucket *last_symbol;
+
+extern int nstates;
+extern core *first_state;
+extern shifts *first_shift;
+extern reductions *first_reduction;
+extern short *accessing_symbol;
+extern core **state_table;
+extern shifts **shift_table;
+extern reductions **reduction_table;
+extern unsigned *LA;
+extern short *LAruleno;
+extern short *lookaheads;
+extern short *goto_map;
+extern short *from_state;
+extern short *to_state;
+
+extern action **parser;
+extern int SRtotal;
+extern int RRtotal;
+extern short *SRconflicts;
+extern short *RRconflicts;
+extern short *defred;
+extern short *rules_used;
+extern short nunused;
+extern short final_state;
+
+/* global functions */
+
+extern char *allocate();
+extern bucket *lookup();
+extern bucket *make_bucket();
+
+
+/* system variables */
+
+extern int errno;
+
+
+/* system functions */
+
+extern void free();
+extern char *calloc();
+extern char *malloc();
+extern char *realloc();
+extern char *strcpy();

+ 11 - 0
mcs/jay/depend

@@ -0,0 +1,11 @@
+closure.o: closure.c defs.h
+error.o: error.c defs.h
+lalr.o: lalr.c defs.h
+lr0.o: lr0.c defs.h
+main.o: main.c defs.h
+mkpar.o: mkpar.c defs.h
+output.o: output.c defs.h
+reader.o: reader.c defs.h
+symtab.o: symtab.c defs.h
+verbose.o: verbose.c defs.h
+warshall.o: warshall.c defs.h

+ 335 - 0
mcs/jay/error.c

@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)error.c	5.3 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+/* routines for printing error messages  */
+
+#include "defs.h"
+
+
+fatal(msg)
+char *msg;
+{
+    fprintf(stderr, "%s: f - %s\n", myname, msg);
+    done(2);
+}
+
+
+no_space()
+{
+    fprintf(stderr, "%s: f - out of space\n", myname);
+    done(2);
+}
+
+
+open_error(filename)
+char *filename;
+{
+    fprintf(stderr, "%s: f - cannot open \"%s\"\n", myname, filename);
+    done(2);
+}
+
+
+unexpected_EOF()
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", unexpected end-of-file\n",
+	    myname, lineno, input_file_name);
+    done(1);
+}
+
+
+print_pos(st_line, st_cptr)
+char *st_line;
+char *st_cptr;
+{
+    register char *s;
+
+    if (st_line == 0) return;
+    for (s = st_line; *s != '\n'; ++s)
+    {
+	if (isprint(*s) || *s == '\t')
+	    putc(*s, stderr);
+	else
+	    putc('?', stderr);
+    }
+    putc('\n', stderr);
+    for (s = st_line; s < st_cptr; ++s)
+    {
+	if (*s == '\t')
+	    putc('\t', stderr);
+	else
+	    putc(' ', stderr);
+    }
+    putc('^', stderr);
+    putc('\n', stderr);
+}
+
+
+syntax_error(st_lineno, st_line, st_cptr)
+int st_lineno;
+char *st_line;
+char *st_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", syntax error\n",
+	    myname, st_lineno, input_file_name);
+    print_pos(st_line, st_cptr);
+    done(1);
+}
+
+
+unterminated_comment(c_lineno, c_line, c_cptr)
+int c_lineno;
+char *c_line;
+char *c_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", unmatched /*\n",
+	    myname, c_lineno, input_file_name);
+    print_pos(c_line, c_cptr);
+    done(1);
+}
+
+
+unterminated_string(s_lineno, s_line, s_cptr)
+int s_lineno;
+char *s_line;
+char *s_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", unterminated string\n",
+	    myname, s_lineno, input_file_name);
+    print_pos(s_line, s_cptr);
+    done(1);
+}
+
+
+unterminated_text(t_lineno, t_line, t_cptr)
+int t_lineno;
+char *t_line;
+char *t_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", unmatched %%{\n",
+	    myname, t_lineno, input_file_name);
+    print_pos(t_line, t_cptr);
+    done(1);
+}
+
+
+illegal_tag(t_lineno, t_line, t_cptr)
+int t_lineno;
+char *t_line;
+char *t_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", illegal tag\n",
+	    myname, t_lineno, input_file_name);
+    print_pos(t_line, t_cptr);
+    done(1);
+}
+
+
+illegal_character(c_cptr)
+char *c_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", illegal character\n",
+	    myname, lineno, input_file_name);
+    print_pos(line, c_cptr);
+    done(1);
+}
+
+
+used_reserved(s)
+char *s;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", illegal use of reserved symbol \
+%s\n", myname, lineno, input_file_name, s);
+    done(1);
+}
+
+
+tokenized_start(s)
+char *s;
+{
+     fprintf(stderr, "%s: e - line %d of \"%s\", the start symbol %s cannot be \
+declared to be a token\n", myname, lineno, input_file_name, s);
+     done(1);
+}
+
+
+retyped_warning(s)
+char *s;
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", the type of %s has been \
+redeclared\n", myname, lineno, input_file_name, s);
+}
+
+
+reprec_warning(s)
+char *s;
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", the precedence of %s has been \
+redeclared\n", myname, lineno, input_file_name, s);
+}
+
+
+revalued_warning(s)
+char *s;
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", the value of %s has been \
+redeclared\n", myname, lineno, input_file_name, s);
+}
+
+
+terminal_start(s)
+char *s;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", the start symbol %s is a \
+token\n", myname, lineno, input_file_name, s);
+    done(1);
+}
+
+
+restarted_warning()
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", the start symbol has been \
+redeclared\n", myname, lineno, input_file_name);
+}
+
+
+no_grammar()
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", no grammar has been \
+specified\n", myname, lineno, input_file_name);
+    done(1);
+}
+
+
+terminal_lhs(s_lineno)
+int s_lineno;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", a token appears on the lhs \
+of a production\n", myname, s_lineno, input_file_name);
+    done(1);
+}
+
+
+prec_redeclared()
+{
+    fprintf(stderr, "%s: w - line %d of  \"%s\", conflicting %%prec \
+specifiers\n", myname, lineno, input_file_name);
+}
+
+
+unterminated_action(a_lineno, a_line, a_cptr)
+int a_lineno;
+char *a_line;
+char *a_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", unterminated action\n",
+	    myname, a_lineno, input_file_name);
+    print_pos(a_line, a_cptr);
+    done(1);
+}
+
+
+dollar_warning(a_lineno, i)
+int a_lineno;
+int i;
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", $%d references beyond the \
+end of the current rule\n", myname, a_lineno, input_file_name, i);
+}
+
+
+dollar_error(a_lineno, a_line, a_cptr)
+int a_lineno;
+char *a_line;
+char *a_cptr;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", illegal $-name\n",
+	    myname, a_lineno, input_file_name);
+    print_pos(a_line, a_cptr);
+    done(1);
+}
+
+
+untyped_lhs()
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", $$ is untyped\n",
+	    myname, lineno, input_file_name);
+    /** done(1); */
+}
+
+
+untyped_rhs(i, s)
+int i;
+char *s;
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", $%d (%s) is untyped\n",
+	    myname, lineno, input_file_name, i, s);
+    /** done(1); */
+}
+
+
+unknown_rhs(i)
+int i;
+{
+    fprintf(stderr, "%s: e - line %d of \"%s\", $%d is untyped\n",
+	    myname, lineno, input_file_name, i);
+    done(1);
+}
+
+
+default_action_warning()
+{
+    fprintf(stderr, "%s: w - line %d of \"%s\", the default action assigns an \
+undefined value to $$\n", myname, lineno, input_file_name);
+}
+
+
+undefined_goal(s)
+char *s;
+{
+    fprintf(stderr, "%s: e - the start symbol %s is undefined\n", myname, s);
+    done(1);
+}
+
+
+undefined_symbol_warning(s)
+char *s;
+{
+    fprintf(stderr, "%s: w - the symbol %s is undefined\n", myname, s);
+}

+ 120 - 0
mcs/jay/jay.1

@@ -0,0 +1,120 @@
+.\" Copyright (c) 1989, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Robert Paul Corbett.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"	This product includes software developed by the University of
+.\"	California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)yacc.1	5.8 (Berkeley) 5/24/93
+.\"
+.TH JAY 1 "May 24, 1993 / July 8, 1998"
+.UC 6
+.SH NAME
+jay \- an LALR(1) parser generator for Java and C#
+.SH SYNOPSIS
+.B jay [ -tv ] [ -c ] [ -b
+.I file_prefix
+.B ] [ -V
+.I yyValue
+.B ]
+.I filename
+.B <
+.I skeleton
+.SH DESCRIPTION
+.I Jay
+reads the grammar specification in the file
+.I filename
+and generates an LR(1) parser for it.
+The parsers consist of a set of LALR(1) parsing tables and a driver routine
+from the file
+.I skeleton
+written in the Java programming language.
+.I Jay
+writes the parse tables and the driver routine to standard output.
+.PP
+The following options are available:
+.RS
+.TP
+\fB-b \fIfile_prefix\fR
+The
+.B -b
+option changes the prefix prepended to the output file names to
+the string denoted by
+.IR file_prefix.
+The default prefix is the character
+.IR y.
+.TP
+.B -c
+The
+.B -c 
+option makes jay generate C# code instead of the default Java.
+.TP
+.B -t
+The
+.B -t
+option arranges for
+debugging information to be incorporated in the compiled code.
+.TP
+.B -v
+The
+.B -v
+option causes a human-readable description of the generated parser to
+be written to the file
+.IR y.output.
+.RE
+.PP
+If the environment variable TMPDIR is set, the string denoted by
+TMPDIR will be used as the name of the directory where the temporary
+files are created.
+.SH FILES
+.IR skeleton
+.br
+.IR y.output
+.br
+.IR /tmp/yacc.aXXXXXX
+.br
+.IR /tmp/yacc.tXXXXXX
+.br
+.IR /tmp/yacc.uXXXXXX
+.SH DIAGNOSTICS
+If there are rules that are never reduced, the number of such rules is
+reported on standard error.
+If there are any LALR(1) conflicts, the number of conflicts is reported
+on standard error.
+.SH HISTORY
+.I Jay
+is derived from Berkeley
+.I yacc .
+Input conventions closely follow those of
+.I yacc ;
+for details,
+consult the parser
+.I skeleton
+file and the commented example included with the sources.

BIN
mcs/jay/jay.cygwin


+ 678 - 0
mcs/jay/lalr.c

@@ -0,0 +1,678 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)lalr.c	5.3 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+#include "defs.h"
+
+typedef
+  struct shorts
+    {
+      struct shorts *next;
+      short value;
+    }
+  shorts;
+
+int tokensetsize;
+short *lookaheads;
+short *LAruleno;
+unsigned *LA;
+short *accessing_symbol;
+core **state_table;
+shifts **shift_table;
+reductions **reduction_table;
+short *goto_map;
+short *from_state;
+short *to_state;
+
+short **transpose();
+
+static int infinity;
+static int maxrhs;
+static int ngotos;
+static unsigned *F;
+static short **includes;
+static shorts **lookback;
+static short **R;
+static short *INDEX;
+static short *VERTICES;
+static int top;
+
+
+lalr()
+{
+    tokensetsize = WORDSIZE(ntokens);
+
+    set_state_table();
+    set_accessing_symbol();
+    set_shift_table();
+    set_reduction_table();
+    set_maxrhs();
+    initialize_LA();
+    set_goto_map();
+    initialize_F();
+    build_relations();
+    compute_FOLLOWS();
+    compute_lookaheads();
+}
+
+
+
+set_state_table()
+{
+    register core *sp;
+
+    state_table = NEW2(nstates, core *);
+    for (sp = first_state; sp; sp = sp->next)
+	state_table[sp->number] = sp;
+}
+
+
+
+set_accessing_symbol()
+{
+    register core *sp;
+
+    accessing_symbol = NEW2(nstates, short);
+    for (sp = first_state; sp; sp = sp->next)
+	accessing_symbol[sp->number] = sp->accessing_symbol;
+}
+
+
+
+set_shift_table()
+{
+    register shifts *sp;
+
+    shift_table = NEW2(nstates, shifts *);
+    for (sp = first_shift; sp; sp = sp->next)
+	shift_table[sp->number] = sp;
+}
+
+
+
+set_reduction_table()
+{
+    register reductions *rp;
+
+    reduction_table = NEW2(nstates, reductions *);
+    for (rp = first_reduction; rp; rp = rp->next)
+	reduction_table[rp->number] = rp;
+}
+
+
+
+set_maxrhs()
+{
+  register short *itemp;
+  register short *item_end;
+  register int length;
+  register int max;
+
+  length = 0;
+  max = 0;
+  item_end = ritem + nitems;
+  for (itemp = ritem; itemp < item_end; itemp++)
+    {
+      if (*itemp >= 0)
+	{
+	  length++;
+	}
+      else
+	{
+	  if (length > max) max = length;
+	  length = 0;
+	}
+    }
+
+  maxrhs = max;
+}
+
+
+
+initialize_LA()
+{
+  register int i, j, k;
+  register reductions *rp;
+
+  lookaheads = NEW2(nstates + 1, short);
+
+  k = 0;
+  for (i = 0; i < nstates; i++)
+    {
+      lookaheads[i] = k;
+      rp = reduction_table[i];
+      if (rp)
+	k += rp->nreds;
+    }
+  lookaheads[nstates] = k;
+
+  LA = NEW2(k * tokensetsize, unsigned);
+  LAruleno = NEW2(k, short);
+  lookback = NEW2(k, shorts *);
+
+  k = 0;
+  for (i = 0; i < nstates; i++)
+    {
+      rp = reduction_table[i];
+      if (rp)
+	{
+	  for (j = 0; j < rp->nreds; j++)
+	    {
+	      LAruleno[k] = rp->rules[j];
+	      k++;
+	    }
+	}
+    }
+}
+
+
+set_goto_map()
+{
+  register shifts *sp;
+  register int i;
+  register int symbol;
+  register int k;
+  register short *temp_map;
+  register int state2;
+  register int state1;
+
+  goto_map = NEW2(nvars + 1, short) - ntokens;
+  temp_map = NEW2(nvars + 1, short) - ntokens;
+
+  ngotos = 0;
+  for (sp = first_shift; sp; sp = sp->next)
+    {
+      for (i = sp->nshifts - 1; i >= 0; i--)
+	{
+	  symbol = accessing_symbol[sp->shift[i]];
+
+	  if (ISTOKEN(symbol)) break;
+
+	  if (ngotos == MAXSHORT)
+	    fatal("too many gotos");
+
+	  ngotos++;
+	  goto_map[symbol]++;
+        }
+    }
+
+  k = 0;
+  for (i = ntokens; i < nsyms; i++)
+    {
+      temp_map[i] = k;
+      k += goto_map[i];
+    }
+
+  for (i = ntokens; i < nsyms; i++)
+    goto_map[i] = temp_map[i];
+
+  goto_map[nsyms] = ngotos;
+  temp_map[nsyms] = ngotos;
+
+  from_state = NEW2(ngotos, short);
+  to_state = NEW2(ngotos, short);
+
+  for (sp = first_shift; sp; sp = sp->next)
+    {
+      state1 = sp->number;
+      for (i = sp->nshifts - 1; i >= 0; i--)
+	{
+	  state2 = sp->shift[i];
+	  symbol = accessing_symbol[state2];
+
+	  if (ISTOKEN(symbol)) break;
+
+	  k = temp_map[symbol]++;
+	  from_state[k] = state1;
+	  to_state[k] = state2;
+	}
+    }
+
+  FREE(temp_map + ntokens);
+}
+
+
+
+/*  Map_goto maps a state/symbol pair into its numeric representation.	*/
+
+int
+map_goto(state, symbol)
+int state;
+int symbol;
+{
+    register int high;
+    register int low;
+    register int middle;
+    register int s;
+
+    low = goto_map[symbol];
+    high = goto_map[symbol + 1];
+
+    for (;;)
+    {
+	assert(low <= high);
+	middle = (low + high) >> 1;
+	s = from_state[middle];
+	if (s == state)
+	    return (middle);
+	else if (s < state)
+	    low = middle + 1;
+	else
+	    high = middle - 1;
+    }
+}
+
+
+
+initialize_F()
+{
+  register int i;
+  register int j;
+  register int k;
+  register shifts *sp;
+  register short *edge;
+  register unsigned *rowp;
+  register short *rp;
+  register short **reads;
+  register int nedges;
+  register int stateno;
+  register int symbol;
+  register int nwords;
+
+  nwords = ngotos * tokensetsize;
+  F = NEW2(nwords, unsigned);
+
+  reads = NEW2(ngotos, short *);
+  edge = NEW2(ngotos + 1, short);
+  nedges = 0;
+
+  rowp = F;
+  for (i = 0; i < ngotos; i++)
+    {
+      stateno = to_state[i];
+      sp = shift_table[stateno];
+
+      if (sp)
+	{
+	  k = sp->nshifts;
+
+	  for (j = 0; j < k; j++)
+	    {
+	      symbol = accessing_symbol[sp->shift[j]];
+	      if (ISVAR(symbol))
+		break;
+	      SETBIT(rowp, symbol);
+	    }
+
+	  for (; j < k; j++)
+	    {
+	      symbol = accessing_symbol[sp->shift[j]];
+	      if (nullable[symbol])
+		edge[nedges++] = map_goto(stateno, symbol);
+	    }
+	
+	  if (nedges)
+	    {
+	      reads[i] = rp = NEW2(nedges + 1, short);
+
+	      for (j = 0; j < nedges; j++)
+		rp[j] = edge[j];
+
+	      rp[nedges] = -1;
+	      nedges = 0;
+	    }
+	}
+
+      rowp += tokensetsize;
+    }
+
+  SETBIT(F, 0);
+  digraph(reads);
+
+  for (i = 0; i < ngotos; i++)
+    {
+      if (reads[i])
+	FREE(reads[i]);
+    }
+
+  FREE(reads);
+  FREE(edge);
+}
+
+
+
+build_relations()
+{
+  register int i;
+  register int j;
+  register int k;
+  register short *rulep;
+  register short *rp;
+  register shifts *sp;
+  register int length;
+  register int nedges;
+  register int done;
+  register int state1;
+  register int stateno;
+  register int symbol1;
+  register int symbol2;
+  register short *shortp;
+  register short *edge;
+  register short *states;
+  register short **new_includes;
+
+  includes = NEW2(ngotos, short *);
+  edge = NEW2(ngotos + 1, short);
+  states = NEW2(maxrhs + 1, short);
+
+  for (i = 0; i < ngotos; i++)
+    {
+      nedges = 0;
+      state1 = from_state[i];
+      symbol1 = accessing_symbol[to_state[i]];
+
+      for (rulep = derives[symbol1]; *rulep >= 0; rulep++)
+	{
+	  length = 1;
+	  states[0] = state1;
+	  stateno = state1;
+
+	  for (rp = ritem + rrhs[*rulep]; *rp >= 0; rp++)
+	    {
+	      symbol2 = *rp;
+	      sp = shift_table[stateno];
+	      k = sp->nshifts;
+
+	      for (j = 0; j < k; j++)
+		{
+		  stateno = sp->shift[j];
+		  if (accessing_symbol[stateno] == symbol2) break;
+		}
+
+	      states[length++] = stateno;
+	    }
+
+	  add_lookback_edge(stateno, *rulep, i);
+
+	  length--;
+	  done = 0;
+	  while (!done)
+	    {
+	      done = 1;
+	      rp--;
+	      if (ISVAR(*rp))
+		{
+		  stateno = states[--length];
+		  edge[nedges++] = map_goto(stateno, *rp);
+		  if (nullable[*rp] && length > 0) done = 0;
+		}
+	    }
+	}
+
+      if (nedges)
+	{
+	  includes[i] = shortp = NEW2(nedges + 1, short);
+	  for (j = 0; j < nedges; j++)
+	    shortp[j] = edge[j];
+	  shortp[nedges] = -1;
+	}
+    }
+
+  new_includes = transpose(includes, ngotos);
+
+  for (i = 0; i < ngotos; i++)
+    if (includes[i])
+      FREE(includes[i]);
+
+  FREE(includes);
+
+  includes = new_includes;
+
+  FREE(edge);
+  FREE(states);
+}
+
+
+add_lookback_edge(stateno, ruleno, gotono)
+int stateno, ruleno, gotono;
+{
+    register int i, k;
+    register int found;
+    register shorts *sp;
+
+    i = lookaheads[stateno];
+    k = lookaheads[stateno + 1];
+    found = 0;
+    while (!found && i < k)
+    {
+	if (LAruleno[i] == ruleno)
+	    found = 1;
+	else
+	    ++i;
+    }
+    assert(found);
+
+    sp = NEW(shorts);
+    sp->next = lookback[i];
+    sp->value = gotono;
+    lookback[i] = sp;
+}
+
+
+
+short **
+transpose(R, n)
+short **R;
+int n;
+{
+  register short **new_R;
+  register short **temp_R;
+  register short *nedges;
+  register short *sp;
+  register int i;
+  register int k;
+
+  nedges = NEW2(n, short);
+
+  for (i = 0; i < n; i++)
+    {
+      sp = R[i];
+      if (sp)
+	{
+	  while (*sp >= 0)
+	    nedges[*sp++]++;
+	}
+    }
+
+  new_R = NEW2(n, short *);
+  temp_R = NEW2(n, short *);
+
+  for (i = 0; i < n; i++)
+    {
+      k = nedges[i];
+      if (k > 0)
+	{
+	  sp = NEW2(k + 1, short);
+	  new_R[i] = sp;
+	  temp_R[i] = sp;
+	  sp[k] = -1;
+	}
+    }
+
+  FREE(nedges);
+
+  for (i = 0; i < n; i++)
+    {
+      sp = R[i];
+      if (sp)
+	{
+	  while (*sp >= 0)
+	    *temp_R[*sp++]++ = i;
+	}
+    }
+
+  FREE(temp_R);
+
+  return (new_R);
+}
+
+
+
+compute_FOLLOWS()
+{
+  digraph(includes);
+}
+
+
+compute_lookaheads()
+{
+  register int i, n;
+  register unsigned *fp1, *fp2, *fp3;
+  register shorts *sp, *next;
+  register unsigned *rowp;
+
+  rowp = LA;
+  n = lookaheads[nstates];
+  for (i = 0; i < n; i++)
+    {
+      fp3 = rowp + tokensetsize;
+      for (sp = lookback[i]; sp; sp = sp->next)
+	{
+	  fp1 = rowp;
+	  fp2 = F + tokensetsize * sp->value;
+	  while (fp1 < fp3)
+	    *fp1++ |= *fp2++;
+	}
+      rowp = fp3;
+    }
+
+  for (i = 0; i < n; i++)
+    for (sp = lookback[i]; sp; sp = next)
+      {
+        next = sp->next;
+        FREE(sp);
+      }
+
+  FREE(lookback);
+  FREE(F);
+}
+
+
+digraph(relation)
+short **relation;
+{
+  register int i;
+
+  infinity = ngotos + 2;
+  INDEX = NEW2(ngotos + 1, short);
+  VERTICES = NEW2(ngotos + 1, short);
+  top = 0;
+
+  R = relation;
+
+  for (i = 0; i < ngotos; i++)
+    INDEX[i] = 0;
+
+  for (i = 0; i < ngotos; i++)
+    {
+      if (INDEX[i] == 0 && R[i])
+	traverse(i);
+    }
+
+  FREE(INDEX);
+  FREE(VERTICES);
+}
+
+
+
+traverse(i)
+register int i;
+{
+  register unsigned *fp1;
+  register unsigned *fp2;
+  register unsigned *fp3;
+  register int j;
+  register short *rp;
+
+  int height;
+  unsigned *base;
+
+  VERTICES[++top] = i;
+  INDEX[i] = height = top;
+
+  base = F + i * tokensetsize;
+  fp3 = base + tokensetsize;
+
+  rp = R[i];
+  if (rp)
+    {
+      while ((j = *rp++) >= 0)
+	{
+	  if (INDEX[j] == 0)
+	    traverse(j);
+
+	  if (INDEX[i] > INDEX[j])
+	    INDEX[i] = INDEX[j];
+
+	  fp1 = base;
+	  fp2 = F + j * tokensetsize;
+
+	  while (fp1 < fp3)
+	    *fp1++ |= *fp2++;
+	}
+    }
+
+  if (INDEX[i] == height)
+    {
+      for (;;)
+	{
+	  j = VERTICES[top--];
+	  INDEX[j] = infinity;
+
+	  if (i == j)
+	    break;
+
+	  fp1 = base;
+	  fp2 = F + j * tokensetsize;
+
+	  while (fp1 < fp3)
+	    *fp2++ = *fp1++;
+	}
+    }
+}

+ 637 - 0
mcs/jay/lr0.c

@@ -0,0 +1,637 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)lr0.c	5.3 (Berkeley) 1/20/91";
+#endif /* not lint */
+
+#include "defs.h"
+
+extern short *itemset;
+extern short *itemsetend;
+extern unsigned *ruleset;
+
+int nstates;
+core *first_state;
+shifts *first_shift;
+reductions *first_reduction;
+
+int get_state();
+core *new_state();
+
+static core **state_set;
+static core *this_state;
+static core *last_state;
+static shifts *last_shift;
+static reductions *last_reduction;
+
+static int nshifts;
+static short *shift_symbol;
+
+static short *redset;
+static short *shiftset;
+
+static short **kernel_base;
+static short **kernel_end;
+static short *kernel_items;
+
+
+allocate_itemsets()
+{
+    register short *itemp;
+    register short *item_end;
+    register int symbol;
+    register int i;
+    register int count;
+    register int max;
+    register short *symbol_count;
+
+    count = 0;
+    symbol_count = NEW2(nsyms, short);
+
+    item_end = ritem + nitems;
+    for (itemp = ritem; itemp < item_end; itemp++)
+    {
+	symbol = *itemp;
+	if (symbol >= 0)
+	{
+	    count++;
+	    symbol_count[symbol]++;
+	}
+    }
+
+    kernel_base = NEW2(nsyms, short *);
+    kernel_items = NEW2(count, short);
+
+    count = 0;
+    max = 0;
+    for (i = 0; i < nsyms; i++)
+    {
+	kernel_base[i] = kernel_items + count;
+	count += symbol_count[i];
+	if (max < symbol_count[i])
+	    max = symbol_count[i];
+    }
+
+    shift_symbol = symbol_count;
+    kernel_end = NEW2(nsyms, short *);
+}
+
+
+allocate_storage()
+{
+    allocate_itemsets();
+    shiftset = NEW2(nsyms, short);
+    redset = NEW2(nrules + 1, short);
+    state_set = NEW2(nitems, core *);
+}
+
+
+append_states()
+{
+    register int i;
+    register int j;
+    register int symbol;
+
+#ifdef	TRACE
+    fprintf(stderr, "Entering append_states()\n");
+#endif
+    for (i = 1; i < nshifts; i++)
+    {
+	symbol = shift_symbol[i];
+	j = i;
+	while (j > 0 && shift_symbol[j - 1] > symbol)
+	{
+	    shift_symbol[j] = shift_symbol[j - 1];
+	    j--;
+	}
+	shift_symbol[j] = symbol;
+    }
+
+    for (i = 0; i < nshifts; i++)
+    {
+	symbol = shift_symbol[i];
+	shiftset[i] = get_state(symbol);
+    }
+}
+
+
+free_storage()
+{
+    FREE(shift_symbol);
+    FREE(redset);
+    FREE(shiftset);
+    FREE(kernel_base);
+    FREE(kernel_end);
+    FREE(kernel_items);
+    FREE(state_set);
+}
+
+
+
+generate_states()
+{
+    allocate_storage();
+    itemset = NEW2(nitems, short);
+    ruleset = NEW2(WORDSIZE(nrules), unsigned);
+    set_first_derives();
+    initialize_states();
+
+    while (this_state)
+    {
+	closure(this_state->items, this_state->nitems);
+	save_reductions();
+	new_itemsets();
+	append_states();
+
+	if (nshifts > 0)
+	    save_shifts();
+
+	this_state = this_state->next;
+    }
+
+    finalize_closure();
+    free_storage();
+}
+
+
+
+int
+get_state(symbol)
+int symbol;
+{
+    register int key;
+    register short *isp1;
+    register short *isp2;
+    register short *iend;
+    register core *sp;
+    register int found;
+    register int n;
+
+#ifdef	TRACE
+    fprintf(stderr, "Entering get_state(%d)\n", symbol);
+#endif
+
+    isp1 = kernel_base[symbol];
+    iend = kernel_end[symbol];
+    n = iend - isp1;
+
+    key = *isp1;
+    assert(0 <= key && key < nitems);
+    sp = state_set[key];
+    if (sp)
+    {
+	found = 0;
+	while (!found)
+	{
+	    if (sp->nitems == n)
+	    {
+		found = 1;
+		isp1 = kernel_base[symbol];
+		isp2 = sp->items;
+
+		while (found && isp1 < iend)
+		{
+		    if (*isp1++ != *isp2++)
+			found = 0;
+		}
+	    }
+
+	    if (!found)
+	    {
+		if (sp->link)
+		{
+		    sp = sp->link;
+		}
+		else
+		{
+		    sp = sp->link = new_state(symbol);
+		    found = 1;
+		}
+	    }
+	}
+    }
+    else
+    {
+	state_set[key] = sp = new_state(symbol);
+    }
+
+    return (sp->number);
+}
+
+
+
+initialize_states()
+{
+    register int i;
+    register short *start_derives;
+    register core *p;
+
+    start_derives = derives[start_symbol];
+    for (i = 0; start_derives[i] >= 0; ++i)
+	continue;
+
+    p = (core *) MALLOC(sizeof(core) + i*sizeof(short));
+    if (p == 0) no_space();
+
+    p->next = 0;
+    p->link = 0;
+    p->number = 0;
+    p->accessing_symbol = 0;
+    p->nitems = i;
+
+    for (i = 0;  start_derives[i] >= 0; ++i)
+	p->items[i] = rrhs[start_derives[i]];
+
+    first_state = last_state = this_state = p;
+    nstates = 1;
+}
+
+
+new_itemsets()
+{
+    register int i;
+    register int shiftcount;
+    register short *isp;
+    register short *ksp;
+    register int symbol;
+
+    for (i = 0; i < nsyms; i++)
+	kernel_end[i] = 0;
+
+    shiftcount = 0;
+    isp = itemset;
+    while (isp < itemsetend)
+    {
+	i = *isp++;
+	symbol = ritem[i];
+	if (symbol > 0)
+	{
+	    ksp = kernel_end[symbol];
+	    if (!ksp)
+	    {
+		shift_symbol[shiftcount++] = symbol;
+		ksp = kernel_base[symbol];
+	    }
+
+	    *ksp++ = i + 1;
+	    kernel_end[symbol] = ksp;
+	}
+    }
+
+    nshifts = shiftcount;
+}
+
+
+
+core *
+new_state(symbol)
+int symbol;
+{
+    register int n;
+    register core *p;
+    register short *isp1;
+    register short *isp2;
+    register short *iend;
+
+#ifdef	TRACE
+    fprintf(stderr, "Entering new_state(%d)\n", symbol);
+#endif
+
+    if (nstates >= MAXSHORT)
+	fatal("too many states");
+
+    isp1 = kernel_base[symbol];
+    iend = kernel_end[symbol];
+    n = iend - isp1;
+
+    p = (core *) allocate((unsigned) (sizeof(core) + (n - 1) * sizeof(short)));
+    p->accessing_symbol = symbol;
+    p->number = nstates;
+    p->nitems = n;
+
+    isp2 = p->items;
+    while (isp1 < iend)
+	*isp2++ = *isp1++;
+
+    last_state->next = p;
+    last_state = p;
+
+    nstates++;
+
+    return (p);
+}
+
+
+/* show_cores is used for debugging */
+
+show_cores()
+{
+    core *p;
+    int i, j, k, n;
+    int itemno;
+
+    k = 0;
+    for (p = first_state; p; ++k, p = p->next)
+    {
+	if (k) printf("\n");
+	printf("state %d, number = %d, accessing symbol = %s\n",
+		k, p->number, symbol_name[p->accessing_symbol]);
+	n = p->nitems;
+	for (i = 0; i < n; ++i)
+	{
+	    itemno = p->items[i];
+	    printf("%4d  ", itemno);
+	    j = itemno;
+	    while (ritem[j] >= 0) ++j;
+	    printf("%s :", symbol_name[rlhs[-ritem[j]]]);
+	    j = rrhs[-ritem[j]];
+	    while (j < itemno)
+		printf(" %s", symbol_name[ritem[j++]]);
+	    printf(" .");
+	    while (ritem[j] >= 0)
+		printf(" %s", symbol_name[ritem[j++]]);
+	    printf("\n");
+	    fflush(stdout);
+	}
+    }
+}
+
+
+/* show_ritems is used for debugging */
+
+show_ritems()
+{
+    int i;
+
+    for (i = 0; i < nitems; ++i)
+	printf("ritem[%d] = %d\n", i, ritem[i]);
+}
+
+
+/* show_rrhs is used for debugging */
+show_rrhs()
+{
+    int i;
+
+    for (i = 0; i < nrules; ++i)
+	printf("rrhs[%d] = %d\n", i, rrhs[i]);
+}
+
+
+/* show_shifts is used for debugging */
+
+show_shifts()
+{
+    shifts *p;
+    int i, j, k;
+
+    k = 0;
+    for (p = first_shift; p; ++k, p = p->next)
+    {
+	if (k) printf("\n");
+	printf("shift %d, number = %d, nshifts = %d\n", k, p->number,
+		p->nshifts);
+	j = p->nshifts;
+	for (i = 0; i < j; ++i)
+	    printf("\t%d\n", p->shift[i]);
+    }
+}
+
+
+save_shifts()
+{
+    register shifts *p;
+    register short *sp1;
+    register short *sp2;
+    register short *send;
+
+    p = (shifts *) allocate((unsigned) (sizeof(shifts) +
+			(nshifts - 1) * sizeof(short)));
+
+    p->number = this_state->number;
+    p->nshifts = nshifts;
+
+    sp1 = shiftset;
+    sp2 = p->shift;
+    send = shiftset + nshifts;
+
+    while (sp1 < send)
+	*sp2++ = *sp1++;
+
+    if (last_shift)
+    {
+	last_shift->next = p;
+	last_shift = p;
+    }
+    else
+    {
+	first_shift = p;
+	last_shift = p;
+    }
+}
+
+
+
+save_reductions()
+{
+    register short *isp;
+    register short *rp1;
+    register short *rp2;
+    register int item;
+    register int count;
+    register reductions *p;
+    register short *rend;
+
+    count = 0;
+    for (isp = itemset; isp < itemsetend; isp++)
+    {
+	item = ritem[*isp];
+	if (item < 0)
+	{
+	    redset[count++] = -item;
+	}
+    }
+
+    if (count)
+    {
+	p = (reductions *) allocate((unsigned) (sizeof(reductions) +
+					(count - 1) * sizeof(short)));
+
+	p->number = this_state->number;
+	p->nreds = count;
+
+	rp1 = redset;
+	rp2 = p->rules;
+	rend = rp1 + count;
+
+	while (rp1 < rend)
+	    *rp2++ = *rp1++;
+
+	if (last_reduction)
+	{
+	    last_reduction->next = p;
+	    last_reduction = p;
+	}
+	else
+	{
+	    first_reduction = p;
+	    last_reduction = p;
+	}
+    }
+}
+
+
+set_derives()
+{
+    register int i, k;
+    register int lhs;
+    register short *rules;
+
+    derives = NEW2(nsyms, short *);
+    rules = NEW2(nvars + nrules, short);
+
+    k = 0;
+    for (lhs = start_symbol; lhs < nsyms; lhs++)
+    {
+	derives[lhs] = rules + k;
+	for (i = 0; i < nrules; i++)
+	{
+	    if (rlhs[i] == lhs)
+	    {
+		rules[k] = i;
+		k++;
+	    }
+	}
+	rules[k] = -1;
+	k++;
+    }
+
+#ifdef	DEBUG
+    print_derives();
+#endif
+}
+
+free_derives()
+{
+    FREE(derives[start_symbol]);
+    FREE(derives);
+}
+
+#ifdef	DEBUG
+print_derives()
+{
+    register int i;
+    register short *sp;
+
+    printf("\nDERIVES\n\n");
+
+    for (i = start_symbol; i < nsyms; i++)
+    {
+	printf("%s derives ", symbol_name[i]);
+	for (sp = derives[i]; *sp >= 0; sp++)
+	{
+	    printf("  %d", *sp);
+	}
+	putchar('\n');
+    }
+
+    putchar('\n');
+}
+#endif
+
+
+set_nullable()
+{
+    register int i, j;
+    register int empty;
+    int done;
+
+    nullable = MALLOC(nsyms);
+    if (nullable == 0) no_space();
+
+    for (i = 0; i < nsyms; ++i)
+	nullable[i] = 0;
+
+    done = 0;
+    while (!done)
+    {
+	done = 1;
+	for (i = 1; i < nitems; i++)
+	{
+	    empty = 1;
+	    while ((j = ritem[i]) >= 0)
+	    {
+		if (!nullable[j])
+		    empty = 0;
+		++i;
+	    }
+	    if (empty)
+	    {
+		j = rlhs[-j];
+		if (!nullable[j])
+		{
+		    nullable[j] = 1;
+		    done = 0;
+		}
+	    }
+	}
+    }
+
+#ifdef DEBUG
+    for (i = 0; i < nsyms; i++)
+    {
+	if (nullable[i])
+	    printf("%s is nullable\n", symbol_name[i]);
+	else
+	    printf("%s is not nullable\n", symbol_name[i]);
+    }
+#endif
+}
+
+
+free_nullable()
+{
+    FREE(nullable);
+}
+
+
+lr0()
+{
+    set_derives();
+    set_nullable();
+    generate_states();
+}

+ 337 - 0
mcs/jay/main.c

@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)main.c	5.5 (Berkeley) 5/24/93";
+#endif /* not lint */
+
+#include <signal.h>
+#include "defs.h"
+
+char tflag;
+char vflag;
+char csharp = 0;
+
+char *file_prefix = "y";
+char *myname = "yacc";
+char *temp_form = "yacc.XXXXXXX";
+
+int lineno;
+int outline;
+
+char *action_file_name;
+char *input_file_name = "";
+char *prolog_file_name;
+char *local_file_name;
+char *verbose_file_name;
+
+FILE *action_file;	/*  a temp file, used to save actions associated    */
+			/*  with rules until the parser is written	    */
+FILE *input_file;	/*  the input file				    */
+FILE *prolog_file;	/*  temp files, used to save text until all	    */
+FILE *local_file;	/*  symbols have been defined			    */
+FILE *verbose_file;	/*  y.output					    */
+
+int nitems;
+int nrules;
+int nsyms;
+int ntokens;
+int nvars;
+
+int   start_symbol;
+char  **symbol_name;
+short *symbol_value;
+short *symbol_prec;
+char  *symbol_assoc;
+
+short *ritem;
+short *rlhs;
+short *rrhs;
+short *rprec;
+char  *rassoc;
+short **derives;
+char *nullable;
+
+extern char *mktemp();
+extern char *getenv();
+
+done(k)
+int k;
+{
+    if (action_file) { fclose(action_file); unlink(action_file_name); }
+    if (prolog_file) { fclose(prolog_file); unlink(prolog_file_name); }
+    if (local_file) { fclose(local_file); unlink(local_file_name); }
+    exit(k);
+}
+
+
+void
+onintr(signo)
+	int signo;
+{
+    done(1);
+}
+
+
+set_signals()
+{
+#ifdef SIGINT
+    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+	signal(SIGINT, onintr);
+#endif
+#ifdef SIGTERM
+    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
+	signal(SIGTERM, onintr);
+#endif
+#ifdef SIGHUP
+    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
+	signal(SIGHUP, onintr);
+#endif
+}
+
+
+usage()
+{
+    fprintf(stderr, "usage: %s [-tvc] [-b file_prefix] filename\n", myname);
+    exit(1);
+}
+
+
+getargs(argc, argv)
+int argc;
+char *argv[];
+{
+    register int i;
+    register char *s;
+
+    if (argc > 0) myname = argv[0];
+    for (i = 1; i < argc; ++i)
+    {
+	s = argv[i];
+	if (*s != '-') break;
+	switch (*++s)
+	{
+	case '\0':
+	    input_file = stdin;
+	    if (i + 1 < argc) usage();
+	    return;
+
+	case '-':
+	    ++i;
+	    goto no_more_options;
+
+	case 'b':
+	    if (*++s)
+		 file_prefix = s;
+	    else if (++i < argc)
+		file_prefix = argv[i];
+	    else
+		usage();
+	    continue;
+
+	case 't':
+	    tflag = 1;
+	    break;
+
+	case 'c':
+	    csharp = 1;
+	    line_format = "#line %d \"%s\"\n";
+	    break;
+	    
+	case 'v':
+	    vflag = 1;
+	    break;
+
+	default:
+	    usage();
+	}
+
+	for (;;)
+	{
+	    switch (*++s)
+	    {
+	    case '\0':
+		goto end_of_option;
+
+	    case 't':
+		tflag = 1;
+		break;
+
+	    case 'v':
+		vflag = 1;
+		break;
+
+	    default:
+		usage();
+	    }
+	}
+end_of_option:;
+    }
+
+no_more_options:;
+    if (i + 1 != argc) usage();
+    input_file_name = argv[i];
+}
+
+
+char *
+allocate(n)
+unsigned n;
+{
+    register char *p;
+
+    p = NULL;
+    if (n)
+    {
+	p = CALLOC(1, n);
+	if (!p) no_space();
+    }
+    return (p);
+}
+
+
+create_file_names()
+{
+    int i, len;
+    char *tmpdir;
+
+    tmpdir = getenv("TMPDIR");
+    if (tmpdir == 0) tmpdir = "/tmp";
+
+    len = strlen(tmpdir);
+    i = len + 13;
+    if (len && tmpdir[len-1] != '/')
+	++i;
+
+    action_file_name = MALLOC(i);
+    if (action_file_name == 0) no_space();
+    prolog_file_name = MALLOC(i);
+    if (prolog_file_name == 0) no_space();
+    local_file_name = MALLOC(i);
+    if (local_file_name == 0) no_space();
+
+    strcpy(action_file_name, tmpdir);
+    strcpy(prolog_file_name, tmpdir);
+    strcpy(local_file_name, tmpdir);
+
+    if (len && tmpdir[len - 1] != '/')
+    {
+	action_file_name[len] = '/';
+	prolog_file_name[len] = '/';
+	local_file_name[len] = '/';
+	++len;
+    }
+
+    strcpy(action_file_name + len, temp_form);
+    strcpy(prolog_file_name + len, temp_form);
+    strcpy(local_file_name + len, temp_form);
+
+    action_file_name[len + 5] = 'a';
+    prolog_file_name[len + 5] = 'p';
+    local_file_name[len + 5] = 'l';
+
+    mktemp(action_file_name);
+    mktemp(prolog_file_name);
+    mktemp(local_file_name);
+
+    len = strlen(file_prefix);
+
+    if (vflag)
+    {
+	verbose_file_name = MALLOC(len + 8);
+	if (verbose_file_name == 0)
+	    no_space();
+	strcpy(verbose_file_name, file_prefix);
+	strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
+    }
+}
+
+
+open_files()
+{
+    create_file_names();
+
+    if (input_file == 0)
+    {
+	input_file = fopen(input_file_name, "r");
+	if (input_file == 0)
+	    open_error(input_file_name);
+    }
+
+    action_file = fopen(action_file_name, "w");
+    if (action_file == 0)
+	open_error(action_file_name);
+
+    prolog_file = fopen(prolog_file_name, "w");
+    if (prolog_file == 0)
+	open_error(prolog_file_name);
+
+    local_file = fopen(local_file_name, "w");
+    if (local_file == 0)
+	open_error(local_file_name);
+
+    if (vflag)
+    {
+	verbose_file = fopen(verbose_file_name, "w");
+	if (verbose_file == 0)
+	    open_error(verbose_file_name);
+    }
+}
+
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+    set_signals();
+    getargs(argc, argv);
+    open_files();
+    reader();
+    lr0();
+    lalr();
+    make_parser();
+    verbose();
+    output();
+    done(0);
+    /*NOTREACHED*/
+}

+ 10 - 0
mcs/jay/makefile

@@ -0,0 +1,10 @@
+all	= jay.$(OSTYPE)
+c	= closure.c error.c lalr.c lr0.c main.c mkpar.c output.c reader.c \
+	  symtab.c verbose.c warshall.c
+
+CFLAGS=#-g
+
+jay.$(OSTYPE):	$(c:.c=.o)	; $(CC) -o $@ $(CFLAGS) $(c:.c=.o)
+
+depend:	*.[ch]		; $(CC) -MM $(CFLAGS) $c > $@
+-include depend

+ 395 - 0
mcs/jay/mkpar.c

@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mkpar.c	5.3 (Berkeley) 1/20/91";
+#endif /* not lint */
+
+#include "defs.h"
+
+action **parser;
+int SRtotal;
+int RRtotal;
+short *SRconflicts;
+short *RRconflicts;
+short *defred;
+short *rules_used;
+short nunused;
+short final_state;
+
+static int SRcount;
+static int RRcount;
+
+extern action *parse_actions();
+extern action *get_shifts();
+extern action *add_reductions();
+extern action *add_reduce();
+
+
+make_parser()
+{
+    register int i;
+
+    parser = NEW2(nstates, action *);
+    for (i = 0; i < nstates; i++)
+	parser[i] = parse_actions(i);
+
+    find_final_state();
+    remove_conflicts();
+    unused_rules();
+    if (SRtotal + RRtotal > 0) total_conflicts();
+    defreds();
+}
+
+
+action *
+parse_actions(stateno)
+register int stateno;
+{
+    register action *actions;
+
+    actions = get_shifts(stateno);
+    actions = add_reductions(stateno, actions);
+    return (actions);
+}
+
+
+action *
+get_shifts(stateno)
+int stateno;
+{
+    register action *actions, *temp;
+    register shifts *sp;
+    register short *to_state;
+    register int i, k;
+    register int symbol;
+
+    actions = 0;
+    sp = shift_table[stateno];
+    if (sp)
+    {
+	to_state = sp->shift;
+	for (i = sp->nshifts - 1; i >= 0; i--)
+	{
+	    k = to_state[i];
+	    symbol = accessing_symbol[k];
+	    if (ISTOKEN(symbol))
+	    {
+		temp = NEW(action);
+		temp->next = actions;
+		temp->symbol = symbol;
+		temp->number = k;
+		temp->prec = symbol_prec[symbol];
+		temp->action_code = SHIFT;
+		temp->assoc = symbol_assoc[symbol];
+		actions = temp;
+	    }
+	}
+    }
+    return (actions);
+}
+
+action *
+add_reductions(stateno, actions)
+int stateno;
+register action *actions;
+{
+    register int i, j, m, n;
+    register int ruleno, tokensetsize;
+    register unsigned *rowp;
+
+    tokensetsize = WORDSIZE(ntokens);
+    m = lookaheads[stateno];
+    n = lookaheads[stateno + 1];
+    for (i = m; i < n; i++)
+    {
+	ruleno = LAruleno[i];
+	rowp = LA + i * tokensetsize;
+	for (j = ntokens - 1; j >= 0; j--)
+	{
+	    if (BIT(rowp, j))
+		actions = add_reduce(actions, ruleno, j);
+	}
+    }
+    return (actions);
+}
+
+
+action *
+add_reduce(actions, ruleno, symbol)
+register action *actions;
+register int ruleno, symbol;
+{
+    register action *temp, *prev, *next;
+
+    prev = 0;
+    for (next = actions; next && next->symbol < symbol; next = next->next)
+	prev = next;
+
+    while (next && next->symbol == symbol && next->action_code == SHIFT)
+    {
+	prev = next;
+	next = next->next;
+    }
+
+    while (next && next->symbol == symbol &&
+	    next->action_code == REDUCE && next->number < ruleno)
+    {
+	prev = next;
+	next = next->next;
+    }
+
+    temp = NEW(action);
+    temp->next = next;
+    temp->symbol = symbol;
+    temp->number = ruleno;
+    temp->prec = rprec[ruleno];
+    temp->action_code = REDUCE;
+    temp->assoc = rassoc[ruleno];
+
+    if (prev)
+	prev->next = temp;
+    else
+	actions = temp;
+
+    return (actions);
+}
+
+
+find_final_state()
+{
+    register int goal, i;
+    register short *to_state;
+    register shifts *p;
+
+    p = shift_table[0];
+    to_state = p->shift;
+    goal = ritem[1];
+    for (i = p->nshifts - 1; i >= 0; --i)
+    {
+	final_state = to_state[i];
+	if (accessing_symbol[final_state] == goal) break;
+    }
+}
+
+
+unused_rules()
+{
+    register int i;
+    register action *p;
+
+    rules_used = (short *) MALLOC(nrules*sizeof(short));
+    if (rules_used == 0) no_space();
+
+    for (i = 0; i < nrules; ++i)
+	rules_used[i] = 0;
+
+    for (i = 0; i < nstates; ++i)
+    {
+	for (p = parser[i]; p; p = p->next)
+	{
+	    if (p->action_code == REDUCE && p->suppressed == 0)
+		rules_used[p->number] = 1;
+	}
+    }
+
+    nunused = 0;
+    for (i = 3; i < nrules; ++i)
+	if (!rules_used[i]) ++nunused;
+
+    if (nunused)
+	if (nunused == 1)
+	    fprintf(stderr, "%s: 1 rule never reduced\n", myname);
+	else
+	    fprintf(stderr, "%s: %d rules never reduced\n", myname, nunused);
+}
+
+
+remove_conflicts()
+{
+    register int i;
+    register int symbol;
+    register action *p, *pref;
+
+    SRtotal = 0;
+    RRtotal = 0;
+    SRconflicts = NEW2(nstates, short);
+    RRconflicts = NEW2(nstates, short);
+    for (i = 0; i < nstates; i++)
+    {
+	SRcount = 0;
+	RRcount = 0;
+	symbol = -1;
+	for (p = parser[i]; p; p = p->next)
+	{
+	    if (p->symbol != symbol)
+	    {
+		pref = p;
+		symbol = p->symbol;
+	    }
+	    else if (i == final_state && symbol == 0)
+	    {
+		SRcount++;
+		p->suppressed = 1;
+	    }
+	    else if (pref->action_code == SHIFT)
+	    {
+		if (pref->prec > 0 && p->prec > 0)
+		{
+		    if (pref->prec < p->prec)
+		    {
+			pref->suppressed = 2;
+			pref = p;
+		    }
+		    else if (pref->prec > p->prec)
+		    {
+			p->suppressed = 2;
+		    }
+		    else if (pref->assoc == LEFT)
+		    {
+			pref->suppressed = 2;
+			pref = p;
+		    }
+		    else if (pref->assoc == RIGHT)
+		    {
+			p->suppressed = 2;
+		    }
+		    else
+		    {
+			pref->suppressed = 2;
+			p->suppressed = 2;
+		    }
+		}
+		else
+		{
+		    SRcount++;
+		    p->suppressed = 1;
+		}
+	    }
+	    else
+	    {
+		RRcount++;
+		p->suppressed = 1;
+	    }
+	}
+	SRtotal += SRcount;
+	RRtotal += RRcount;
+	SRconflicts[i] = SRcount;
+	RRconflicts[i] = RRcount;
+    }
+}
+
+
+total_conflicts()
+{
+    fprintf(stderr, "%s: ", myname);
+    if (SRtotal == 1)
+	fprintf(stderr, "1 shift/reduce conflict");
+    else if (SRtotal > 1)
+	fprintf(stderr, "%d shift/reduce conflicts", SRtotal);
+
+    if (SRtotal && RRtotal)
+	fprintf(stderr, ", ");
+
+    if (RRtotal == 1)
+	fprintf(stderr, "1 reduce/reduce conflict");
+    else if (RRtotal > 1)
+	fprintf(stderr, "%d reduce/reduce conflicts", RRtotal);
+
+    fprintf(stderr, ".\n");
+}
+
+
+int
+sole_reduction(stateno)
+int stateno;
+{
+    register int count, ruleno;
+    register action *p;
+
+    count = 0;
+    ruleno = 0; 
+    for (p = parser[stateno]; p; p = p->next)
+    {
+	if (p->action_code == SHIFT && p->suppressed == 0)
+	    return (0);
+	else if (p->action_code == REDUCE && p->suppressed == 0)
+	{
+	    if (ruleno > 0 && p->number != ruleno)
+		return (0);
+	    if (p->symbol != 1)
+		++count;
+	    ruleno = p->number;
+	}
+    }
+
+    if (count == 0)
+	return (0);
+    return (ruleno);
+}
+
+
+defreds()
+{
+    register int i;
+
+    defred = NEW2(nstates, short);
+    for (i = 0; i < nstates; i++)
+	defred[i] = sole_reduction(i);
+}
+ 
+free_action_row(p)
+register action *p;
+{
+  register action *q;
+
+  while (p)
+    {
+      q = p->next;
+      FREE(p);
+      p = q;
+    }
+}
+
+free_parser()
+{
+  register int i;
+
+  for (i = 0; i < nstates; i++)
+    free_action_row(parser[i]);
+
+  FREE(parser);
+}

+ 1173 - 0
mcs/jay/output.c

@@ -0,0 +1,1173 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)output.c	5.7 (Berkeley) 5/24/93";
+#endif /* not lint */
+
+#include "defs.h"
+#include <string.h>
+
+static int nvectors;
+static int nentries;
+static short **froms;
+static short **tos;
+static short *tally;
+static short *width;
+static short *state_count;
+static short *order;
+static short *base;
+static short *pos;
+static int maxtable;
+static short *table;
+static short *check;
+static int lowzero;
+static int high;
+extern int csharp;
+
+output () {
+  int lno = 0;
+  char buf [128];
+
+  free_itemsets();
+  free_shifts();
+  free_reductions();
+
+  while (fgets(buf, sizeof buf, stdin) != NULL) {
+    char * cp;
+    ++ lno;
+    if (buf[strlen(buf)-1] != '\n')
+      fprintf(stderr, "jay: line %d is too long\n", lno), done(1);
+    switch (buf[0]) {
+    case '#':	continue;
+    case 't':	if (!tflag) fputs("//t", stdout);
+    case '.':	break;
+    default:
+      cp = strtok(buf, " \t\r\n");
+      if (cp)
+        if (strcmp(cp, "actions") == 0) output_semantic_actions();
+        else if (strcmp(cp, "debug") == 0) output_debug();
+        else if (strcmp(cp, "epilog") == 0) output_trailing_text();
+        else if (strcmp(cp, "prolog") == 0)
+		output_stored_text(prolog_file, prolog_file_name);
+        else if (strcmp(cp, "local") == 0)
+		output_stored_text(local_file, local_file_name);
+        else if (strcmp(cp, "tables") == 0)
+	  output_rule_data(), output_yydefred(), output_actions();
+        else if (strcmp(cp, "tokens") == 0)
+		output_defines(strtok(NULL, "\r\n"));
+        else
+          fprintf(stderr, "jay: unknown call (%s) in line %d\n", cp, lno);
+      continue;
+    }
+    fputs(buf+1, stdout), ++ outline;
+  }
+  free_parser();
+}
+
+output_rule_data()
+{
+    register int i;
+    register int j;
+
+
+    printf("  %s static %s short [] yyLhs  = {%16d,",
+	   csharp ? "" : " protected",
+	   csharp ? "" : " final",
+	    symbol_value[start_symbol]);
+
+    j = 10;
+    for (i = 3; i < nrules; i++)
+    {
+	if (j >= 10)
+	{
+	    ++outline;
+	    putchar('\n');
+	    j = 1;
+	}
+        else
+	    ++j;
+
+        printf("%5d,", symbol_value[rlhs[i]]);
+    }
+    outline += 2;
+    printf("\n  };\n");
+
+    printf("  %s static %s short [] yyLen = {%12d,",
+	   csharp ? "" : "protected",
+	   csharp ? "" : "final",
+	   2);
+
+    j = 10;
+    for (i = 3; i < nrules; i++)
+    {
+	if (j >= 10)
+	{
+	    ++outline;
+	    putchar('\n');
+	    j = 1;
+	}
+	else
+	  j++;
+
+        printf("%5d,", rrhs[i + 1] - rrhs[i] - 1);
+    }
+    outline += 2;
+    printf("\n  };\n");
+}
+
+
+output_yydefred()
+{
+    register int i, j;
+
+    printf("  %s static %s short [] yyDefRed = {%13d,",
+	   csharp ? "" : "protected",
+	   csharp ? "" : "final",	   
+	    (defred[0] ? defred[0] - 2 : 0));
+
+    j = 10;
+    for (i = 1; i < nstates; i++)
+    {
+	if (j < 10)
+	    ++j;
+	else
+	{
+	    ++outline;
+	    putchar('\n');
+	    j = 1;
+	}
+
+	printf("%5d,", (defred[i] ? defred[i] - 2 : 0));
+    }
+
+    outline += 2;
+    printf("\n  };\n");
+}
+
+
+output_actions()
+{
+    nvectors = 2*nstates + nvars;
+
+    froms = NEW2(nvectors, short *);
+    tos = NEW2(nvectors, short *);
+    tally = NEW2(nvectors, short);
+    width = NEW2(nvectors, short);
+
+    token_actions();
+    FREE(lookaheads);
+    FREE(LA);
+    FREE(LAruleno);
+    FREE(accessing_symbol);
+
+    goto_actions();
+    FREE(goto_map + ntokens);
+    FREE(from_state);
+    FREE(to_state);
+
+    sort_actions();
+    pack_table();
+    output_base();
+    output_table();
+    output_check();
+}
+
+
+token_actions()
+{
+    register int i, j;
+    register int shiftcount, reducecount;
+    register int max, min;
+    register short *actionrow, *r, *s;
+    register action *p;
+
+    actionrow = NEW2(2*ntokens, short);
+    for (i = 0; i < nstates; ++i)
+    {
+	if (parser[i])
+	{
+	    for (j = 0; j < 2*ntokens; ++j)
+	    actionrow[j] = 0;
+
+	    shiftcount = 0;
+	    reducecount = 0;
+	    for (p = parser[i]; p; p = p->next)
+	    {
+		if (p->suppressed == 0)
+		{
+		    if (p->action_code == SHIFT)
+		    {
+			++shiftcount;
+			actionrow[p->symbol] = p->number;
+		    }
+		    else if (p->action_code == REDUCE && p->number != defred[i])
+		    {
+			++reducecount;
+			actionrow[p->symbol + ntokens] = p->number;
+		    }
+		}
+	    }
+
+	    tally[i] = shiftcount;
+	    tally[nstates+i] = reducecount;
+	    width[i] = 0;
+	    width[nstates+i] = 0;
+	    if (shiftcount > 0)
+	    {
+		froms[i] = r = NEW2(shiftcount, short);
+		tos[i] = s = NEW2(shiftcount, short);
+		min = MAXSHORT;
+		max = 0;
+		for (j = 0; j < ntokens; ++j)
+		{
+		    if (actionrow[j])
+		    {
+			if (min > symbol_value[j])
+			    min = symbol_value[j];
+			if (max < symbol_value[j])
+			    max = symbol_value[j];
+			*r++ = symbol_value[j];
+			*s++ = actionrow[j];
+		    }
+		}
+		width[i] = max - min + 1;
+	    }
+	    if (reducecount > 0)
+	    {
+		froms[nstates+i] = r = NEW2(reducecount, short);
+		tos[nstates+i] = s = NEW2(reducecount, short);
+		min = MAXSHORT;
+		max = 0;
+		for (j = 0; j < ntokens; ++j)
+		{
+		    if (actionrow[ntokens+j])
+		    {
+			if (min > symbol_value[j])
+			    min = symbol_value[j];
+			if (max < symbol_value[j])
+			    max = symbol_value[j];
+			*r++ = symbol_value[j];
+			*s++ = actionrow[ntokens+j] - 2;
+		    }
+		}
+		width[nstates+i] = max - min + 1;
+	    }
+	}
+    }
+    FREE(actionrow);
+}
+
+goto_actions()
+{
+    register int i, j, k;
+
+    state_count = NEW2(nstates, short);
+
+    k = default_goto(start_symbol + 1);
+    printf("  protected static %s short [] yyDgoto  = {%14d,", csharp ? "" : "final", k);
+    save_column(start_symbol + 1, k);
+
+    j = 10;
+    for (i = start_symbol + 2; i < nsyms; i++)
+    {
+	if (j >= 10)
+	{
+	    ++outline;
+	    putchar('\n');
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	k = default_goto(i);
+	printf("%5d,", k);
+	save_column(i, k);
+    }
+
+    outline += 2;
+    printf("\n  };\n");
+    FREE(state_count);
+}
+
+int
+default_goto(symbol)
+int symbol;
+{
+    register int i;
+    register int m;
+    register int n;
+    register int default_state;
+    register int max;
+
+    m = goto_map[symbol];
+    n = goto_map[symbol + 1];
+
+    if (m == n) return (0);
+
+    for (i = 0; i < nstates; i++)
+	state_count[i] = 0;
+
+    for (i = m; i < n; i++)
+	state_count[to_state[i]]++;
+
+    max = 0;
+    default_state = 0;
+    for (i = 0; i < nstates; i++)
+    {
+	if (state_count[i] > max)
+	{
+	    max = state_count[i];
+	    default_state = i;
+	}
+    }
+
+    return (default_state);
+}
+
+
+
+save_column(symbol, default_state)
+int symbol;
+int default_state;
+{
+    register int i;
+    register int m;
+    register int n;
+    register short *sp;
+    register short *sp1;
+    register short *sp2;
+    register int count;
+    register int symno;
+
+    m = goto_map[symbol];
+    n = goto_map[symbol + 1];
+
+    count = 0;
+    for (i = m; i < n; i++)
+    {
+	if (to_state[i] != default_state)
+	    ++count;
+    }
+    if (count == 0) return;
+
+    symno = symbol_value[symbol] + 2*nstates;
+
+    froms[symno] = sp1 = sp = NEW2(count, short);
+    tos[symno] = sp2 = NEW2(count, short);
+
+    for (i = m; i < n; i++)
+    {
+	if (to_state[i] != default_state)
+	{
+	    *sp1++ = from_state[i];
+	    *sp2++ = to_state[i];
+	}
+    }
+
+    tally[symno] = count;
+    width[symno] = sp1[-1] - sp[0] + 1;
+}
+
+sort_actions()
+{
+  register int i;
+  register int j;
+  register int k;
+  register int t;
+  register int w;
+
+  order = NEW2(nvectors, short);
+  nentries = 0;
+
+  for (i = 0; i < nvectors; i++)
+    {
+      if (tally[i] > 0)
+	{
+	  t = tally[i];
+	  w = width[i];
+	  j = nentries - 1;
+
+	  while (j >= 0 && (width[order[j]] < w))
+	    j--;
+
+	  while (j >= 0 && (width[order[j]] == w) && (tally[order[j]] < t))
+	    j--;
+
+	  for (k = nentries - 1; k > j; k--)
+	    order[k + 1] = order[k];
+
+	  order[j + 1] = i;
+	  nentries++;
+	}
+    }
+}
+
+
+pack_table()
+{
+    register int i;
+    register int place;
+    register int state;
+
+    base = NEW2(nvectors, short);
+    pos = NEW2(nentries, short);
+
+    maxtable = 1000;
+    table = NEW2(maxtable, short);
+    check = NEW2(maxtable, short);
+
+    lowzero = 0;
+    high = 0;
+
+    for (i = 0; i < maxtable; i++)
+	check[i] = -1;
+
+    for (i = 0; i < nentries; i++)
+    {
+	state = matching_vector(i);
+
+	if (state < 0)
+	    place = pack_vector(i);
+	else
+	    place = base[state];
+
+	pos[i] = place;
+	base[order[i]] = place;
+    }
+
+    for (i = 0; i < nvectors; i++)
+    {
+	if (froms[i])
+	    FREE(froms[i]);
+	if (tos[i])
+	    FREE(tos[i]);
+    }
+
+    FREE(froms);
+    FREE(tos);
+    FREE(pos);
+}
+
+
+/*  The function matching_vector determines if the vector specified by	*/
+/*  the input parameter matches a previously considered	vector.  The	*/
+/*  test at the start of the function checks if the vector represents	*/
+/*  a row of shifts over terminal symbols or a row of reductions, or a	*/
+/*  column of shifts over a nonterminal symbol.  Berkeley Yacc does not	*/
+/*  check if a column of shifts over a nonterminal symbols matches a	*/
+/*  previously considered vector.  Because of the nature of LR parsing	*/
+/*  tables, no two columns can match.  Therefore, the only possible	*/
+/*  match would be between a row and a column.  Such matches are	*/
+/*  unlikely.  Therefore, to save time, no attempt is made to see if a	*/
+/*  column matches a previously considered vector.			*/
+/*									*/
+/*  Matching_vector is poorly designed.  The test could easily be made	*/
+/*  faster.  Also, it depends on the vectors being in a specific	*/
+/*  order.								*/
+
+int
+matching_vector(vector)
+int vector;
+{
+    register int i;
+    register int j;
+    register int k;
+    register int t;
+    register int w;
+    register int match;
+    register int prev;
+
+    i = order[vector];
+    if (i >= 2*nstates)
+	return (-1);
+
+    t = tally[i];
+    w = width[i];
+
+    for (prev = vector - 1; prev >= 0; prev--)
+    {
+	j = order[prev];
+	if (width[j] != w || tally[j] != t)
+	    return (-1);
+
+	match = 1;
+	for (k = 0; match && k < t; k++)
+	{
+	    if (tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k])
+		match = 0;
+	}
+
+	if (match)
+	    return (j);
+    }
+
+    return (-1);
+}
+
+
+
+int
+pack_vector(vector)
+int vector;
+{
+    register int i, j, k, l;
+    register int t;
+    register int loc;
+    register int ok;
+    register short *from;
+    register short *to;
+    int newmax;
+
+    i = order[vector];
+    t = tally[i];
+    assert(t);
+
+    from = froms[i];
+    to = tos[i];
+
+    j = lowzero - from[0];
+    for (k = 1; k < t; ++k)
+	if (lowzero - from[k] > j)
+	    j = lowzero - from[k];
+    for (;; ++j)
+    {
+	if (j == 0)
+	    continue;
+	ok = 1;
+	for (k = 0; ok && k < t; k++)
+	{
+	    loc = j + from[k];
+	    if (loc >= maxtable)
+	    {
+		if (loc >= MAXTABLE)
+		    fatal("maximum table size exceeded");
+
+		newmax = maxtable;
+		do { newmax += 200; } while (newmax <= loc);
+		table = (short *) REALLOC(table, newmax*sizeof(short));
+		if (table == 0) no_space();
+		check = (short *) REALLOC(check, newmax*sizeof(short));
+		if (check == 0) no_space();
+		for (l  = maxtable; l < newmax; ++l)
+		{
+		    table[l] = 0;
+		    check[l] = -1;
+		}
+		maxtable = newmax;
+	    }
+
+	    if (check[loc] != -1)
+		ok = 0;
+	}
+	for (k = 0; ok && k < vector; k++)
+	{
+	    if (pos[k] == j)
+		ok = 0;
+	}
+	if (ok)
+	{
+	    for (k = 0; k < t; k++)
+	    {
+		loc = j + from[k];
+		table[loc] = to[k];
+		check[loc] = from[k];
+		if (loc > high) high = loc;
+	    }
+
+	    while (check[lowzero] != -1)
+		++lowzero;
+
+	    return (j);
+	}
+    }
+}
+
+
+
+output_base()
+{
+    register int i, j;
+
+    printf("  protected static %s short [] yySindex = {%13d,", csharp?"":"final", base[0]);
+
+    j = 10;
+    for (i = 1; i < nstates; i++)
+    {
+	if (j >= 10)
+	{
+	    ++outline;
+	    putchar('\n');
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	printf("%5d,", base[i]);
+    }
+
+    outline += 2;
+    printf("\n  };\n  protected static %s short [] yyRindex = {%13d,",
+	   csharp ? "" : "final",
+	    base[nstates]);
+
+    j = 10;
+    for (i = nstates + 1; i < 2*nstates; i++)
+    {
+	if (j >= 10)
+	{
+	    ++outline;
+	    putchar('\n');
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	printf("%5d,", base[i]);
+    }
+
+    outline += 2;
+    printf("\n  };\n  protected static %s short [] yyGindex = {%13d,",
+	   csharp ? "" : "final",
+	    base[2*nstates]);
+
+    j = 10;
+    for (i = 2*nstates + 1; i < nvectors - 1; i++)
+    {
+	if (j >= 10)
+	{
+	    ++outline;
+	    putchar('\n');
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	printf("%5d,", base[i]);
+    }
+
+    outline += 2;
+    printf("\n  };\n");
+    FREE(base);
+}
+
+
+
+output_table()
+{
+    register int i;
+    register int j;
+
+    printf("  protected static %s short [] yyTable = {%14d,", csharp ? "" : "final", table[0]);
+
+    j = 10;
+    for (i = 1; i <= high; i++)
+    {
+	if (j >= 10)
+	{
+	    ++outline;
+	    putchar('\n');
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	printf("%5d,", table[i]);
+    }
+
+    outline += 2;
+    printf("\n  };\n");
+    FREE(table);
+}
+
+
+
+output_check()
+{
+    register int i;
+    register int j;
+
+    printf("  protected static %s short [] yyCheck = {%14d,",
+	   csharp ? "" : "final",
+	    check[0]);
+
+    j = 10;
+    for (i = 1; i <= high; i++)
+    {
+	if (j >= 10)
+	{
+	    ++outline;
+	    putchar('\n');
+	    j = 1;
+	}
+	else
+	    ++j;
+
+	printf("%5d,", check[i]);
+    }
+
+    outline += 2;
+    printf("\n  };\n");
+    FREE(check);
+}
+
+
+int
+is_C_identifier(name)
+char *name;
+{
+    register char *s;
+    register int c;
+
+    s = name;
+    c = *s;
+    if (c == '"')
+    {
+	c = *++s;
+	if (!isalpha(c) && c != '_' && c != '$')
+	    return (0);
+	while ((c = *++s) != '"')
+	{
+	    if (!isalnum(c) && c != '_' && c != '$')
+		return (0);
+	}
+	return (1);
+    }
+
+    if (!isalpha(c) && c != '_' && c != '$')
+	return (0);
+    while (c = *++s)
+    {
+	if (!isalnum(c) && c != '_' && c != '$')
+	    return (0);
+    }
+    return (1);
+}
+
+
+output_defines(prefix)
+char *prefix;
+{
+    register int c, i;
+    register char *s;
+
+    for (i = 2; i < ntokens; ++i)
+    {
+	s = symbol_name[i];
+	if (is_C_identifier(s))
+	{
+	    if (prefix)
+	        printf("  %s ", prefix);
+	    c = *s;
+	    if (c == '"')
+	    {
+		while ((c = *++s) != '"')
+		{
+		    putchar(c);
+		}
+	    }
+	    else
+	    {
+		do
+		{
+		    putchar(c);
+		}
+		while (c = *++s);
+	    }
+	    ++outline;
+	    printf(" = %d%s\n", symbol_value[i], csharp ? ";" : ";");
+	}
+    }
+
+    ++outline;
+    printf("  %s yyErrorCode = %d%s\n", prefix ? prefix : "", symbol_value[1], csharp ? ";" : ";");
+}
+
+
+output_stored_text(file, name)
+FILE *file;
+char *name;
+{
+    register int c;
+    register FILE *in;
+
+    fflush(file);
+    in = fopen(name, "r");
+    if (in == NULL)
+	open_error(name);
+    if ((c = getc(in)) != EOF) {
+      if (c ==  '\n')
+	++outline;
+      putchar(c);
+      while ((c = getc(in)) != EOF)
+      {
+	if (c == '\n')
+	    ++outline;
+    	putchar(c);
+      }
+      printf(line_format, ++outline + 1, "-");
+    }
+    fclose(in);
+}
+
+
+output_debug()
+{
+    register int i, j, k, max;
+    char **symnam, *s;
+    char * prefix = tflag ? "" : "//t";
+
+    ++outline;
+    printf("  protected static %s int yyFinal = %d;\n", csharp ? "" : "final", final_state);
+
+      ++outline;
+      printf("%s  public static %s string [] yyRule = {\n", prefix, csharp ? "" : "final");
+      for (i = 2; i < nrules; ++i)
+      {
+	  printf("%s    \"%s :", prefix, symbol_name[rlhs[i]]);
+	  for (j = rrhs[i]; ritem[j] > 0; ++j)
+	  {
+	      s = symbol_name[ritem[j]];
+	      if (s[0] == '"')
+	      {
+		  printf(" \\\"");
+		  while (*++s != '"')
+		  {
+		      if (*s == '\\')
+		      {
+			  if (s[1] == '\\')
+			      printf("\\\\\\\\");
+			  else
+			      printf("\\\\%c", s[1]);
+			  ++s;
+		      }
+		      else
+			  putchar(*s);
+		  }
+		  printf("\\\"");
+	      }
+	      else if (s[0] == '\'')
+	      {
+		  if (s[1] == '"')
+		      printf(" '\\\"'");
+		  else if (s[1] == '\\')
+		  {
+		      if (s[2] == '\\')
+			  printf(" '\\\\\\\\");
+		      else
+			  printf(" '\\\\%c", s[2]);
+		      s += 2;
+		      while (*++s != '\'')
+			  putchar(*s);
+		      putchar('\'');
+		  }
+		  else
+		      printf(" '%c'", s[1]);
+	      }
+	      else
+		  printf(" %s", s);
+	  }
+	  ++outline;
+	  printf("\",\n");
+      }
+      ++ outline;
+      printf("%s  };\n", prefix);
+
+    max = 0;
+    for (i = 2; i < ntokens; ++i)
+	if (symbol_value[i] > max)
+	    max = symbol_value[i];
+
+	/* need yyName for yyExpecting() */
+
+      printf("  protected static %s string [] yyName = {", csharp ? "" : "final");
+      symnam = (char **) MALLOC((max+1)*sizeof(char *));
+      if (symnam == 0) no_space();
+  
+      /* Note that it is  not necessary to initialize the element	*/
+      /* symnam[max].							*/
+      for (i = 0; i < max; ++i)
+	  symnam[i] = 0;
+      for (i = ntokens - 1; i >= 2; --i)
+	  symnam[symbol_value[i]] = symbol_name[i];
+      symnam[0] = "end-of-file";
+  
+      j = 70; fputs("    ", stdout);
+      for (i = 0; i <= max; ++i)
+      {
+	  if (s = symnam[i])
+	  {
+	      if (s[0] == '"')
+	      {
+		  k = 7;
+		  while (*++s != '"')
+		  {
+		      ++k;
+		      if (*s == '\\')
+		      {
+			  k += 2;
+			  if (*++s == '\\')
+			      ++k;
+		      }
+		  }
+		  j += k;
+		  if (j > 70)
+		  {
+		      ++outline;
+		      printf("\n    ");
+		      j = k;
+		  }
+		  printf("\"\\\"");
+		  s = symnam[i];
+		  while (*++s != '"')
+		  {
+		      if (*s == '\\')
+		      {
+			  printf("\\\\");
+			  if (*++s == '\\')
+			      printf("\\\\");
+			  else
+			      putchar(*s);
+		      }
+		      else
+			  putchar(*s);
+		  }
+		  printf("\\\"\",");
+	      }
+	      else if (s[0] == '\'')
+	      {
+		  if (s[1] == '"')
+		  {
+		      j += 7;
+		      if (j > 70)
+		      {
+			  ++outline;
+		      	  printf("\n    ");
+			  j = 7;
+		      }
+		      printf("\"'\\\"'\",");
+		  }
+		  else
+		  {
+		      k = 5;
+		      while (*++s != '\'')
+		      {
+			  ++k;
+			  if (*s == '\\')
+			  {
+			      k += 2;
+			      if (*++s == '\\')
+				  ++k;
+			  }
+		      }
+		      j += k;
+		      if (j > 70)
+		      {
+			  ++outline;
+		      	  printf("\n    ");
+			  j = k;
+		      }
+		      printf("\"'");
+		      s = symnam[i];
+		      while (*++s != '\'')
+		      {
+			  if (*s == '\\')
+			  {
+			      printf("\\\\");
+			      if (*++s == '\\')
+				  printf("\\\\");
+			      else
+				  putchar(*s);
+			  }
+			  else
+			      putchar(*s);
+		      }
+		      printf("'\",");
+		  }
+	      }
+	      else
+	      {
+		  k = strlen(s) + 3;
+		  j += k;
+		  if (j > 70)
+		  {
+		      ++outline;
+		      printf("\n    ");
+		      j = k;
+		  }
+		  putchar('"');
+		  do { putchar(*s); } while (*++s);
+		  printf("\",");
+	      }
+	  }
+	  else
+	  {
+	      j += 5;
+	      if (j > 70)
+	      {
+		  ++outline;
+		  printf("\n    ");
+		  j = 5;
+	      }
+	      printf("null,");
+	  }
+      }
+      outline += 2;
+      printf("\n  };\n");
+      FREE(symnam);
+}
+
+output_trailing_text()
+{
+    register int c, last;
+    register FILE *in;
+
+    if (line == 0)
+	return;
+
+    in = input_file;
+    c = *cptr;
+    if (c == '\n')
+    {
+	++lineno;
+	if ((c = getc(in)) == EOF)
+	    return;
+        ++outline;
+	printf(line_format, lineno, input_file_name);
+	if (c == '\n')
+	    ++outline;
+	putchar(c);
+	last = c;
+    }
+    else
+    {
+	++outline;
+	printf(line_format, lineno, input_file_name);
+	do { putchar(c); } while ((c = *++cptr) != '\n');
+	++outline;
+	putchar('\n');
+	last = '\n';
+    }
+
+    while ((c = getc(in)) != EOF)
+    {
+	if (c == '\n')
+	    ++outline;
+	putchar(c);
+	last = c;
+    }
+
+    if (last != '\n')
+    {
+	++outline;
+	putchar('\n');
+    }
+    printf(line_format, ++outline + 1, "-");
+}
+
+
+output_semantic_actions()
+{
+    register int c, last;
+
+    fclose(action_file);
+    action_file = fopen(action_file_name, "r");
+    if (action_file == NULL)
+	open_error(action_file_name);
+
+    if ((c = getc(action_file)) == EOF)
+	return;
+
+    last = c;
+    if (c == '\n')
+	++outline;
+    putchar(c);
+    while ((c = getc(action_file)) != EOF)
+    {
+	if (c == '\n')
+	    ++outline;
+	putchar(c);
+	last = c;
+    }
+
+    if (last != '\n')
+    {
+	++outline;
+	putchar('\n');
+    }
+
+    printf(line_format, ++outline + 1, "-");
+}
+
+
+free_itemsets()
+{
+    register core *cp, *next;
+
+    FREE(state_table);
+    for (cp = first_state; cp; cp = next)
+    {
+	next = cp->next;
+	FREE(cp);
+    }
+}
+
+
+free_shifts()
+{
+    register shifts *sp, *next;
+
+    FREE(shift_table);
+    for (sp = first_shift; sp; sp = next)
+    {
+	next = sp->next;
+	FREE(sp);
+    }
+}
+
+
+
+free_reductions()
+{
+    register reductions *rp, *next;
+
+    FREE(reduction_table);
+    for (rp = first_reduction; rp; rp = next)
+    {
+	next = rp->next;
+	FREE(rp);
+    }
+}

+ 1627 - 0
mcs/jay/reader.c

@@ -0,0 +1,1627 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)reader.c	5.7 (Berkeley) 1/20/91";
+#endif /* not lint */
+
+#include "defs.h"
+
+/*  The line size must be a positive integer.  One hundred was chosen	*/
+/*  because few lines in Yacc input grammars exceed 100 characters.	*/
+/*  Note that if a line exceeds LINESIZE characters, the line buffer	*/
+/*  will be expanded to accomodate it.					*/
+
+#define LINESIZE 100
+
+char *cache;
+int cinc, cache_size;
+
+int ntags, tagmax;
+char **tag_table;
+
+char saw_eof;
+char *cptr, *line;
+int linesize;
+
+bucket *goal;
+int prec;
+int gensym;
+char last_was_action;
+
+int maxitems;
+bucket **pitem;
+
+int maxrules;
+bucket **plhs;
+
+int name_pool_size;
+char *name_pool;
+
+char *line_format = "\t\t\t\t\t// line %d \"%s\"\n";
+
+
+cachec(c)
+int c;
+{
+    assert(cinc >= 0);
+    if (cinc >= cache_size)
+    {
+	cache_size += 256;
+	cache = REALLOC(cache, cache_size);
+	if (cache == 0) no_space();
+    }
+    cache[cinc] = c;
+    ++cinc;
+}
+
+
+get_line()
+{
+    register FILE *f = input_file;
+    register int c;
+    register int i;
+
+    if (saw_eof || (c = getc(f)) == EOF)
+    {
+	if (line) { FREE(line); line = 0; }
+	cptr = 0;
+	saw_eof = 1;
+	return;
+    }
+
+    if (line == 0 || linesize != (LINESIZE + 1))
+    {
+	if (line) FREE(line);
+	linesize = LINESIZE + 1;
+	line = MALLOC(linesize);
+	if (line == 0) no_space();
+    }
+
+    i = 0;
+    ++lineno;
+    for (;;)
+    {
+	line[i]  =  c;
+	if (c == '\n') { cptr = line; return; }
+	if (++i >= linesize)
+	{
+	    linesize += LINESIZE;
+	    line = REALLOC(line, linesize);
+	    if (line ==  0) no_space();
+	}
+	c = getc(f);
+	if (c ==  EOF)
+	{
+	    line[i] = '\n';
+	    saw_eof = 1;
+	    cptr = line;
+	    return;
+	}
+    }
+}
+
+
+char *
+dup_line()
+{
+    register char *p, *s, *t;
+
+    if (line == 0) return (0);
+    s = line;
+    while (*s != '\n') ++s;
+    p = MALLOC(s - line + 1);
+    if (p == 0) no_space();
+
+    s = line;
+    t = p;
+    while ((*t++ = *s++) != '\n') continue;
+    return (p);
+}
+
+
+skip_comment()
+{
+    register char *s;
+
+    int st_lineno = lineno;
+    char *st_line = dup_line();
+    char *st_cptr = st_line + (cptr - line);
+
+    s = cptr + 2;
+    for (;;)
+    {
+	if (*s == '*' && s[1] == '/')
+	{
+	    cptr = s + 2;
+	    FREE(st_line);
+	    return;
+	}
+	if (*s == '\n')
+	{
+	    get_line();
+	    if (line == 0)
+		unterminated_comment(st_lineno, st_line, st_cptr);
+	    s = cptr;
+	}
+	else
+	    ++s;
+    }
+}
+
+
+int
+nextc()
+{
+    register char *s;
+
+    if (line == 0)
+    {
+	get_line();
+	if (line == 0)
+	    return (EOF);
+    }
+
+    s = cptr;
+    for (;;)
+    {
+	switch (*s)
+	{
+	case '\n':
+	    get_line();
+	    if (line == 0) return (EOF);
+	    s = cptr;
+	    break;
+
+	case ' ':
+	case '\t':
+	case '\f':
+	case '\r':
+	case '\v':
+	case ',':
+	case ';':
+	    ++s;
+	    break;
+
+	case '\\':
+	    cptr = s;
+	    return ('%');
+
+	case '/':
+	    if (s[1] == '*')
+	    {
+		cptr = s;
+		skip_comment();
+		s = cptr;
+		break;
+	    }
+	    else if (s[1] == '/')
+	    {
+		get_line();
+		if (line == 0) return (EOF);
+		s = cptr;
+		break;
+	    }
+	    /* fall through */
+
+	default:
+	    cptr = s;
+	    return (*s);
+	}
+    }
+}
+
+
+int
+keyword()
+{
+    register int c;
+    char *t_cptr = cptr;
+
+    c = *++cptr;
+    if (isalpha(c))
+    {
+	cinc = 0;
+	for (;;)
+	{
+	    if (isalpha(c))
+	    {
+		if (isupper(c)) c = tolower(c);
+		cachec(c);
+	    }
+	    else if (isdigit(c) || c == '_' || c == '.' || c == '$')
+		cachec(c);
+	    else
+		break;
+	    c = *++cptr;
+	}
+	cachec(NUL);
+
+	if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
+	    return (TOKEN);
+	if (strcmp(cache, "type") == 0)
+	    return (TYPE);
+	if (strcmp(cache, "left") == 0)
+	    return (LEFT);
+	if (strcmp(cache, "right") == 0)
+	    return (RIGHT);
+	if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
+	    return (NONASSOC);
+	if (strcmp(cache, "start") == 0)
+	    return (START);
+    }
+    else
+    {
+	++cptr;
+	if (c == '{')
+	    return (TEXT);
+	if (c == '%' || c == '\\')
+	    return (MARK);
+	if (c == '<')
+	    return (LEFT);
+	if (c == '>')
+	    return (RIGHT);
+	if (c == '0')
+	    return (TOKEN);
+	if (c == '2')
+	    return (NONASSOC);
+    }
+    syntax_error(lineno, line, t_cptr);
+    /*NOTREACHED*/
+}
+
+
+copy_text(f)
+FILE *f;
+{
+    register int c;
+    int quote;
+    int need_newline = 0;
+    int t_lineno = lineno;
+    char *t_line = dup_line();
+    char *t_cptr = t_line + (cptr - line - 2);
+
+    if (*cptr == '\n')
+    {
+	get_line();
+	if (line == 0)
+	    unterminated_text(t_lineno, t_line, t_cptr);
+    }
+    fprintf(f, line_format, lineno, input_file_name);
+
+loop:
+    c = *cptr++;
+    switch (c)
+    {
+    case '\n':
+    next_line:
+	putc('\n', f);
+	need_newline = 0;
+	get_line();
+	if (line) goto loop;
+	unterminated_text(t_lineno, t_line, t_cptr);
+
+    case '\'':
+    case '"':
+	{
+	    int s_lineno = lineno;
+	    char *s_line = dup_line();
+	    char *s_cptr = s_line + (cptr - line - 1);
+
+	    quote = c;
+	    putc(c, f);
+	    for (;;)
+	    {
+		c = *cptr++;
+		putc(c, f);
+		if (c == quote)
+		{
+		    need_newline = 1;
+		    FREE(s_line);
+		    goto loop;
+		}
+		if (c == '\n')
+		    unterminated_string(s_lineno, s_line, s_cptr);
+		if (c == '\\')
+		{
+		    c = *cptr++;
+		    putc(c, f);
+		    if (c == '\n')
+		    {
+			get_line();
+			if (line == 0)
+			    unterminated_string(s_lineno, s_line, s_cptr);
+		    }
+		}
+	    }
+	}
+
+    case '/':
+	putc(c, f);
+	need_newline = 1;
+	c = *cptr;
+	if (c == '/')
+	{
+	    do putc(c, f); while ((c = *++cptr) != '\n');
+	    goto next_line;
+	}
+	if (c == '*')
+	{
+	    int c_lineno = lineno;
+	    char *c_line = dup_line();
+	    char *c_cptr = c_line + (cptr - line - 1);
+
+	    putc('*', f);
+	    ++cptr;
+	    for (;;)
+	    {
+		c = *cptr++;
+		putc(c, f);
+		if (c == '*' && *cptr == '/')
+		{
+		    putc('/', f);
+		    ++cptr;
+		    FREE(c_line);
+		    goto loop;
+		}
+		if (c == '\n')
+		{
+		    get_line();
+		    if (line == 0)
+			unterminated_comment(c_lineno, c_line, c_cptr);
+		}
+	    }
+	}
+	need_newline = 1;
+	goto loop;
+
+    case '%':
+    case '\\':
+	if (*cptr == '}')
+	{
+	    if (need_newline) putc('\n', f);
+	    ++cptr;
+	    FREE(t_line);
+	    return;
+	}
+	/* fall through */
+
+    default:
+	putc(c, f);
+	need_newline = 1;
+	goto loop;
+    }
+}
+
+int
+hexval(c)
+int c;
+{
+    if (c >= '0' && c <= '9')
+	return (c - '0');
+    if (c >= 'A' && c <= 'F')
+	return (c - 'A' + 10);
+    if (c >= 'a' && c <= 'f')
+	return (c - 'a' + 10);
+    return (-1);
+}
+
+
+bucket *
+get_literal()
+{
+    register int c, quote;
+    register int i;
+    register int n;
+    register char *s;
+    register bucket *bp;
+    int s_lineno = lineno;
+    char *s_line = dup_line();
+    char *s_cptr = s_line + (cptr - line);
+
+    quote = *cptr++;
+    cinc = 0;
+    for (;;)
+    {
+	c = *cptr++;
+	if (c == quote) break;
+	if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
+	if (c == '\\')
+	{
+	    char *c_cptr = cptr - 1;
+
+	    c = *cptr++;
+	    switch (c)
+	    {
+	    case '\n':
+		get_line();
+		if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
+		continue;
+
+	    case '0': case '1': case '2': case '3':
+	    case '4': case '5': case '6': case '7':
+		n = c - '0';
+		c = *cptr;
+		if (IS_OCTAL(c))
+		{
+		    n = (n << 3) + (c - '0');
+		    c = *++cptr;
+		    if (IS_OCTAL(c))
+		    {
+			n = (n << 3) + (c - '0');
+			++cptr;
+		    }
+		}
+		if (n > MAXCHAR) illegal_character(c_cptr);
+		c = n;
+	    	break;
+
+	    case 'x':
+		c = *cptr++;
+		n = hexval(c);
+		if (n < 0 || n >= 16)
+		    illegal_character(c_cptr);
+		for (;;)
+		{
+		    c = *cptr;
+		    i = hexval(c);
+		    if (i < 0 || i >= 16) break;
+		    ++cptr;
+		    n = (n << 4) + i;
+		    if (n > MAXCHAR) illegal_character(c_cptr);
+		}
+		c = n;
+		break;
+
+	    case 'a': c = 7; break;
+	    case 'b': c = '\b'; break;
+	    case 'f': c = '\f'; break;
+	    case 'n': c = '\n'; break;
+	    case 'r': c = '\r'; break;
+	    case 't': c = '\t'; break;
+	    case 'v': c = '\v'; break;
+	    }
+	}
+	cachec(c);
+    }
+    FREE(s_line);
+
+    n = cinc;
+    s = MALLOC(n);
+    if (s == 0) no_space();
+    
+    for (i = 0; i < n; ++i)
+	s[i] = cache[i];
+
+    cinc = 0;
+    if (n == 1)
+	cachec('\'');
+    else
+	cachec('"');
+
+    for (i = 0; i < n; ++i)
+    {
+	c = ((unsigned char *)s)[i];
+	if (c == '\\' || c == cache[0])
+	{
+	    cachec('\\');
+	    cachec(c);
+	}
+	else if (isprint(c))
+	    cachec(c);
+	else
+	{
+	    cachec('\\');
+	    switch (c)
+	    {
+	    case 7: cachec('a'); break;
+	    case '\b': cachec('b'); break;
+	    case '\f': cachec('f'); break;
+	    case '\n': cachec('n'); break;
+	    case '\r': cachec('r'); break;
+	    case '\t': cachec('t'); break;
+	    case '\v': cachec('v'); break;
+	    default:
+		cachec(((c >> 6) & 7) + '0');
+		cachec(((c >> 3) & 7) + '0');
+		cachec((c & 7) + '0');
+		break;
+	    }
+	}
+    }
+
+    if (n == 1)
+	cachec('\'');
+    else
+	cachec('"');
+
+    cachec(NUL);
+    bp = lookup(cache);
+    bp->class = TERM;
+    if (n == 1 && bp->value == UNDEFINED)
+	bp->value = *(unsigned char *)s;
+    FREE(s);
+
+    return (bp);
+}
+
+
+int
+is_reserved(name)
+char *name;
+{
+    char *s;
+
+    if (strcmp(name, ".") == 0 ||
+	    strcmp(name, "$accept") == 0 ||
+	    strcmp(name, "$end") == 0)
+	return (1);
+
+    if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
+    {
+	s = name + 3;
+	while (isdigit(*s)) ++s;
+	if (*s == NUL) return (1);
+    }
+
+    return (0);
+}
+
+
+bucket *
+get_name()
+{
+    register int c;
+
+    cinc = 0;
+    for (c = *cptr; IS_IDENT(c); c = *++cptr)
+	cachec(c);
+    cachec(NUL);
+
+    if (is_reserved(cache)) used_reserved(cache);
+
+    return (lookup(cache));
+}
+
+
+int
+get_number()
+{
+    register int c;
+    register int n;
+
+    n = 0;
+    for (c = *cptr; isdigit(c); c = *++cptr)
+	n = 10*n + (c - '0');
+
+    return (n);
+}
+
+
+char *
+get_tag(int emptyOk)
+{
+    register int c;
+    register int i;
+    register char *s;
+    int t_lineno = lineno;
+    char *t_line = dup_line();
+    char *t_cptr = t_line + (cptr - line);
+
+    ++cptr;
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (emptyOk && c == '>') {
+      ++cptr; return 0;	// 0 indicates empty tag if emptyOk
+    }
+    if (!isalpha(c) && c != '_' && c != '$')
+	illegal_tag(t_lineno, t_line, t_cptr);
+
+    cinc = 0;
+    do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
+    cachec(NUL);
+
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (c != '>')
+	illegal_tag(t_lineno, t_line, t_cptr);
+    ++cptr;
+
+    for (i = 0; i < ntags; ++i)
+    {
+	if (strcmp(cache, tag_table[i]) == 0)
+	    return (tag_table[i]);
+    }
+
+    if (ntags >= tagmax)
+    {
+	tagmax += 16;
+	tag_table = (char **)
+			(tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
+				   : MALLOC(tagmax*sizeof(char *)));
+	if (tag_table == 0) no_space();
+    }
+
+    s = MALLOC(cinc);
+    if  (s == 0) no_space();
+    strcpy(s, cache);
+    tag_table[ntags] = s;
+    ++ntags;
+    FREE(t_line);
+    return (s);
+}
+
+
+declare_tokens(assoc)
+int assoc;
+{
+    register int c;
+    register bucket *bp;
+    int value;
+    char *tag = 0;
+
+    if (assoc != TOKEN) ++prec;
+
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (c == '<')
+    {
+	tag = get_tag(0);
+	c = nextc();
+	if (c == EOF) unexpected_EOF();
+    }
+
+    for (;;)
+    {
+	if (isalpha(c) || c == '_' || c == '.' || c == '$')
+	    bp = get_name();
+	else if (c == '\'' || c == '"')
+	    bp = get_literal();
+	else
+	    return;
+
+	if (bp == goal) tokenized_start(bp->name);
+	bp->class = TERM;
+
+	if (tag)
+	{
+	    if (bp->tag && tag != bp->tag)
+		retyped_warning(bp->name);
+	    bp->tag = tag;
+	}
+
+	if (assoc != TOKEN)
+	{
+	    if (bp->prec && prec != bp->prec)
+		reprec_warning(bp->name);
+	    bp->assoc = assoc;
+	    bp->prec = prec;
+	}
+
+	c = nextc();
+	if (c == EOF) unexpected_EOF();
+	value = UNDEFINED;
+	if (isdigit(c))
+	{
+	    value = get_number();
+	    if (bp->value != UNDEFINED && value != bp->value)
+		revalued_warning(bp->name);
+	    bp->value = value;
+	    c = nextc();
+	    if (c == EOF) unexpected_EOF();
+	}
+    }
+}
+
+
+declare_types()
+{
+    register int c;
+    register bucket *bp;
+    char *tag;
+
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (c != '<') syntax_error(lineno, line, cptr);
+    tag = get_tag(0);
+
+    for (;;)
+    {
+	c = nextc();
+	if (isalpha(c) || c == '_' || c == '.' || c == '$')
+	    bp = get_name();
+	else if (c == '\'' || c == '"')
+	    bp = get_literal();
+	else
+	    return;
+
+	if (bp->tag && tag != bp->tag)
+	    retyped_warning(bp->name);
+	bp->tag = tag;
+    }
+}
+
+
+declare_start()
+{
+    register int c;
+    register bucket *bp;
+
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (!isalpha(c) && c != '_' && c != '.' && c != '$')
+	syntax_error(lineno, line, cptr);
+    bp = get_name();
+    if (bp->class == TERM)
+	terminal_start(bp->name);
+    if (goal && goal != bp)
+	restarted_warning();
+    goal = bp;
+}
+
+
+read_declarations()
+{
+    register int c, k;
+
+    cache_size = 256;
+    cache = MALLOC(cache_size);
+    if (cache == 0) no_space();
+
+    for (;;)
+    {
+	c = nextc();
+	if (c == EOF) unexpected_EOF();
+	if (c != '%') syntax_error(lineno, line, cptr);
+	switch (k = keyword())
+	{
+	case MARK:
+	    return;
+
+	case TEXT:
+	    copy_text(prolog_file);
+	    break;
+
+	case TOKEN:
+	case LEFT:
+	case RIGHT:
+	case NONASSOC:
+	    declare_tokens(k);
+	    break;
+
+	case TYPE:
+	    declare_types();
+	    break;
+
+	case START:
+	    declare_start();
+	    break;
+	}
+    }
+}
+
+
+initialize_grammar()
+{
+    nitems = 4;
+    maxitems = 300;
+    pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
+    if (pitem == 0) no_space();
+    pitem[0] = 0;
+    pitem[1] = 0;
+    pitem[2] = 0;
+    pitem[3] = 0;
+
+    nrules = 3;
+    maxrules = 100;
+    plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
+    if (plhs == 0) no_space();
+    plhs[0] = 0;
+    plhs[1] = 0;
+    plhs[2] = 0;
+    rprec = (short *) MALLOC(maxrules*sizeof(short));
+    if (rprec == 0) no_space();
+    rprec[0] = 0;
+    rprec[1] = 0;
+    rprec[2] = 0;
+    rassoc = (char *) MALLOC(maxrules*sizeof(char));
+    if (rassoc == 0) no_space();
+    rassoc[0] = TOKEN;
+    rassoc[1] = TOKEN;
+    rassoc[2] = TOKEN;
+}
+
+
+expand_items()
+{
+    maxitems += 300;
+    pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
+    if (pitem == 0) no_space();
+}
+
+
+expand_rules()
+{
+    maxrules += 100;
+    plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
+    if (plhs == 0) no_space();
+    rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
+    if (rprec == 0) no_space();
+    rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
+    if (rassoc == 0) no_space();
+}
+
+
+advance_to_start()
+{
+    register int c;
+    register bucket *bp;
+    char *s_cptr;
+    int s_lineno;
+
+    for (;;)
+    {
+	c = nextc();
+	if (c != '%') break;
+	s_cptr = cptr;
+	switch (keyword())
+	{
+	case MARK:
+	    no_grammar();
+
+	case TEXT:
+	    copy_text(local_file);
+	    break;
+
+	case START:
+	    declare_start();
+	    break;
+
+	default:
+	    syntax_error(lineno, line, s_cptr);
+	}
+    }
+
+    c = nextc();
+    if (!isalpha(c) && c != '_' && c != '.' && c != '_')
+	syntax_error(lineno, line, cptr);
+    bp = get_name();
+    if (goal == 0)
+    {
+	if (bp->class == TERM)
+	    terminal_start(bp->name);
+	goal = bp;
+    }
+
+    s_lineno = lineno;
+    c = nextc();
+    if (c == EOF) unexpected_EOF();
+    if (c != ':') syntax_error(lineno, line, cptr);
+    start_rule(bp, s_lineno);
+    ++cptr;
+}
+
+
+start_rule(bp, s_lineno)
+register bucket *bp;
+int s_lineno;
+{
+    if (bp->class == TERM)
+	terminal_lhs(s_lineno);
+    bp->class = NONTERM;
+    if (nrules >= maxrules)
+	expand_rules();
+    plhs[nrules] = bp;
+    rprec[nrules] = UNDEFINED;
+    rassoc[nrules] = TOKEN;
+}
+
+
+end_rule()
+{
+    register int i;
+
+    if (!last_was_action && plhs[nrules]->tag)
+    {
+	for (i = nitems - 1; pitem[i]; --i) continue;
+	if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag)
+	    default_action_warning();	/** if classes don't match exactly **/
+    }					/** bug: could be superclass... **/
+
+    last_was_action = 0;
+    if (nitems >= maxitems) expand_items();
+    pitem[nitems] = 0;
+    ++nitems;
+    ++nrules;
+}
+
+
+insert_empty_rule()
+{
+    register bucket *bp, **bpp;
+
+    assert(cache);
+    sprintf(cache, "$$%d", ++gensym);
+    bp = make_bucket(cache);
+    last_symbol->next = bp;
+    last_symbol = bp;
+    bp->tag = plhs[nrules]->tag;
+    bp->class = NONTERM;
+
+    if ((nitems += 2) > maxitems)
+	expand_items();
+    bpp = pitem + nitems - 1;
+    *bpp-- = bp;
+    while (bpp[0] = bpp[-1]) --bpp;
+
+    if (++nrules >= maxrules)
+	expand_rules();
+    plhs[nrules] = plhs[nrules-1];
+    plhs[nrules-1] = bp;
+    rprec[nrules] = rprec[nrules-1];
+    rprec[nrules-1] = 0;
+    rassoc[nrules] = rassoc[nrules-1];
+    rassoc[nrules-1] = TOKEN;
+}
+
+
+add_symbol()
+{
+    register int c;
+    register bucket *bp;
+    int s_lineno = lineno;
+
+    c = *cptr;
+    if (c == '\'' || c == '"')
+	bp = get_literal();
+    else
+	bp = get_name();
+
+    c = nextc();
+    if (c == ':')
+    {
+	end_rule();
+	start_rule(bp, s_lineno);
+	++cptr;
+	return;
+    }
+
+    if (last_was_action)
+	insert_empty_rule();
+    last_was_action = 0;
+
+    if (++nitems > maxitems)
+	expand_items();
+    pitem[nitems-1] = bp;
+}
+
+
+copy_action()
+{
+    register int c;
+    register int i, n;
+    int depth;
+    int quote;
+    char *tag;
+    register FILE *f = action_file;
+    int a_lineno = lineno;
+    char *a_line = dup_line();
+    char *a_cptr = a_line + (cptr - line);
+
+    if (last_was_action)
+	insert_empty_rule();
+    last_was_action = 1;
+
+    fprintf(f, "case %d:\n", nrules - 2);
+    fprintf(f, line_format, lineno, input_file_name);
+    putc(' ', f); putc(' ', f);
+    if (*cptr == '=') ++cptr;
+
+    n = 0;
+    for (i = nitems - 1; pitem[i]; --i) ++n;
+
+    depth = 0;
+loop:
+    c = *cptr;
+    if (c == '$')
+    {
+	if (cptr[1] == '<')
+	{
+	    int d_lineno = lineno;
+	    char *d_line = dup_line();
+	    char *d_cptr = d_line + (cptr - line);
+
+	    ++cptr;
+	    tag = get_tag(1);
+	    c = *cptr;
+	    if (c == '$')
+	    {   if (tag && strcmp(tag, "Object"))
+					fprintf(f, "((%s)yyVal)", tag);
+		else fprintf(f, "yyVal");
+		++cptr;
+		FREE(d_line);
+		goto loop;
+	    }
+	    else if (isdigit(c))
+	    {
+		i = get_number();
+		if (i > n) dollar_warning(d_lineno, i);
+		if (tag && strcmp(tag, "Object"))
+			fprintf(f, "((%s)yyVals[%d+yyTop])", tag, i - n);
+		else fprintf(f, "yyVals[%d+yyTop]", i - n);
+		FREE(d_line);
+		goto loop;
+	    }
+	    else if (c == '-' && isdigit(cptr[1]))
+	    {
+		++cptr;
+		i = -get_number() - n;
+		if (tag && strcmp(tag, "Object"))
+			fprintf(f, "((%s)yyVals[%d+yyTop])", tag, i);
+		else fprintf(f, "yyVals[%d+yyTop]", tag, i);
+		FREE(d_line);
+		goto loop;
+	    }
+	    else
+		dollar_error(d_lineno, d_line, d_cptr);
+	}
+	else if (cptr[1] == '$')
+	{
+	    if (ntags && plhs[nrules]->tag == 0)
+		untyped_lhs();
+	    fprintf(f, "yyVal");
+	    cptr += 2;
+	    goto loop;
+	}
+	else if (isdigit(cptr[1]))
+	{
+	    ++cptr;
+	    i = get_number();
+	    if (ntags)
+	    {
+		if (i <= 0 || i > n)
+		    unknown_rhs(i);
+		tag = pitem[nitems + i - n - 1]->tag;
+		if (tag == 0)
+		    untyped_rhs(i, pitem[nitems + i - n - 1]->name),
+		    fprintf(f, "yyVals[%d+yyTop]", i - n);
+		else if (strcmp(tag, "Object"))
+		    fprintf(f, "((%s)yyVals[%d+yyTop])", tag, i - n);
+		else
+		    fprintf(f, "yyVals[%d+yyTop]", i - n);
+	    }
+	    else
+	    {
+		if (i > n)
+		    dollar_warning(lineno, i);
+		fprintf(f, "yyVals[%d+yyTop]", i - n);
+	    }
+	    goto loop;
+	}
+	else if (cptr[1] == '-')
+	{
+	    cptr += 2;
+	    i = get_number();
+	    if (ntags)
+		unknown_rhs(-i);
+	    fprintf(f, "yyVals[%d+yyTop]", -i - n);
+	    goto loop;
+	}
+    }
+    if (isalpha(c) || c == '_' || c == '$')
+    {
+	do
+	{
+	    putc(c, f);
+	    c = *++cptr;
+	} while (isalnum(c) || c == '_' || c == '$');
+	goto loop;
+    }
+    putc(c, f);
+    ++cptr;
+    switch (c)
+    {
+    case '\n':
+    next_line:
+	get_line();
+	if (line) goto loop;
+	unterminated_action(a_lineno, a_line, a_cptr);
+
+    case ';':
+	if (depth > 0) goto loop;
+	fprintf(f, "\nbreak;\n");
+	return;
+
+    case '{':
+	++depth;
+	goto loop;
+
+    case '}':
+	if (--depth > 0) goto loop;
+	fprintf(f, "\n  break;\n");
+	return;
+
+    case '\'':
+    case '"':
+	{
+	    int s_lineno = lineno;
+	    char *s_line = dup_line();
+	    char *s_cptr = s_line + (cptr - line - 1);
+
+	    quote = c;
+	    for (;;)
+	    {
+		c = *cptr++;
+		putc(c, f);
+		if (c == quote)
+		{
+		    FREE(s_line);
+		    goto loop;
+		}
+		if (c == '\n')
+		    unterminated_string(s_lineno, s_line, s_cptr);
+		if (c == '\\')
+		{
+		    c = *cptr++;
+		    putc(c, f);
+		    if (c == '\n')
+		    {
+			get_line();
+			if (line == 0)
+			    unterminated_string(s_lineno, s_line, s_cptr);
+		    }
+		}
+	    }
+	}
+
+    case '/':
+	c = *cptr;
+	if (c == '/')
+	{
+	    putc('*', f);
+	    while ((c = *++cptr) != '\n')
+	    {
+		if (c == '*' && cptr[1] == '/')
+		    fprintf(f, "* ");
+		else
+		    putc(c, f);
+	    }
+	    fprintf(f, "*/\n");
+	    goto next_line;
+	}
+	if (c == '*')
+	{
+	    int c_lineno = lineno;
+	    char *c_line = dup_line();
+	    char *c_cptr = c_line + (cptr - line - 1);
+
+	    putc('*', f);
+	    ++cptr;
+	    for (;;)
+	    {
+		c = *cptr++;
+		putc(c, f);
+		if (c == '*' && *cptr == '/')
+		{
+		    putc('/', f);
+		    ++cptr;
+		    FREE(c_line);
+		    goto loop;
+		}
+		if (c == '\n')
+		{
+		    get_line();
+		    if (line == 0)
+			unterminated_comment(c_lineno, c_line, c_cptr);
+		}
+	    }
+	}
+	goto loop;
+
+    default:
+	goto loop;
+    }
+}
+
+
+int
+mark_symbol()
+{
+    register int c;
+    register bucket *bp;
+
+    c = cptr[1];
+    if (c == '%' || c == '\\')
+    {
+	cptr += 2;
+	return (1);
+    }
+
+    if (c == '=')
+	cptr += 2;
+    else if ((c == 'p' || c == 'P') &&
+	     ((c = cptr[2]) == 'r' || c == 'R') &&
+	     ((c = cptr[3]) == 'e' || c == 'E') &&
+	     ((c = cptr[4]) == 'c' || c == 'C') &&
+	     ((c = cptr[5], !IS_IDENT(c))))
+	cptr += 5;
+    else
+	syntax_error(lineno, line, cptr);
+
+    c = nextc();
+    if (isalpha(c) || c == '_' || c == '.' || c == '$')
+	bp = get_name();
+    else if (c == '\'' || c == '"')
+	bp = get_literal();
+    else
+    {
+	syntax_error(lineno, line, cptr);
+	/*NOTREACHED*/
+    }
+
+    if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
+	prec_redeclared();
+
+    rprec[nrules] = bp->prec;
+    rassoc[nrules] = bp->assoc;
+    return (0);
+}
+
+
+read_grammar()
+{
+    register int c;
+
+    initialize_grammar();
+    advance_to_start();
+
+    for (;;)
+    {
+	c = nextc();
+	if (c == EOF) break;
+	if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
+		c == '"')
+	    add_symbol();
+	else if (c == '{' || c == '=')
+	    copy_action();
+	else if (c == '|')
+	{
+	    end_rule();
+	    start_rule(plhs[nrules-1], 0);
+	    ++cptr;
+	}
+	else if (c == '%')
+	{
+	    if (mark_symbol()) break;
+	}
+	else
+	    syntax_error(lineno, line, cptr);
+    }
+    end_rule();
+}
+
+
+free_tags()
+{
+    register int i;
+
+    if (tag_table == 0) return;
+
+    for (i = 0; i < ntags; ++i)
+    {
+	assert(tag_table[i]);
+	FREE(tag_table[i]);
+    }
+    FREE(tag_table);
+}
+
+
+pack_names()
+{
+    register bucket *bp;
+    register char *p, *s, *t;
+
+    name_pool_size = 13;  /* 13 == sizeof("$end") + sizeof("$accept") */
+    for (bp = first_symbol; bp; bp = bp->next)
+	name_pool_size += strlen(bp->name) + 1;
+    name_pool = MALLOC(name_pool_size);
+    if (name_pool == 0) no_space();
+
+    strcpy(name_pool, "$accept");
+    strcpy(name_pool+8, "$end");
+    t = name_pool + 13;
+    for (bp = first_symbol; bp; bp = bp->next)
+    {
+	p = t;
+	s = bp->name;
+	while (*t++ = *s++) continue;
+	FREE(bp->name);
+	bp->name = p;
+    }
+}
+
+
+check_symbols()
+{
+    register bucket *bp;
+
+    if (goal->class == UNKNOWN)
+	undefined_goal(goal->name);
+
+    for (bp = first_symbol; bp; bp = bp->next)
+    {
+	if (bp->class == UNKNOWN)
+	{
+	    undefined_symbol_warning(bp->name);
+	    bp->class = TERM;
+	}
+    }
+}
+
+
+pack_symbols()
+{
+    register bucket *bp;
+    register bucket **v;
+    register int i, j, k, n;
+
+    nsyms = 2;
+    ntokens = 1;
+    for (bp = first_symbol; bp; bp = bp->next)
+    {
+	++nsyms;
+	if (bp->class == TERM) ++ntokens;
+    }
+    start_symbol = ntokens;
+    nvars = nsyms - ntokens;
+
+    symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
+    if (symbol_name == 0) no_space();
+    symbol_value = (short *) MALLOC(nsyms*sizeof(short));
+    if (symbol_value == 0) no_space();
+    symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
+    if (symbol_prec == 0) no_space();
+    symbol_assoc = MALLOC(nsyms);
+    if (symbol_assoc == 0) no_space();
+
+    v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
+    if (v == 0) no_space();
+
+    v[0] = 0;
+    v[start_symbol] = 0;
+
+    i = 1;
+    j = start_symbol + 1;
+    for (bp = first_symbol; bp; bp = bp->next)
+    {
+	if (bp->class == TERM)
+	    v[i++] = bp;
+	else
+	    v[j++] = bp;
+    }
+    assert(i == ntokens && j == nsyms);
+
+    for (i = 1; i < ntokens; ++i)
+	v[i]->index = i;
+
+    goal->index = start_symbol + 1;
+    k = start_symbol + 2;
+    while (++i < nsyms)
+	if (v[i] != goal)
+	{
+	    v[i]->index = k;
+	    ++k;
+	}
+
+    goal->value = 0;
+    k = 1;
+    for (i = start_symbol + 1; i < nsyms; ++i)
+    {
+	if (v[i] != goal)
+	{
+	    v[i]->value = k;
+	    ++k;
+	}
+    }
+
+    k = 0;
+    for (i = 1; i < ntokens; ++i)
+    {
+	n = v[i]->value;
+	if (n > 256)
+	{
+	    for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
+		symbol_value[j] = symbol_value[j-1];
+	    symbol_value[j] = n;
+	}
+    }
+
+    if (v[1]->value == UNDEFINED)
+	v[1]->value = 256;
+
+    j = 0;
+    n = 257;
+    for (i = 2; i < ntokens; ++i)
+    {
+	if (v[i]->value == UNDEFINED)
+	{
+	    while (j < k && n == symbol_value[j])
+	    {
+		while (++j < k && n == symbol_value[j]) continue;
+		++n;
+	    }
+	    v[i]->value = n;
+	    ++n;
+	}
+    }
+
+    symbol_name[0] = name_pool + 8;
+    symbol_value[0] = 0;
+    symbol_prec[0] = 0;
+    symbol_assoc[0] = TOKEN;
+    for (i = 1; i < ntokens; ++i)
+    {
+	symbol_name[i] = v[i]->name;
+	symbol_value[i] = v[i]->value;
+	symbol_prec[i] = v[i]->prec;
+	symbol_assoc[i] = v[i]->assoc;
+    }
+    symbol_name[start_symbol] = name_pool;
+    symbol_value[start_symbol] = -1;
+    symbol_prec[start_symbol] = 0;
+    symbol_assoc[start_symbol] = TOKEN;
+    for (++i; i < nsyms; ++i)
+    {
+	k = v[i]->index;
+	symbol_name[k] = v[i]->name;
+	symbol_value[k] = v[i]->value;
+	symbol_prec[k] = v[i]->prec;
+	symbol_assoc[k] = v[i]->assoc;
+    }
+
+    FREE(v);
+}
+
+
+pack_grammar()
+{
+    register int i, j;
+    int assoc, prec;
+
+    ritem = (short *) MALLOC(nitems*sizeof(short));
+    if (ritem == 0) no_space();
+    rlhs = (short *) MALLOC(nrules*sizeof(short));
+    if (rlhs == 0) no_space();
+    rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
+    if (rrhs == 0) no_space();
+    rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
+    if (rprec == 0) no_space();
+    rassoc = REALLOC(rassoc, nrules);
+    if (rassoc == 0) no_space();
+
+    ritem[0] = -1;
+    ritem[1] = goal->index;
+    ritem[2] = 0;
+    ritem[3] = -2;
+    rlhs[0] = 0;
+    rlhs[1] = 0;
+    rlhs[2] = start_symbol;
+    rrhs[0] = 0;
+    rrhs[1] = 0;
+    rrhs[2] = 1;
+
+    j = 4;
+    for (i = 3; i < nrules; ++i)
+    {
+	rlhs[i] = plhs[i]->index;
+	rrhs[i] = j;
+	assoc = TOKEN;
+	prec = 0;
+	while (pitem[j])
+	{
+	    ritem[j] = pitem[j]->index;
+	    if (pitem[j]->class == TERM)
+	    {
+		prec = pitem[j]->prec;
+		assoc = pitem[j]->assoc;
+	    }
+	    ++j;
+	}
+	ritem[j] = -i;
+	++j;
+	if (rprec[i] == UNDEFINED)
+	{
+	    rprec[i] = prec;
+	    rassoc[i] = assoc;
+	}
+    }
+    rrhs[i] = j;
+
+    FREE(plhs);
+    FREE(pitem);
+}
+
+
+print_grammar()
+{
+    register int i, j, k;
+    int spacing;
+    register FILE *f = verbose_file;
+
+    if (!vflag) return;
+
+    k = 1;
+    for (i = 2; i < nrules; ++i)
+    {
+	if (rlhs[i] != rlhs[i-1])
+	{
+	    if (i != 2) fprintf(f, "\n");
+	    fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
+	    spacing = strlen(symbol_name[rlhs[i]]) + 1;
+	}
+	else
+	{
+	    fprintf(f, "%4d  ", i - 2);
+	    j = spacing;
+	    while (--j >= 0) putc(' ', f);
+	    putc('|', f);
+	}
+
+	while (ritem[k] >= 0)
+	{
+	    fprintf(f, " %s", symbol_name[ritem[k]]);
+	    ++k;
+	}
+	++k;
+	putc('\n', f);
+    }
+}
+
+
+reader()
+{
+    create_symbol_table();
+    read_declarations();
+    read_grammar();
+    free_symbol_table();
+    free_tags();
+    pack_names();
+    check_symbols();
+    pack_symbols();
+    pack_grammar();
+    free_symbols();
+    print_grammar();
+}

+ 268 - 0
mcs/jay/skeleton

@@ -0,0 +1,268 @@
+#	jay skeleton
+
+#	character in column 1 determines outcome...
+#		# is a comment
+#		. is copied
+#		t is copied as //t if -t is set
+#	other lines are interpreted to call jay procedures
+
+.// created by jay 0.7 (c) 1998 [email protected]
+.
+ prolog		## %{ ... %} prior to the first %%
+
+.// %token constants
+.
+ tokens public static final int
+.
+.  /** thrown for irrecoverable syntax errors and stack overflow.
+.    */
+.  public static class yyException extends java.lang.Exception {
+.    public yyException (String message) {
+.      super(message);
+.    }
+.  }
+.
+.  /** must be implemented by a scanner object to supply input to the parser.
+.    */
+.  public interface yyInput {
+.    /** move on to next token.
+.        @return false if positioned beyond tokens.
+.        @throws IOException on input error.
+.      */
+.    boolean advance () throws java.io.IOException;
+.    /** classifies current token.
+.        Should not be called if advance() returned false.
+.        @return current %token or single character.
+.      */
+.    int token ();
+.    /** associated with current token.
+.        Should not be called if advance() returned false.
+.        @return value for token().
+.      */
+.    Object value ();
+.  }
+.
+.  /** simplified error message.
+.      @see <a href="#yyerror(java.lang.String, java.lang.String[])">yyerror</a>
+.    */
+.  public void yyerror (String message) {
+.    yyerror(message, null);
+.  }
+.
+.  /** (syntax) error message.
+.      Can be overwritten to control message format.
+.      @param message text to be displayed.
+.      @param expected vector of acceptable tokens, if available.
+.    */
+.  public void yyerror (String message, String[] expected) {
+.    if (expected != null && expected.length > 0) {
+.      System.err.print(message+", expecting");
+.      for (int n = 0; n < expected.length; ++ n)
+.        System.err.print(" "+expected[n]);
+.      System.err.println();
+.    } else
+.      System.err.println(message);
+.  }
+.
+.  /** debugging support, requires the package jay.yydebug.
+.      Set to null to suppress debugging messages.
+.    */
+t  protected jay.yydebug.yyDebug yydebug;
+.
+ debug			## tables for debugging support
+.
+.  /** index-checked interface to yyName[].
+.      @param token single character or %token value.
+.      @return token name or [illegal] or [unknown].
+.    */
+t  public static final String yyname (int token) {
+t    if (token < 0 || token > yyName.length) return "[illegal]";
+t    String name;
+t    if ((name = yyName[token]) != null) return name;
+t    return "[unknown]";
+t  }
+.
+.  /** computes list of expected tokens on error by tracing the tables.
+.      @param state for which to compute the list.
+.      @return list of token names.
+.    */
+.  protected String[] yyExpecting (int state) {
+.    int token, n, len = 0;
+.    boolean[] ok = new boolean[yyName.length];
+.
+.    if ((n = yySindex[state]) != 0)
+.      for (token = n < 0 ? -n : 0;
+.           token < yyName.length && n+token < yyTable.length; ++ token)
+.        if (yyCheck[n+token] == token && !ok[token] && yyName[token] != null) {
+.          ++ len;
+.          ok[token] = true;
+.        }
+.    if ((n = yyRindex[state]) != 0)
+.      for (token = n < 0 ? -n : 0;
+.           token < yyName.length && n+token < yyTable.length; ++ token)
+.        if (yyCheck[n+token] == token && !ok[token] && yyName[token] != null) {
+.          ++ len;
+.          ok[token] = true;
+.        }
+.
+.    String result[] = new String[len];
+.    for (n = token = 0; n < len;  ++ token)
+.      if (ok[token]) result[n++] = yyName[token];
+.    return result;
+.  }
+.
+.  /** the generated parser, with debugging messages.
+.      Maintains a state and a value stack, currently with fixed maximum size.
+.      @param yyLex scanner.
+.      @param yydebug debug message writer implementing yyDebug, or null.
+.      @return result of the last reduction, if any.
+.      @throws yyException on irrecoverable parse error.
+.    */
+.  public Object yyparse (yyInput yyLex, Object yydebug)
+.				throws java.io.IOException, yyException {
+t    this.yydebug = (jay.yydebug.yyDebug)yydebug;
+.    return yyparse(yyLex);
+.  }
+.
+.  /** initial size and increment of the state/value stack [default 256].
+.      This is not final so that it can be overwritten outside of invocations
+.      of yyparse().
+.    */
+.  protected int yyMax;
+.
+.  /** executed at the beginning of a reduce action.
+.      Used as $$ = yyDefault($1), prior to the user-specified action, if any.
+.      Can be overwritten to provide deep copy, etc.
+.      @param first value for $1, or null.
+.      @return first.
+.    */
+.  protected Object yyDefault (Object first) {
+.    return first;
+.  }
+.
+.  /** the generated parser.
+.      Maintains a state and a value stack, currently with fixed maximum size.
+.      @param yyLex scanner.
+.      @return result of the last reduction, if any.
+.      @throws yyException on irrecoverable parse error.
+.    */
+.  public Object yyparse (yyInput yyLex)
+.				throws java.io.IOException, yyException {
+.    if (yyMax <= 0) yyMax = 256;			// initial size
+.    int yyState = 0, yyStates[] = new int[yyMax];	// state stack
+.    Object yyVal = null, yyVals[] = new Object[yyMax];	// value stack
+.    int yyToken = -1;					// current input
+.    int yyErrorFlag = 0;				// #tks to shift
+.
+ local		## %{ ... %} after the first %%
+
+.    yyLoop: for (int yyTop = 0;; ++ yyTop) {
+.      if (yyTop >= yyStates.length) {			// dynamically increase
+.        int[] i = new int[yyStates.length+yyMax];
+.        System.arraycopy(yyStates, 0, i, 0, yyStates.length);
+.        yyStates = i;
+.        Object[] o = new Object[yyVals.length+yyMax];
+.        System.arraycopy(yyVals, 0, o, 0, yyVals.length);
+.        yyVals = o;
+.      }
+.      yyStates[yyTop] = yyState;
+.      yyVals[yyTop] = yyVal;
+t      if (yydebug != null) yydebug.push(yyState, yyVal);
+.
+.      yyDiscarded: for (;;) {	// discarding a token does not change stack
+.        int yyN;
+.        if ((yyN = yyDefRed[yyState]) == 0) {	// else [default] reduce (yyN)
+.          if (yyToken < 0) {
+.            yyToken = yyLex.advance() ? yyLex.token() : 0;
+t            if (yydebug != null)
+t              yydebug.lex(yyState, yyToken, yyname(yyToken), yyLex.value());
+.          }
+.          if ((yyN = yySindex[yyState]) != 0 && (yyN += yyToken) >= 0
+.              && yyN < yyTable.length && yyCheck[yyN] == yyToken) {
+t            if (yydebug != null)
+t              yydebug.shift(yyState, yyTable[yyN], yyErrorFlag-1);
+.            yyState = yyTable[yyN];		// shift to yyN
+.            yyVal = yyLex.value();
+.            yyToken = -1;
+.            if (yyErrorFlag > 0) -- yyErrorFlag;
+.            continue yyLoop;
+.          }
+.          if ((yyN = yyRindex[yyState]) != 0 && (yyN += yyToken) >= 0
+.              && yyN < yyTable.length && yyCheck[yyN] == yyToken)
+.            yyN = yyTable[yyN];			// reduce (yyN)
+.          else
+.            switch (yyErrorFlag) {
+.  
+.            case 0:
+.              yyerror("syntax error", yyExpecting(yyState));
+t              if (yydebug != null) yydebug.error("syntax error");
+.  
+.            case 1: case 2:
+.              yyErrorFlag = 3;
+.              do {
+.                if ((yyN = yySindex[yyStates[yyTop]]) != 0
+.                    && (yyN += yyErrorCode) >= 0 && yyN < yyTable.length
+.                    && yyCheck[yyN] == yyErrorCode) {
+t                  if (yydebug != null)
+t                    yydebug.shift(yyStates[yyTop], yyTable[yyN], 3);
+.                  yyState = yyTable[yyN];
+.                  yyVal = yyLex.value();
+.                  continue yyLoop;
+.                }
+t                if (yydebug != null) yydebug.pop(yyStates[yyTop]);
+.              } while (-- yyTop >= 0);
+t              if (yydebug != null) yydebug.reject();
+.              throw new yyException("irrecoverable syntax error");
+.  
+.            case 3:
+.              if (yyToken == 0) {
+t                if (yydebug != null) yydebug.reject();
+.                throw new yyException("irrecoverable syntax error at end-of-file");
+.              }
+t              if (yydebug != null)
+t                yydebug.discard(yyState, yyToken, yyname(yyToken),
+t  							yyLex.value());
+.              yyToken = -1;
+.              continue yyDiscarded;		// leave stack alone
+.            }
+.        }
+.        int yyV = yyTop + 1-yyLen[yyN];
+t        if (yydebug != null)
+t          yydebug.reduce(yyState, yyStates[yyV-1], yyN, yyRule[yyN], yyLen[yyN]);
+.        yyVal = yyDefault(yyV > yyTop ? null : yyVals[yyV]);
+.        switch (yyN) {
+
+ actions		## code from the actions within the grammar
+
+.        }
+.        yyTop -= yyLen[yyN];
+.        yyState = yyStates[yyTop];
+.        int yyM = yyLhs[yyN];
+.        if (yyState == 0 && yyM == 0) {
+t          if (yydebug != null) yydebug.shift(0, yyFinal);
+.          yyState = yyFinal;
+.          if (yyToken < 0) {
+.            yyToken = yyLex.advance() ? yyLex.token() : 0;
+t            if (yydebug != null)
+t               yydebug.lex(yyState, yyToken,yyname(yyToken), yyLex.value());
+.          }
+.          if (yyToken == 0) {
+t            if (yydebug != null) yydebug.accept(yyVal);
+.            return yyVal;
+.          }
+.          continue yyLoop;
+.        }
+.        if ((yyN = yyGindex[yyM]) != 0 && (yyN += yyState) >= 0
+.            && yyN < yyTable.length && yyCheck[yyN] == yyState)
+.          yyState = yyTable[yyN];
+.        else
+.          yyState = yyDgoto[yyM];
+t        if (yydebug != null) yydebug.shift(yyStates[yyTop], yyState);
+.	 continue yyLoop;
+.      }
+.    }
+.  }
+.
+ tables			## tables for rules, default reduction, and action calls
+.
+ epilog			## text following second %%

+ 351 - 0
mcs/jay/skeleton.cs

@@ -0,0 +1,351 @@
+#	jay skeleton
+
+#	character in column 1 determines outcome...
+#		# is a comment
+#		. is copied
+#		t is copied as //t if -t is set
+#	other lines are interpreted to call jay procedures
+
+.// created by jay 0.7 (c) 1998 [email protected]
+.
+ prolog		## %{ ... %} prior to the first %%
+
+.
+.  /** simplified error message.
+.      @see <a href="#yyerror(java.lang.String, java.lang.String[])">yyerror</a>
+.    */
+.  public void yyerror (string message) {
+.    yyerror(message, null);
+.  }
+.
+.  /** (syntax) error message.
+.      Can be overwritten to control message format.
+.      @param message text to be displayed.
+.      @param expected vector of acceptable tokens, if available.
+.    */
+.  public void yyerror (string message, string[] expected) {
+.    if ((expected != null) && (expected.Length  > 0)) {
+.      System.Console.Write (message+", expecting");
+.      for (int n = 0; n < expected.Length; ++ n)
+.        System.Console.Write (" "+expected[n]);
+.        System.Console.WriteLine ();
+.    } else
+.      System.Console.WriteLine (message);
+.  }
+.
+.  /** debugging support, requires the package jay.yydebug.
+.      Set to null to suppress debugging messages.
+.    */
+t  protected yydebug.yyDebug yydebug;
+.
+ debug			## tables for debugging support
+.
+.  /** index-checked interface to yyName[].
+.      @param token single character or %token value.
+.      @return token name or [illegal] or [unknown].
+.    */
+t  public static string yyname (int token) {
+t    if ((token < 0) || (token > yyName.Length)) return "[illegal]";
+t    string name;
+t    if ((name = yyName[token]) != null) return name;
+t    return "[unknown]";
+t  }
+.
+.  /** computes list of expected tokens on error by tracing the tables.
+.      @param state for which to compute the list.
+.      @return list of token names.
+.    */
+.  protected string[] yyExpecting (int state) {
+.    int token, n, len = 0;
+.    bool[] ok = new bool[yyName.Length];
+.
+.    if ((n = yySindex[state]) != 0)
+.      for (token = n < 0 ? -n : 0;
+.           (token < yyName.Length) && (n+token < yyTable.Length); ++ token)
+.        if (yyCheck[n+token] == token && !ok[token] && yyName[token] != null) {
+.          ++ len;
+.          ok[token] = true;
+.        }
+.    if ((n = yyRindex[state]) != 0)
+.      for (token = n < 0 ? -n : 0;
+.           (token < yyName.Length) && (n+token < yyTable.Length); ++ token)
+.        if (yyCheck[n+token] == token && !ok[token] && yyName[token] != null) {
+.          ++ len;
+.          ok[token] = true;
+.        }
+.
+.    string [] result = new string[len];
+.    for (n = token = 0; n < len;  ++ token)
+.      if (ok[token]) result[n++] = yyName[token];
+.    return result;
+.  }
+.
+.  /** the generated parser, with debugging messages.
+.      Maintains a state and a value stack, currently with fixed maximum size.
+.      @param yyLex scanner.
+.      @param yydebug debug message writer implementing yyDebug, or null.
+.      @return result of the last reduction, if any.
+.      @throws yyException on irrecoverable parse error.
+.    */
+.  public Object yyparse (yyParser.yyInput yyLex, Object yydebug)
+.				 {
+t    this.yydebug = (yydebug.yyDebug)yydebug;
+.    return yyparse(yyLex);
+.  }
+.
+.  /** initial size and increment of the state/value stack [default 256].
+.      This is not final so that it can be overwritten outside of invocations
+.      of yyparse().
+.    */
+.  protected int yyMax;
+.
+.  /** executed at the beginning of a reduce action.
+.      Used as $$ = yyDefault($1), prior to the user-specified action, if any.
+.      Can be overwritten to provide deep copy, etc.
+.      @param first value for $1, or null.
+.      @return first.
+.    */
+.  protected Object yyDefault (Object first) {
+.    return first;
+.  }
+.
+.  /** the generated parser.
+.      Maintains a state and a value stack, currently with fixed maximum size.
+.      @param yyLex scanner.
+.      @return result of the last reduction, if any.
+.      @throws yyException on irrecoverable parse error.
+.    */
+.  public Object yyparse (yyParser.yyInput yyLex)
+.				{
+.    if (yyMax <= 0) yyMax = 256;			// initial size
+.    int yyState = 0;                                   // state stack ptr
+.    int [] yyStates = new int[yyMax];	                // state stack 
+.    Object yyVal = null;                               // value stack ptr
+.    Object [] yyVals = new Object[yyMax];	        // value stack
+.    int yyToken = -1;					// current input
+.    int yyErrorFlag = 0;				// #tks to shift
+.
+ local		## %{ ... %} after the first %%
+
+.    int yyTop = 0;
+.    goto skip;
+.    yyLoop:
+.    yyTop++;
+.    skip:
+.    for (;; ++ yyTop) {
+.      if (yyTop >= yyStates.Length) {			// dynamically increase
+.        int[] i = new int[yyStates.Length+yyMax];
+.        System.Array.Copy(yyStates, i, 0);
+.        yyStates = i;
+.        Object[] o = new Object[yyVals.Length+yyMax];
+.        System.Array.Copy(yyVals, o, 0);
+.        yyVals = o;
+.      }
+.      yyStates[yyTop] = yyState;
+.      yyVals[yyTop] = yyVal;
+t      if (yydebug != null) yydebug.push(yyState, yyVal);
+.
+.      yyDiscarded: for (;;) {	// discarding a token does not change stack
+.        int yyN;
+.        if ((yyN = yyDefRed[yyState]) == 0) {	// else [default] reduce (yyN)
+.          if (yyToken < 0) {
+.            yyToken = yyLex.advance() ? yyLex.token() : 0;
+t            if (yydebug != null)
+t              yydebug.lex(yyState, yyToken, yyname(yyToken), yyLex.value());
+.          }
+.          if ((yyN = yySindex[yyState]) != 0 && ((yyN += yyToken) >= 0)
+.              && (yyN < yyTable.Length) && (yyCheck[yyN] == yyToken)) {
+t            if (yydebug != null)
+t              yydebug.shift(yyState, yyTable[yyN], yyErrorFlag-1);
+.            yyState = yyTable[yyN];		// shift to yyN
+.            yyVal = yyLex.value();
+.            yyToken = -1;
+.            if (yyErrorFlag > 0) -- yyErrorFlag;
+.            goto yyLoop;
+.          }
+.          if ((yyN = yyRindex[yyState]) != 0 && (yyN += yyToken) >= 0
+.              && yyN < yyTable.Length && yyCheck[yyN] == yyToken)
+.            yyN = yyTable[yyN];			// reduce (yyN)
+.          else
+.            switch (yyErrorFlag) {
+.  
+.            case 0:
+.              yyerror("syntax error", yyExpecting(yyState));
+t              if (yydebug != null) yydebug.error("syntax error");
+.              goto case 1;
+.            case 1: case 2:
+.              yyErrorFlag = 3;
+.              do {
+.                if ((yyN = yySindex[yyStates[yyTop]]) != 0
+.                    && (yyN += Token.yyErrorCode) >= 0 && yyN < yyTable.Length
+.                    && yyCheck[yyN] == Token.yyErrorCode) {
+t                  if (yydebug != null)
+t                    yydebug.shift(yyStates[yyTop], yyTable[yyN], 3);
+.                  yyState = yyTable[yyN];
+.                  yyVal = yyLex.value();
+.                  goto yyLoop;
+.                }
+t                if (yydebug != null) yydebug.pop(yyStates[yyTop]);
+.              } while (-- yyTop >= 0);
+t              if (yydebug != null) yydebug.reject();
+.              throw new yyParser.yyException("irrecoverable syntax error");
+.  
+.            case 3:
+.              if (yyToken == 0) {
+t                if (yydebug != null) yydebug.reject();
+.                throw new yyParser.yyException("irrecoverable syntax error at end-of-file");
+.              }
+t              if (yydebug != null)
+t                yydebug.discard(yyState, yyToken, yyname(yyToken),
+t  							yyLex.value());
+.              yyToken = -1;
+.              goto yyDiscarded;		// leave stack alone
+.            }
+.        }
+.        int yyV = yyTop + 1-yyLen[yyN];
+t        if (yydebug != null)
+t          yydebug.reduce(yyState, yyStates[yyV-1], yyN, yyRule[yyN], yyLen[yyN]);
+.        yyVal = yyDefault(yyV > yyTop ? null : yyVals[yyV]);
+.        switch (yyN) {
+
+ actions		## code from the actions within the grammar
+
+.        }
+.        yyTop -= yyLen[yyN];
+.        yyState = yyStates[yyTop];
+.        int yyM = yyLhs[yyN];
+.        if (yyState == 0 && yyM == 0) {
+t          if (yydebug != null) yydebug.shift(0, yyFinal);
+.          yyState = yyFinal;
+.          if (yyToken < 0) {
+.            yyToken = yyLex.advance() ? yyLex.token() : 0;
+t            if (yydebug != null)
+t               yydebug.lex(yyState, yyToken,yyname(yyToken), yyLex.value());
+.          }
+.          if (yyToken == 0) {
+t            if (yydebug != null) yydebug.accept(yyVal);
+.            return yyVal;
+.          }
+.          goto yyLoop;
+.        }
+.        if (((yyN = yyGindex[yyM]) != 0) && ((yyN += yyState) >= 0)
+.            && (yyN < yyTable.Length) && (yyCheck[yyN] == yyState))
+.          yyState = yyTable[yyN];
+.        else
+.          yyState = yyDgoto[yyM];
+t        if (yydebug != null) yydebug.shift(yyStates[yyTop], yyState);
+.	 goto yyLoop;
+.      }
+.    }
+.  }
+.
+ tables			## tables for rules, default reduction, and action calls
+.
+ epilog			## text following second %%
+.namespace yydebug {
+.        using System;
+.	 public interface yyDebug {
+.		 void push (int state, Object value);
+.		 void lex (int state, int token, string name, Object value);
+.		 void shift (int from, int to, int errorFlag);
+.		 void pop (int state);
+.		 void discard (int state, int token, string name, Object value);
+.		 void reduce (int from, int to, int rule, string text, int len);
+.		 void shift (int from, int to);
+.		 void accept (Object value);
+.		 void error (string message);
+.		 void reject ();
+.	 }
+.	 
+.	 class yyDebugSimple : yyDebug {
+.		 void println (string s){
+.			 Console.WriteLine (s);
+.		 }
+.		 
+.		 public void push (int state, Object value) {
+.			 println ("push\tstate "+state+"\tvalue "+value);
+.		 }
+.		 
+.		 public void lex (int state, int token, string name, Object value) {
+.			 println("lex\tstate "+state+"\treading "+name+"\tvalue "+value);
+.		 }
+.		 
+.		 public void shift (int from, int to, int errorFlag) {
+.			 switch (errorFlag) {
+.			 default:				// normally
+.				 println("shift\tfrom state "+from+" to "+to);
+.				 break;
+.			 case 0: case 1: case 2:		// in error recovery
+.				 println("shift\tfrom state "+from+" to "+to
+.					     +"\t"+errorFlag+" left to recover");
+.				 break;
+.			 case 3:				// normally
+.				 println("shift\tfrom state "+from+" to "+to+"\ton error");
+.				 break;
+.			 }
+.		 }
+.		 
+.		 public void pop (int state) {
+.			 println("pop\tstate "+state+"\ton error");
+.		 }
+.		 
+.		 public void discard (int state, int token, string name, Object value) {
+.			 println("discard\tstate "+state+"\ttoken "+name+"\tvalue "+value);
+.		 }
+.		 
+.		 public void reduce (int from, int to, int rule, string text, int len) {
+.			 println("reduce\tstate "+from+"\tuncover "+to
+.				     +"\trule ("+rule+") "+text);
+.		 }
+.		 
+.		 public void shift (int from, int to) {
+.			 println("goto\tfrom state "+from+" to "+to);
+.		 }
+.		 
+.		 public void accept (Object value) {
+.			 println("accept\tvalue "+value);
+.		 }
+.		 
+.		 public void error (string message) {
+.			 println("error\t"+message);
+.		 }
+.		 
+.		 public void reject () {
+.			 println("reject");
+.		 }
+.		 
+.	 }
+.}
+.// %token constants
+. class Token {
+ tokens public const int
+. }
+. namespace yyParser {
+.  using System;
+.  /** thrown for irrecoverable syntax errors and stack overflow.
+.    */
+.  public class yyException : System.Exception {
+.    public yyException (string message) : base (message) {
+.    }
+.  }
+.
+.  /** must be implemented by a scanner object to supply input to the parser.
+.    */
+.  public interface yyInput {
+.    /** move on to next token.
+.        @return false if positioned beyond tokens.
+.        @throws IOException on input error.
+.      */
+.    bool advance (); // throws java.io.IOException;
+.    /** classifies current token.
+.        Should not be called if advance() returned false.
+.        @return current %token or single character.
+.      */
+.    int token ();
+.    /** associated with current token.
+.        Should not be called if advance() returned false.
+.        @return value for token().
+.      */
+.    Object value ();
+.  }
+. }

+ 158 - 0
mcs/jay/symtab.c

@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)symtab.c	5.3 (Berkeley) 6/1/90";
+#endif /* not lint */
+
+#include "defs.h"
+
+/* TABLE_SIZE is the number of entries in the symbol table. */
+/* TABLE_SIZE must be a power of two.			    */
+
+#define	TABLE_SIZE 1024
+
+
+bucket **symbol_table;
+bucket *first_symbol;
+bucket *last_symbol;
+
+
+int
+hash(name)
+char *name;
+{
+    register char *s;
+    register int c, k;
+
+    assert(name && *name);
+    s = name;
+    k = *s;
+    while (c = *++s)
+	k = (31*k + c) & (TABLE_SIZE - 1);
+
+    return (k);
+}
+
+
+bucket *
+make_bucket(name)
+char *name;
+{
+    register bucket *bp;
+
+    assert(name);
+    bp = (bucket *) MALLOC(sizeof(bucket));
+    if (bp == 0) no_space();
+    bp->link = 0;
+    bp->next = 0;
+    bp->name = MALLOC(strlen(name) + 1);
+    if (bp->name == 0) no_space();
+    bp->tag = 0;
+    bp->value = UNDEFINED;
+    bp->index = 0;
+    bp->prec = 0;
+    bp-> class = UNKNOWN;
+    bp->assoc = TOKEN;
+
+    if (bp->name == 0) no_space();
+    strcpy(bp->name, name);
+
+    return (bp);
+}
+
+
+bucket *
+lookup(name)
+char *name;
+{
+    register bucket *bp, **bpp;
+
+    bpp = symbol_table + hash(name);
+    bp = *bpp;
+
+    while (bp)
+    {
+	if (strcmp(name, bp->name) == 0) return (bp);
+	bpp = &bp->link;
+	bp = *bpp;
+    }
+
+    *bpp = bp = make_bucket(name);
+    last_symbol->next = bp;
+    last_symbol = bp;
+
+    return (bp);
+}
+
+
+create_symbol_table()
+{
+    register int i;
+    register bucket *bp;
+
+    symbol_table = (bucket **) MALLOC(TABLE_SIZE*sizeof(bucket *));
+    if (symbol_table == 0) no_space();
+    for (i = 0; i < TABLE_SIZE; i++)
+	symbol_table[i] = 0;
+
+    bp = make_bucket("error");
+    bp->index = 1;
+    bp->class = TERM;
+
+    first_symbol = bp;
+    last_symbol = bp;
+    symbol_table[hash("error")] = bp;
+}
+
+
+free_symbol_table()
+{
+    FREE(symbol_table);
+    symbol_table = 0;
+}
+
+
+free_symbols()
+{
+    register bucket *p, *q;
+
+    for (p = first_symbol; p; p = q)
+    {
+	q = p->next;
+	FREE(p);
+    }
+}

+ 366 - 0
mcs/jay/verbose.c

@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)verbose.c	5.3 (Berkeley) 1/20/91";
+#endif /* not lint */
+
+#include "defs.h"
+
+static short *null_rules;
+
+verbose()
+{
+    register int i;
+
+    if (!vflag) return;
+
+    null_rules = (short *) MALLOC(nrules*sizeof(short));
+    if (null_rules == 0) no_space();
+    fprintf(verbose_file, "\f\n");
+    for (i = 0; i < nstates; i++)
+	print_state(i);
+    FREE(null_rules);
+
+    if (nunused)
+	log_unused();
+    if (SRtotal || RRtotal)
+	log_conflicts();
+
+    fprintf(verbose_file, "\n\n%d terminals, %d nonterminals\n", ntokens,
+	    nvars);
+    fprintf(verbose_file, "%d grammar rules, %d states\n", nrules - 2, nstates);
+}
+
+
+log_unused()
+{
+    register int i;
+    register short *p;
+
+    fprintf(verbose_file, "\n\nRules never reduced:\n");
+    for (i = 3; i < nrules; ++i)
+    {
+	if (!rules_used[i])
+	{
+	    fprintf(verbose_file, "\t%s :", symbol_name[rlhs[i]]);
+	    for (p = ritem + rrhs[i]; *p >= 0; ++p)
+		fprintf(verbose_file, " %s", symbol_name[*p]);
+	    fprintf(verbose_file, "  (%d)\n", i - 2);
+	}
+    }
+}
+
+
+log_conflicts()
+{
+    register int i;
+
+    fprintf(verbose_file, "\n\n");
+    for (i = 0; i < nstates; i++)
+    {
+	if (SRconflicts[i] || RRconflicts[i])
+	{
+	    fprintf(verbose_file, "State %d contains ", i);
+	    if (SRconflicts[i] == 1)
+		fprintf(verbose_file, "1 shift/reduce conflict");
+	    else if (SRconflicts[i] > 1)
+		fprintf(verbose_file, "%d shift/reduce conflicts",
+			SRconflicts[i]);
+	    if (SRconflicts[i] && RRconflicts[i])
+		fprintf(verbose_file, ", ");
+	    if (RRconflicts[i] == 1)
+		fprintf(verbose_file, "1 reduce/reduce conflict");
+	    else if (RRconflicts[i] > 1)
+		fprintf(verbose_file, "%d reduce/reduce conflicts",
+			RRconflicts[i]);
+	    fprintf(verbose_file, ".\n");
+	}
+    }
+}
+
+
+print_state(state)
+int state;
+{
+    if (state)
+	fprintf(verbose_file, "\n\n");
+    if (SRconflicts[state] || RRconflicts[state])
+	print_conflicts(state);
+    fprintf(verbose_file, "state %d\n", state);
+    print_core(state);
+    print_nulls(state);
+    print_actions(state);
+}
+
+
+print_conflicts(state)
+int state;
+{
+    register int symbol, act, number;
+    register action *p;
+
+    symbol = -1;
+    for (p = parser[state]; p; p = p->next)
+    {
+	if (p->suppressed == 2)
+	    continue;
+
+	if (p->symbol != symbol)
+	{
+	    symbol = p->symbol;
+	    number = p->number;
+	    if (p->action_code == SHIFT)
+		act = SHIFT;
+	    else
+		act = REDUCE;
+	}
+	else if (p->suppressed == 1)
+	{
+	    if (state == final_state && symbol == 0)
+	    {
+		fprintf(verbose_file, "%d: shift/reduce conflict \
+(accept, reduce %d) on $end\n", state, p->number - 2);
+	    }
+	    else
+	    {
+		if (act == SHIFT)
+		{
+		    fprintf(verbose_file, "%d: shift/reduce conflict \
+(shift %d, reduce %d) on %s\n", state, number, p->number - 2,
+			    symbol_name[symbol]);
+		}
+		else
+		{
+		    fprintf(verbose_file, "%d: reduce/reduce conflict \
+(reduce %d, reduce %d) on %s\n", state, number - 2, p->number - 2,
+			    symbol_name[symbol]);
+		}
+	    }
+	}
+    }
+}
+
+
+print_core(state)
+int state;
+{
+    register int i;
+    register int k;
+    register int rule;
+    register core *statep;
+    register short *sp;
+    register short *sp1;
+
+    statep = state_table[state];
+    k = statep->nitems;
+
+    for (i = 0; i < k; i++)
+    {
+	sp1 = sp = ritem + statep->items[i];
+
+	while (*sp >= 0) ++sp;
+	rule = -(*sp);
+	fprintf(verbose_file, "\t%s : ", symbol_name[rlhs[rule]]);
+
+        for (sp = ritem + rrhs[rule]; sp < sp1; sp++)
+	    fprintf(verbose_file, "%s ", symbol_name[*sp]);
+
+	putc('.', verbose_file);
+
+	while (*sp >= 0)
+	{
+	    fprintf(verbose_file, " %s", symbol_name[*sp]);
+	    sp++;
+	}
+	fprintf(verbose_file, "  (%d)\n", -2 - *sp);
+    }
+}
+
+
+print_nulls(state)
+int state;
+{
+    register action *p;
+    register int i, j, k, nnulls;
+
+    nnulls = 0;
+    for (p = parser[state]; p; p = p->next)
+    {
+	if (p->action_code == REDUCE &&
+		(p->suppressed == 0 || p->suppressed == 1))
+	{
+	    i = p->number;
+	    if (rrhs[i] + 1 == rrhs[i+1])
+	    {
+		for (j = 0; j < nnulls && i > null_rules[j]; ++j)
+		    continue;
+
+		if (j == nnulls)
+		{
+		    ++nnulls;
+		    null_rules[j] = i;
+		}
+		else if (i != null_rules[j])
+		{
+		    ++nnulls;
+		    for (k = nnulls - 1; k > j; --k)
+			null_rules[k] = null_rules[k-1];
+		    null_rules[j] = i;
+		}
+	    }
+	}
+    }
+
+    for (i = 0; i < nnulls; ++i)
+    {
+	j = null_rules[i];
+	fprintf(verbose_file, "\t%s : .  (%d)\n", symbol_name[rlhs[j]],
+		j - 2);
+    }
+    fprintf(verbose_file, "\n");
+}
+
+
+print_actions(stateno)
+int stateno;
+{
+    register action *p;
+    register shifts *sp;
+    register int as;
+
+    if (stateno == final_state)
+	fprintf(verbose_file, "\t$end  accept\n");
+
+    p = parser[stateno];
+    if (p)
+    {
+	print_shifts(p);
+	print_reductions(p, defred[stateno]);
+    }
+
+    sp = shift_table[stateno];
+    if (sp && sp->nshifts > 0)
+    {
+	as = accessing_symbol[sp->shift[sp->nshifts - 1]];
+	if (ISVAR(as))
+	    print_gotos(stateno);
+    }
+}
+
+
+print_shifts(p)
+register action *p;
+{
+    register int count;
+    register action *q;
+
+    count = 0;
+    for (q = p; q; q = q->next)
+    {
+	if (q->suppressed < 2 && q->action_code == SHIFT)
+	    ++count;
+    }
+
+    if (count > 0)
+    {
+	for (; p; p = p->next)
+	{
+	    if (p->action_code == SHIFT && p->suppressed == 0)
+		fprintf(verbose_file, "\t%s  shift %d\n",
+			    symbol_name[p->symbol], p->number);
+	}
+    }
+}
+
+
+print_reductions(p, defred)
+register action *p;
+register int defred;
+{
+    register int k, anyreds;
+    register action *q;
+
+    anyreds = 0;
+    for (q = p; q ; q = q->next)
+    {
+	if (q->action_code == REDUCE && q->suppressed < 2)
+	{
+	    anyreds = 1;
+	    break;
+	}
+    }
+
+    if (anyreds == 0)
+	fprintf(verbose_file, "\t.  error\n");
+    else
+    {
+	for (; p; p = p->next)
+	{
+	    if (p->action_code == REDUCE && p->number != defred)
+	    {
+		k = p->number - 2;
+		if (p->suppressed == 0)
+		    fprintf(verbose_file, "\t%s  reduce %d\n",
+			    symbol_name[p->symbol], k);
+	    }
+	}
+
+        if (defred > 0)
+	    fprintf(verbose_file, "\t.  reduce %d\n", defred - 2);
+    }
+}
+
+
+print_gotos(stateno)
+int stateno;
+{
+    register int i, k;
+    register int as;
+    register short *to_state;
+    register shifts *sp;
+
+    putc('\n', verbose_file);
+    sp = shift_table[stateno];
+    to_state = sp->shift;
+    for (i = 0; i < sp->nshifts; ++i)
+    {
+	k = to_state[i];
+	as = accessing_symbol[k];
+	if (ISVAR(as))
+	    fprintf(verbose_file, "\t%s  goto %d\n", symbol_name[as], k);
+    }
+}

+ 122 - 0
mcs/jay/warshall.c

@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Robert Paul Corbett.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)warshall.c	5.4 (Berkeley) 5/24/93";
+#endif /* not lint */
+
+#include "defs.h"
+
+transitive_closure(R, n)
+unsigned *R;
+int n;
+{
+    register int rowsize;
+    register unsigned i;
+    register unsigned *rowj;
+    register unsigned *rp;
+    register unsigned *rend;
+    register unsigned *ccol;
+    register unsigned *relend;
+    register unsigned *cword;
+    register unsigned *rowi;
+
+    rowsize = WORDSIZE(n);
+    relend = R + n*rowsize;
+
+    cword = R;
+    i = 0;
+    rowi = R;
+    while (rowi < relend)
+    {
+	ccol = cword;
+	rowj = R;
+
+	while (rowj < relend)
+	{
+	    if (*ccol & (1 << i))
+	    {
+		rp = rowi;
+		rend = rowj + rowsize;
+		while (rowj < rend)
+		    *rowj++ |= *rp++;
+	    }
+	    else
+	    {
+		rowj += rowsize;
+	    }
+
+	    ccol += rowsize;
+	}
+
+	if (++i >= BITS_PER_WORD)
+	{
+	    i = 0;
+	    cword++;
+	}
+
+	rowi += rowsize;
+    }
+}
+
+reflexive_transitive_closure(R, n)
+unsigned *R;
+int n;
+{
+    register int rowsize;
+    register unsigned i;
+    register unsigned *rp;
+    register unsigned *relend;
+
+    transitive_closure(R, n);
+
+    rowsize = WORDSIZE(n);
+    relend = R + n*rowsize;
+
+    i = 0;
+    rp = R;
+    while (rp < relend)
+    {
+	*rp |= (1 << i);
+	if (++i >= BITS_PER_WORD)
+	{
+	    i = 0;
+	    rp++;
+	}
+
+	rp += rowsize;
+    }
+}

+ 3 - 0
mcs/mcs/.cvsignore

@@ -0,0 +1,3 @@
+compiler.pdb
+cs-parser.cs
+y.output

+ 7 - 5
mcs/mcs/makefile

@@ -1,3 +1,5 @@
+CSC=//c/winnt/microsoft.net/framework/v1.0.2914/csc.exe
+
 VERSION=0.13
 
 COMMON_SOURCES = cs-parser.cs cs-tokenizer.cs errors.cs tree.cs  
@@ -26,23 +28,23 @@ COMPILER_SOURCES = \
 TEST_TOKENIZER_SOURCES = test-token.cs $(COMMON_SOURCES)
 
 all:
-	-rm compiler.exe
-	csc /target:exe /r:System.dll /debug+ /debug:full /out:compiler.exe $(COMPILER_SOURCES)
+	-rm -f compiler.exe
+	$(CSC) /target:exe /r:System.dll /debug+ /debug:full /out:compiler.exe $(COMPILER_SOURCES)
 
 opt:
 	-rm compiler.exe
-	csc /optimize+ /target:exe /r:System.dll /debug+ /debug:full /out:compiler.exe $(COMPILER_SOURCES)
+	$(CSC) /optimize+ /target:exe /r:System.dll /debug+ /debug:full /out:compiler.exe $(COMPILER_SOURCES)
 
 old: test-tokenizer.exe
 test-tokenizer.exe: $(TEST_TOKENIZER_SOURCES)
-	csc /target:exe /out:test-tokenizer.exe $(TEST_TOKENIZER_SOURCES)
+	$(CSC) /target:exe /out:test-tokenizer.exe $(TEST_TOKENIZER_SOURCES)
 
 bison:
 	perl -pe 's/\015//' < cs-parser.jay > x.y
 	bison --debug --verbose x.y
 
 parser:
-	./jay -tv cs-parser.jay > cs-parser.cs
+	../jay/jay.$(OSTYPE) -ctv < ../jay/skeleton.cs cs-parser.jay > cs-parser.cs
 
 migparser:
 	jay -tv cs-parser.jay > cs-parser.cs