[net.sources] Xref for yacc

cathy@comp.lancs.ac.uk (Cathy) (07/10/86)

	The following source forms the xref program for syntactically correct
Yacc files and runs on UN*X 4.2. All tokens and non-terminals in the grammar
are located, together with a list of the line numbers at which they occur. The
output is a numbered listing of the Yacc grammar upto the second '%%' or EOF,
followed by the xref table. Should a syntax error occur before normal termin-
ation, the grammar listing ends and as much of the table as has been constructed
is printed. All comments /* .. */ , %{ .. %} and actions { .. } are ignored,
although they appear in the listing.
	Table data is stored in "table[]", which holds MAXINTS terminal /
non-terminal names, each of length <= MAXCHARS. A total of MAXDEFS defining (rhs
of rule) occurances can be held, and a total of MAXOCCS lhs occurances. Each
identifier which may be the start token has the message held in "start_maybe[]"
printed - likewise all possible tokens are accompanied by "token_maybe[]". All
defining occurances are printed following "declared_at_mark[]", and all other
occurances following "occurs_at_mark[]".

	An example of the output is given below.

   1 :	%{
   2 :	# include <ctype.h>
   3 :	%}
   4 :	
   5 :	
   6 :		/*******************************************************\
   7 :		*							*
   8 :		*	Date : Fri Jul  4 00:50:04 BST 1986		*
   9 :		*							*
  10 :		\*******************************************************/
  11 :	
  12 :	%token	IDENTIFIER START_TOKEN NUMBER
  13 :	
  14 :	%start	small
  15 :	
  16 :	%%
  17 :	
  18 :	small
  19 :		:	start middle
  20 :				{
  21 :					printf("\n\nMiddle");
  22 :					yyclearin;
  23 :					return(0);
  24 :				}
  25 :			end postamble
  26 :		;
  27 :	
  28 :	start
  29 :		:	/* empty */
  30 :		|	START_TOKEN
  31 :		;
  32 :	
  33 :	middle
  34 :		:
  35 :		;
  36 :	
  37 :	middle
  38 :		:	MID_TOKEN
  39 :		|	/* empty */
  40 :		;
  41 :	
  42 :	%%


'small' -
~~~~~~~		*18 , never occurs on rhs of rule - start rule?
'start' -
~~~~~~~		*28 , 19
'middle' -
~~~~~~~		*33 , *37, 19
'end' -
~~~~~~~		is not declared - token??, 25
'postamble' -
~~~~~~~		is not declared - token??, 25
'START_TOKEN' -
~~~~~~~		is not declared - token??, 30
'MID_TOKEN' -
~~~~~~~		is not declared - token??, 38

	End of X-ref
	~~~~~~~~~~~~

	The text below should be stored in the file
	
	pack.out
	
and can be converted from the single file to the three files

	xref-grammar, xref-regular_expr, xref-line.h

by issuing the command

	sh pack.out

	Issue the commands

	lex xref-regular_expr
	yacc -vd xref-grammar
	cc y.tab.c -o xref

to produce an executable version and use as any UN*X command.


