Xref for yacc
Cathy
cathy at comp.lancs.ac.uk
Thu Jul 10 08:52:08 AEST 1986
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 at ucl-cs | Post: University of Lancaster,
JANET: cathy at uk.ac.lancs.comp | Department of Computing,
Phone: +44 524 65201 ext ???? | Bailrigg, Lancaster, LA1 4YR, UK.
More information about the Comp.sources.unix
mailing list