<---------------------------------- Cut here ---------------------------------->
#!/bin/sh
echo 'Start of pack.out, part 01 of 01:'
echo 'x - xref-grammar'
sed 's/^X//' > xref-grammar << '/'
X%{
X
X# include <ctype.h>
X# include <stdio.h>
X
X%}
X
X
X	/*******************************************************\
X	*							*
X	*	X_reference program for YACC files		*
X	*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~		*
X	*							*
X	*	Cathy Taylor,					*
X	*	c/o Department of Computing,			*
X	*	University of Lancaster,			*
X	*	Bailrigg, Lancaster, England.			*
X	*							*
X	*	Date : Fri Jul  4 00:50:04 BST 1986		*
X	*							*
X	\*******************************************************/
X
X
X	/***********************************************\
X	*						*
X	*	Yacc Input Syntax			*
X	*	~~~~~~~~~~~~~~~~~			*
X	*						*
X	*	Adapted from the document		*
X	*	'YACC - Yet Another Compiler Compiler'	*
X	*		by				*
X	*	   S. C. Johnson			*
X	*						*
X	*	Date: Tue Jul  1 02:40:18 BST 1986	*
X	*						*
X	\***********************************************/
X
X
X%token	IDENTIFIER CHARACTER NUMBER
X%token	LEFT RIGHT NONASSOC TOKEN PREC TYPE START UNION
X%token	PER PERCURL ACT
X%token	COLON SEMICOLON COMMA OR LESS GREATER
X
X%start	spec
X
X%%
X
Xspec
X	:	defs PER rules tail
X			{
X				printf("\n\n");
X				yyclearin;
X				return(0);
X			}
X	;
X
Xtail
X	:	/* empty */
X	|	PER 
X	;
X
Xdefs
X	:	/* empty */
X	|	def_bk
X	;
X
Xdef_bk
X	:	def
X	|	def_bk def
X	;
X
Xdef
X	:	START IDENTIFIER
X	|	UNION
X	|	PERCURL
X	|	rword tag nlist
X	;
X
Xrword
X	:	TOKEN
X	|	LEFT
X	|	RIGHT
X	|	NONASSOC
X	|	TYPE
X	;
X
Xtag
X	:	/* empty */
X	|	LESS IDENTIFIER GREATER
X	;
X
Xnlist
X	:	nmno
X	|	nlist opt_comma nmno
X	;
X
Xopt_comma
X	:	/* empty */
X	|	COMMA
X	;
X
Xnmno
X	:	IDENTIFIER opt_num
X	;
X
Xopt_num
X	:	/* empty */
X	|	NUMBER
X	;
Xrules
X	:	rule
X	|	rules rule
X	;
X
Xrule
X	:	IDENTIFIER
X		{
X			yyaction(ON_C_IDENT,line);
X		}
X		COLON body SEMICOLON
X	;
X
Xbody
X	:	body_block
X	|	body OR body_block
X	;
X
Xbody_block
X	:	/* empty */
X	|	body_block body_entity
X	;
X
Xbody_entity
X	:	opt_prec id_ent
X	|	ACT
X	;
X
Xid_ent
X	:	IDENTIFIER
X		{
X			yyaction(ON_IDENT,line);
X		}
X	|	CHARACTER
X	;
X
Xopt_prec
X	:	/* empty */
X	|	PREC
X	;
X
X
X%%
X
X# include	<stdio.h>
X# include	"lex.yy.c"
X# include	"xref-line.h"
X
X#define	ON_C_IDENT	000
X#define	ON_IDENT	001
X
X#define	MAXIDENTS	1000
X#define MAXCHARS	100
X#define	MAXDEFS		20
X#define	MAXOCCS		1000
X
Xstruct	IREC {
X		char	ident[MAXCHARS];
X		int	desc[MAXDEFS];
X		int	nextdesc;
X		int	occ[MAXOCCS];
X		int	nextocc;
X		} idents[MAXIDENTS];
X
X
Xyyaction (action,ln)
Xint	action;
Xint	ln;
X{
X	int	id;
X	
X	id = 0;
X	while (	strcmp(idents[id].ident,yytext) != 0 && strcmp(idents[id].ident,"") != 0 )
X		id++;
X
X	if ( strcmp(idents[id].ident, yytext) != 0 )
X	{
X
X	/*******************************************************\
X	*							*
X	*	New non-terminal to be stored.			*
X	*	No distinction is made here between tokens	*
X	*	and (non) terminals.				*
X	*							*
X	\*******************************************************/
X
X		strcpy(idents[id].ident,yytext);
X		idents[id].nextdesc = 0;
X		idents[id].nextocc = 0;
X	} /* fi */
X
X	switch (action) {
X	case ON_C_IDENT:
X
X	/*******************************************************\
X	*							*
X	*	Add to list of definition lines.		*
X	*							*
X	\*******************************************************/
X
X		idents[id].desc[idents[id].nextdesc++] = ln;
X		break;
X
X	case ON_IDENT:
X				
X	/*******************************************************\
X	*							*
X	*	Add to list of occurance lines.			*
X	*							*
X	\*******************************************************/
X
X		idents[id].occ[idents[id].nextocc++] = ln;
X		break;
X
X	default		:
X		fprintf (stdout, "yyaction: invalid action\n");
X		return (-1);
X		} /* hctiws */
X	return (0);
X} /* corp */
X
Xnline(ln)
Xint	ln;
X{
X	printf("%4d :\t",ln);
X}
X
X
X	char	declared_at_mark[] = "*";
X	char	occurs_at_mark[] = "";
X	char	token_maybe[] = "is not declared - token??";
X	char	start_maybe[] = "never occurs on rhs of rule - start rule?";
X	
X/*
X*	Strings for output
X*/
X
Xmain ()
X{
X	int	ind,id;
X
X	strcpy(idents[0].ident,"");
X
X	line = 0;
X	nline(++line);
X
X	yyparse ();
X
X	id = 0;
X	while( strcmp(idents[id].ident,"") != 0 )
X	{
X		printf("\n'%s' -\n~~~~~~~\t\t",idents[id].ident);
X		if (idents[id].nextdesc == 0 )
X		    printf("%s",token_maybe);
X		else
X		{
X		    ind = 0;
X		    printf("*%d ",idents[id].desc[ind++]);
X		    for ( ind=1; ind < idents[id].nextdesc ; ind++)
X			printf(", %s%d",declared_at_mark,idents[id].desc[ind]);
X		}
X		if (idents[id].occ[0] == 0)
X		    printf(", %s",start_maybe);
X		else
X		{
X		    for ( ind = 0; ind < idents[id].nextocc ; ind++ )
X			printf(", %s%d",occurs_at_mark,idents[id].occ[ind]);
X		}
X		id++;
X	}
X	printf("\n\n\tEnd of X-ref\n\t~~~~~~~~~~~~\n");
X} /* niam */
X
Xyyerror(mess)
Xchar	*mess;
X{
X	printf("\n\t%s\n",mess);
X} /* corp */
/
echo 'x - xref-regular_expr'
sed 's/^X//' > xref-regular_expr << '/'
X
X	/*******************************************************\
X	*							*
X	*	X_ref for YACC - LEX file			*
X	*	~~~~~~~~~~~~~~~~~~~~~~~~~			*
X	*							*
X	*	Date: Tue Jul  1 03:36:21 BST 1986		*
X	*							*
X	*	Cathy Taylor,					*
X	*	c/o Department of Computing,			*
X	*	University of Lancaster,			*
X	*	Bailrigg, Lancaster, England.			*
X	*							*
X	\*******************************************************/
X
X%{
X
X# include	<stdio.h>
X# include	"xref-line.h"
X
X#define		TRUE 1
X#define 	FALSE 0
X
Xint	recognised;
Xchar	c;
X
X%}
X
X	/* abbreviations */
X
Xdigit		[0-9]
Xu_case		[A-Z]
Xl_case		[a-z]
Xid_char		[A-Za-z0-9_]
Xletter		[A-Za-z]
Xwhite		[\t ]
X
X
X%%
X
X"/*"			{
X				ECHO;
X				recognised = FALSE;
X				c = nextchar();
X				while (recognised == FALSE)
X				{
X					while (c != '*')
X						c = nextchar();
X					c = nextchar();
X					if (c == '\/')
X						recognised = TRUE;
X				}
X			}
X"%{"			{
X				ECHO;
X				recognised = FALSE;
X				c = nextchar();
X				while (recognised == FALSE)
X				{
X					while (c != '\%')
X						c = nextchar();
X					c = nextchar();
X					if (c == '\}')
X						recognised = TRUE;
X				}
X				return(PERCURL);
X			}
X"{"			{
X
X/*
X*	Although LEX can cope with the full definition,
X*	( "{"[^\}]*"}" ) this may overrun the lex buffer (200 chars).
X*	Thus this routine.
X*/
X
X				ECHO;
X				c = nextchar();
X				while (c != '\}')
X					c = nextchar();
X				return(ACT);
X			}
X{letter}{id_char}*	{
X				ECHO;
X				return(IDENTIFIER);
X			}
X"'"\\?[^']+"'"		{
X				ECHO;
X				return(CHARACTER);
X			}
X{white}+		{	
X				ECHO;
X			}
X{digit}+		{
X				ECHO;
X				return(NUMBER);
X			}
X"%"{white}*"left"	{
X				ECHO;
X				return(LEFT);
X			}
X"%"{white}*"right"	{
X				ECHO;
X				return(RIGHT);
X			}
X"%"{white}*"nonassoc"	{
X				ECHO;
X				return(NONASSOC);
X			}
X"%"{white}*"token"	{
X				ECHO;
X				return(TOKEN);
X			}
X"%"{white}*"prec"	{
X				ECHO;
X				return(PREC);
X			}
X"%"{white}*"type"	{
X				ECHO;
X				return(TYPE);
X			}
X"%"{white}*"start"	{
X				ECHO;
X				return(START);
X			}
X"%"{white}*"union"	{
X				ECHO;
X				return(UNION);
X			}
X"%%"			{
X				ECHO;
X				return(PER);
X			}
X":"			{
X				ECHO;
X				return(COLON);
X			}
X";"			{
X				ECHO;
X				return(SEMICOLON);
X			}
X","			{
X				ECHO;
X				return(COMMA);
X			}
X"|"			{
X				ECHO;
X				return(OR);
X			}
X"<"			{
X				ECHO;
X				return(LESS);
X			}
X">"			{
X				ECHO;
X				return(GREATER);
X			}
X"\n"			{
X				ECHO;
X				nline(++line);
X			}
X
X%%
X
Xyywrap()
X{
X	/* wrap-up procedure */
X	return(1);
X}
X
Xnextchar()
X{
X	char	c;
X	
X	c = input();
X	printf("%c",c);
X	if (c == '\n')
X		nline(++line);
X	return(c);
X}
/
echo 'x - xref-line.h'
sed 's/^X//' > xref-line.h << '/'
X
X	int	line;
/
echo 'Part 01 of pack.out complete.'
exit
<---------------------------------- Cut here ---------------------------------->


-- 

	 - Marxist unite!
	 - Comrades unite!
	 - Bad-spellers of the world untie!
  
UUCP:  ...!seismo!mcvax!ukc!dcl-cs!cathy
DARPA: cathy%lancs.comp@ucl-cs	| Post: University of Lancaster,
JANET: cathy@uk.ac.lancs.comp	|	Department of Computing,
Phone: +44 524 65201 ext ????	|	Bailrigg, Lancaster, LA1 4YR, UK.

cathy@dcl-cs.UUCP (07/14/86)

	( Apologies for sending the wrong version here and to mod.sources a
	few days ago. Correct version is listed below. All flames to above
	address. )

	The following source forms the xref program for syntactically correct
Yacc files and runs on UN*X 4.2. All tokens and non-terminals in the grammar
are located, together with a list of the line numbers at which they occur. The
output is a numbered listing of the Yacc grammar upto the second '%%' or EOF,
followed by an alphabetical listing of the xref table.
	Should a syntax error occur before normal termination, the grammar
listing ends and as much of the table as has been constructed is printed. All
comments /* .. */ , %{ .. %} and actions { .. } are ignored, although they
appear in the listing. Overflow in any field of the data structure holding the
table information is reported as it occurs and execution terminates without
printing any xref information.
	Table data is stored in "table[]", which holds MAXINTS terminal/non-
terminal names, each of length <= MAXCHARS. A total of MAXDEFS defining (rhs of
rule) occurances can be held, and a total of MAXOCCS lhs occurances. Each ident-
ifier which may be the start token has the message held in "start_maybe[]"
printed - likewise all possible tokens are accompanied by "token_maybe[]". All
defining occurances are printed following "declared_at_mark[]", and all
other occurances following "occurs_at_mark[]".
	An example of the output is given below.

   1 :	%{
   2 :	
   3 :	
   4 :	%}
   5 :	
   6 :		/*******************************************************\
   7 :		*							*
   8 :		*	Trivial Yacc grammar.				*
   9 :		*	~~~~~~~~~~~~~~~~~~~~~				*
  10 :		*							*
  11 :		\*******************************************************/
  12 :	
  13 :	%token	IDENTIFIER CHARACTER NUMBER
  14 :	
  15 :	%start	start
  16 :	
  17 :	%%
  18 :	
  19 :	start
  20 :		:	begin middle end
  21 :		;
  22 :	
  23 :	begin
  24 :		:	BEGIN
  25 :		;
  26 :	
  27 :	middle
  28 :		:
  29 :		;
  30 :	
  31 :	begin
  32 :		:
  33 :		|	ALT_BEGIN
  34 :		;
  35 :	
  36 :	


' ALT_BEGIN ' -
			is not declared - token?? 1 occurances at lines , 33
' BEGIN ' -
			is not declared - token?? 1 occurances at lines , 24
' begin ' -
			*23 , *31 1 occurances at lines , 20
' end ' -
			is not declared - token?? 1 occurances at lines , 20
' middle ' -
			*27  1 occurances at lines , 20
' start ' -
			*19 , never occurs on rhs of rule - start rule?

	End of X-ref
	~~~~~~~~~~~~

	The text below should be stored in the file
	
	pack.out
	
and can be converted from the single file to the three files

	xref-grammar
	xref-regular_expr
	xref-line.h

by issuing the command

	sh pack.out

	Issue the commands

	lex xref-regular_expr
	yacc -vd xref-grammar
	cc y.tab.c -o xref

to produce an executable version and use as any UN*X command.


<---------------------------------- Cut here ---------------------------------->
#!/bin/sh
echo 'Start of pack.out, part 01 of 01:'
echo 'x - xref-grammar'
sed 's/^X//' > xref-grammar << '/'
X%{
X
X# include <ctype.h>
X# include <stdio.h>
X
X
X	/***************************************************************\
X	*								*
X	*	Error messages.						*
X	*								*
X	\***************************************************************/
X
Xchar	*charroom = " MAXCHARS TOO SMALL - no room to store ";
Xchar	*occroom  = " MAXOCCS TOO SMALL - no room to store occurance of ";
Xchar	*defroom  = " MAXDEFS TOO SMALL - no room to store definition of ";
Xchar	*idroom   = " MAXIDENTS TOO SMALL - no space in table for new identifier ";
X
X%}
X
X
X	/*******************************************************\
X	*							*
X	*	X_reference program for YACC files		*
X	*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~		*
X	*							*
X	*	Cathy Taylor,					*
X	*	c/o Department of Computing,			*
X	*	University of Lancaster,			*
X	*	Bailrigg, Lancaster, England.			*
X	*							*
X	*	Date : Mon Jul 14 01:24:34 BST 1986		*
X	*							*
X	\*******************************************************/
X
X
X	/***********************************************\
X	*						*
X	*	Yacc Input Syntax			*
X	*	~~~~~~~~~~~~~~~~~			*
X	*						*
X	*	Adapted from the document		*
X	*	'YACC - Yet Another Compiler Compiler'	*
X	*		by				*
X	*	   S. C. Johnson			*
X	*						*
X	*	Date: Tue Jul  1 02:40:18 BST 1986	*
X	*						*
X	\***********************************************/
X
X
X%token	IDENTIFIER CHARACTER NUMBER
X%token	LEFT RIGHT NONASSOC TOKEN PREC TYPE START UNION
X%token	PER PERCURL ACT
X%token	COLON SEMICOLON COMMA OR LESS GREATER
X
X%start	spec
X
X%%
X
Xspec
X	:	defs PER rules tail
X			{
X				printf("\n\n");
X				yyclearin;
X				return(0);
X			}
X	;
X
Xtail
X	:	/* empty */
X	|	PER 
X	;
X
Xdefs
X	:	/* empty */
X	|	def_bk
X	;
X
Xdef_bk
X	:	def
X	|	def_bk def
X	;
X
Xdef
X	:	START IDENTIFIER
X	|	UNION
X	|	PERCURL
X	|	rword tag nlist
X	;
X
Xrword
X	:	TOKEN
X	|	LEFT
X	|	RIGHT
X	|	NONASSOC
X	|	TYPE
X	;
X
Xtag
X	:	/* empty */
X	|	LESS IDENTIFIER GREATER
X	;
X
Xnlist
X	:	nmno
X	|	nlist opt_comma nmno
X	;
X
Xopt_comma
X	:	/* empty */
X	|	COMMA
X	;
X
Xnmno
X	:	IDENTIFIER opt_num
X	;
X
Xopt_num
X	:	/* empty */
X	|	NUMBER
X	;
Xrules
X	:	rule
X	|	rules rule
X	;
X
Xrule
X	:	IDENTIFIER
X		{
X			yyaction(ON_C_IDENT,line);
X		}
X		COLON body SEMICOLON
X	;
X
Xbody
X	:	body_block
X	|	body OR body_block
X	;
X
Xbody_block
X	:	/* empty */
X	|	body_block body_entity
X	;
X
Xbody_entity
X	:	opt_prec id_ent
X	|	ACT
X	;
X
Xid_ent
X	:	IDENTIFIER
X		{
X			yyaction(ON_IDENT,line);
X		}
X	|	CHARACTER
X	;
X
Xopt_prec
X	:	/* empty */
X	|	PREC
X	;
X
X
X%%
X
X# include	<stdio.h>
X# include	"lex.yy.c"
X# include	"sto.h"
X
X#define	ON_C_IDENT	000
X#define	ON_IDENT	001
X
X#define	MAXIDENTS	200
X#define	MAXCHARS	50
X#define	MAXDEFS		5
X#define	MAXOCCS		80
X
Xstruct	IREC {
X		char	symbol[MAXCHARS];
X		int	description[MAXDEFS];
X		int	next_d;
X		int	occurance[MAXOCCS];
X		int	next_o;
X		} table[MAXIDENTS];
X
X
Xyyaction (action,ln)
Xint	action;
Xint	ln;
X{
X	int	id;
X	
X	id = 0;
X	while (	strcmp(table[id].symbol,yytext) != 0 && strcmp(table[id].symbol,"") != 0 )
X	{
X		if (id== MAXIDENTS)
X		{
X			yyerror(strcat(idroom,yytext),ln);
X			exit(3);
X		}
X		id++;
X	}
X
X	if ( strcmp(table[id].symbol, yytext) != 0 )
X	{
X
X	/*******************************************************\
X	*							*
X	*	New non-terminal to be stored.			*
X	*	No distinction is made here between tokens	*
X	*	and (non) terminals.				*
X	*							*
X	\*******************************************************/
X
X		if (strlen(yytext) == MAXCHARS)
X		{
X			yyerror(strcat(charroom,yytext),ln);
X			exit(3);
X		} /* fi */
X		strcpy(table[id].symbol,yytext);
X		table[id].next_d = 0;
X		table[id].next_o = 0;
X	} /* fi */
X
X	switch (action) {
X	case ON_C_IDENT:
X
X	/*******************************************************\
X	*							*
X	*	Add to list of definition lines.		*
X	*							*
X	\*******************************************************/
X
X		if (table[id].next_d == MAXDEFS )
X		{
X			yyerror(strcat(defroom,yytext),ln);
X			exit(3);
X		} /* fi */
X		table[id].description[table[id].next_d++] = ln;
X		break;
X
X
X	case ON_IDENT:
X				
X	/*******************************************************\
X	*							*
X	*	Add to list of occurance lines.			*
X	*							*
X	\*******************************************************/
X		if (table[id].next_o == MAXOCCS )
X		{
X			yyerror(strcat(occroom,yytext),ln);
X			exit(3);
X		} /* fi */
X		table[id].occurance[table[id].next_o++] = ln;
X		break;
X
X	default		:
X		fprintf (stdout, "yyaction: invalid action\n");
X		return (-1);
X		} /* hctiws */
X	return (0);
X} /* corp */
X
Xnline(ln)
Xint	ln;
X{
X	printf("%4d :\t",ln);
X}
X
X
X	char	declared_at_mark[] = "*";
X	char	occurs_at_mark[] = "";
X	char	token_maybe[] = "is not declared - token??";
X	char	start_maybe[] = "never occurs on rhs of rule - start rule?";
X	
X/*
X*	Strings for output
X*/
X
Xmain ()
X{
X	int	ind,id,numids;
X	int	i, j, gap, temp;
X	int	pos[MAXIDENTS];
X
X	strcpy(table[0].symbol,"");
X
X	line = 0;
X	nline(++line);
X
X	yyparse ();
X
X	id = 0;
X	while ( strcmp(table[id].symbol,"") != 0 )
X		pos[id] = id++;
X	
X
X	/***************************************************************\
X	*								*
X	*	Grubby sort. Pointers to records held in "pos[]".	*
X	*								*
X	\***************************************************************/
X
X	numids = id;
X	for (gap = numids/2; gap > 0; gap /= 2)
X		for (i=gap; i<numids; i++)
X			for (j=i-gap; j>=0; j-=gap)
X				if (strcmp(table[pos[j]].symbol,table[pos[j+gap]].symbol) > 0)
X				{
X					temp = pos[j];
X					pos[j] = pos[j+gap];
X					pos[j+gap] = temp;
X				}
X	
X
X	for ( i=0; i<numids; i++ )
X	{
X		id = pos[i];
X		printf("\n' %s ' -\n\t\t\t",table[id].symbol);
X		if (table[id].next_d == 0 )
X		    printf("%s",token_maybe);
X		else
X		{
X		    ind = 0;
X		    printf("%s%d ",declared_at_mark,table[id].description[ind++]);
X		    for ( ind=1; ind < table[id].next_d ; ind++)
X			printf(", %s%d",declared_at_mark,table[id].description[ind]);
X		}
X		if (table[id].occurance[0] == 0)
X		    printf(", %s",start_maybe);
X		else
X		{
X		    printf(" %d occurances at lines ",table[id].next_o);
X		    for ( ind = 0; ind < table[id].next_o ; ind++ )
X			printf(", %s%d",occurs_at_mark,table[id].occurance[ind]);
X		}
X		id++;
X	}
X	printf("\n\n\tEnd of X-ref\n\t~~~~~~~~~~~~\n");
X} /* niam */
X
Xyyerror(mess,errline)
Xchar	*mess;
X{
X	printf("\n\n\n\t%s at line %d\n",mess,errline);
X} /* corp */
/
echo 'x - xref-regular_expr'
sed 's/^X//' > xref-regular_expr << '/'
X
X	/*******************************************************\
X	*							*
X	*	X_ref for YACC - LEX file			*
X	*	~~~~~~~~~~~~~~~~~~~~~~~~~			*
X	*							*
X	*	Date: Tue Jul  1 03:36:21 BST 1986		*
X	*							*
X	\*******************************************************/
X
X%{
X
X# include	<stdio.h>
X# include	"sto.h"
X
X#define		TRUE 1
X#define 	FALSE 0
X
Xint	recognised;
Xchar	c;
X
X%}
X
X	/* abbreviations */
X
Xdigit		[0-9]
Xu_case		[A-Z]
Xl_case		[a-z]
Xid_char		[A-Za-z0-9_]
Xletter		[A-Za-z]
Xwhite		[\t ]
X
X
X%%
X
X"/*"			{
X				ECHO;
X				recognised = FALSE;
X				c = nextchar();
X				while (recognised == FALSE)
X				{
X					while (c != '*')
X						c = nextchar();
X					c = nextchar();
X					if (c == '\/')
X						recognised = TRUE;
X				}
X			}
X"%{"			{
X				ECHO;
X				recognised = FALSE;
X				c = nextchar();
X				while (recognised == FALSE)
X				{
X					while (c != '\%')
X						c = nextchar();
X					c = nextchar();
X					if (c == '\}')
X						recognised = TRUE;
X				}
X				return(PERCURL);
X			}
X"{"			{
X
X/*
X*	Although LEX can cope with the full definition,
X*	( "{"[^\}]*"}" ) this may overrun the lex buffer (200 chars).
X*	Thus this routine.
X*/
X
X				ECHO;
X				c = nextchar();
X				while (c != '\}')
X					c = nextchar();
X				return(ACT);
X			}
X{letter}{id_char}*	{
X				ECHO;
X				return(IDENTIFIER);
X			}
X"'"\\?[^']+"'"		{
X				ECHO;
X				return(CHARACTER);
X			}
X{white}+		{	
X				ECHO;
X			}
X{digit}+		{
X				ECHO;
X				return(NUMBER);
X			}
X"%"{white}*"left"	{
X				ECHO;
X				return(LEFT);
X			}
X"%"{white}*"right"	{
X				ECHO;
X				return(RIGHT);
X			}
X"%"{white}*"nonassoc"	{
X				ECHO;
X				return(NONASSOC);
X			}
X"%"{white}*"token"	{
X				ECHO;
X				return(TOKEN);
X			}
X"%"{white}*"prec"	{
X				ECHO;
X				return(PREC);
X			}
X"%"{white}*"type"	{
X				ECHO;
X				return(TYPE);
X			}
X"%"{white}*"start"	{
X				ECHO;
X				return(START);
X			}
X"%"{white}*"union"	{
X				ECHO;
X				return(UNION);
X			}
X"%%"			{
X				ECHO;
X				return(PER);
X			}
X":"			{
X				ECHO;
X				return(COLON);
X			}
X";"			{
X				ECHO;
X				return(SEMICOLON);
X			}
X","			{
X				ECHO;
X				return(COMMA);
X			}
X"|"			{
X				ECHO;
X				return(OR);
X			}
X"<"			{
X				ECHO;
X				return(LESS);
X			}
X">"			{
X				ECHO;
X				return(GREATER);
X			}
X"\n"			{
X				ECHO;
X				nline(++line);
X			}
X
X%%
X
Xyywrap()
X{
X	/* wrap-up procedure */
X	return(1);
X}
X
Xnextchar()
X{
X	char	c;
X	
X	c = input();
X	printf("%c",c);
X	if (c == '\n')
X		nline(++line);
X	return(c);
X}
/
echo 'x - xref-line.h'
sed 's/^X//' > xref-line.h << '/'
X
X	int	line;
/
echo 'Part 01 of pack.out complete.'
exit
<---------------------------------- Cut here ---------------------------------->
-- 

	 - Marxist unite!
	 - Comrades unite!
	 - Bad-spellers of the world untie!
  
UUCP:  ...!seismo!mcvax!ukc!dcl-cs!cathy
DARPA: cathy%lancs.comp@ucl-cs	| Post: University of Lancaster,
JANET: cathy@uk.ac.lancs.comp	|	Department of Computing,
Phone: +44 524 65201 ext ????	|	Bailrigg, Lancaster, LA1 4YR, UK.