home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
p
/
pccts.zip
/
antlr
/
bits.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-08
|
9KB
|
339 lines
/*
* bits.c -- manage creation and output of bit sets used by the parser.
*
* SOFTWARE RIGHTS
*
* We reserve no LEGAL rights to the Purdue Compiler Construction Tool
* Set (PCCTS) -- PCCTS is in the public domain. An individual or
* company may do whatever they wish with source code distributed with
* PCCTS or the code generated by PCCTS, including the incorporation of
* PCCTS, or its output, into commerical software.
*
* We encourage users to develop software with PCCTS. However, we do ask
* that credit is given to us for developing PCCTS. By "credit",
* we mean that if you incorporate our source code into one of your
* programs (commercial product, research project, or otherwise) that you
* acknowledge this fact somewhere in the documentation, research report,
* etc... If you like PCCTS and have developed a nice tool with the
* output, please mention that you developed it using PCCTS. In
* addition, we ask that this header remain intact in our source code.
* As long as these guidelines are kept, we expect to continue enhancing
* this system and expect to make other tools available as they are
* completed.
*
* ANTLR 1.06
* Terence Parr
* Purdue University
* 1989-1992
*/
#include <stdio.h>
#include <ctype.h>
#include "set.h"
#include "syn.h"
#include "hash.h"
#include "generic.h"
#include "dlgdef.h"
#define BitsPerByte 8
#define BitsPerWord BitsPerByte*sizeof(unsigned)
static unsigned *setwd = NULL;
int setnum = -1;
int wordnum = 0;
int esetnum = 0;
/* Create a new setwd (ignoring [Ep] token on end) */
void
NewSetWd()
{
unsigned *p;
if ( setwd == NULL )
{
setwd = (unsigned *) calloc(TokenNum, sizeof(unsigned));
require(setwd!=NULL, "NewSetWd: cannot alloc set wd\n");
}
for (p = setwd; p<&(setwd[TokenNum]); p++) {*p=0;}
wordnum++;
}
/* Dump the current setwd to ErrFile. 0..MaxTokenVal */
void
DumpSetWd()
{
int i,c=1;
if ( setwd==NULL ) return;
fprintf(DefFile, "extern unsigned setwd%d[];\n", wordnum);
fprintf(ErrFile, "unsigned setwd%d[%d] = {", wordnum, TokenNum-1);
for (i=0; i<TokenNum-1; i++)
{
if ( i!=0 ) fprintf(ErrFile, ",");
if ( c == 8 ) {fprintf(ErrFile, "\n\t"); c=1;} else c++;
fprintf(ErrFile, "0x%x", setwd[i]);
}
fprintf(ErrFile, "};\n");
}
/* Make a new set. Dump old setwd and create new setwd if current setwd is full */
void
NewSet()
{
setnum++;
if ( setnum==BitsPerWord ) /* is current setwd full? */
{
DumpSetWd(); NewSetWd(); setnum = 0;
}
}
/* s is a set of tokens. Turn on bit at each token position in set 'setnum' */
void
FillSet(s)
set s;
{
unsigned mask=(1<<setnum);
int e;
while ( !set_nil(s) )
{
e = set_int(s);
set_rm(e, s);
setwd[e] |= mask;
}
}
/* E r r o r C l a s s S t u f f */
/* compute the FIRST of a rule for the error class stuff */
static set
Efirst(rule, eclass)
char *rule;
ECnode *eclass;
{
set rk, a;
Junction *r;
RuleEntry *q = (RuleEntry *) hash_get(Rname, rule);
if ( q == NULL )
{
warnNoFL(eMsg2("undefined rule '%s' referenced in errclass '%s'; ignored",
rule, TokenStr[eclass->tok]));
return empty;
}
r = RulePtr[q->rulenum];
r->end->halt = TRUE; /* don't let reach fall off end of rule here */
rk = empty;
REACH(r, 1, &rk, a);
r->end->halt = FALSE;
return a;
}
/*
* scan the list of tokens/eclasses/nonterminals filling the new eclass
* with the set described by the list. Note that an eclass can be
* quoted to allow spaces etc... However, an eclass must not conflict
* with a reg expr found elsewhere. The reg expr will be taken over
* the eclass name.
*/
static void
doEclass(eclass)
char *eclass; /* pointer to Error Class */
{
TermEntry *q;
ECnode *p;
ListNode *e;
int t, deg=0;
set a;
require(eclass!=NULL, "doEclass: NULL eset");
p = (ECnode *) eclass;
lexmode(p->lexclass); /* switch to lexclass where errclass is defined */
p->eset = empty;
for (e = (p->elist)->next; e!=NULL; e=e->next)
{
if ( islower( *(e->elem) ) ) /* is it a rule ref? (alias FIRST request) */
{
a = Efirst(e->elem, p);
set_orin(&p->eset, a);
deg += set_deg(a);
set_free( a );
continue;
}
else if ( *(e->elem)=='"' )
{
t = 0;
q = (TermEntry *) hash_get(Texpr, e->elem);
if ( q == NULL )
{
/* if quoted and not an expr look for eclass name */
q = (TermEntry *) hash_get(Tname, e->elem=StripQuotes(e->elem));
if ( q != NULL ) t = q->token;
}
else t = q->token;
}
else /* labelled token/eclass */
{
q = (TermEntry *) hash_get(Tname, e->elem);
if ( q != NULL ) t = q->token; else t=0;
}
if ( t!=0 )
{
set_orel(t, &p->eset);
deg++;
}
else warnNoFL(eMsg2("undefined token '%s' referenced in errclass '%s'; ignored",
e->elem, TokenStr[p->tok]));
}
p->setdeg = deg;
}
void
ComputeErrorSets()
{
list_apply(eclasses, doEclass);
}
/* replace a subset of an error set with an error class name if a subset is found
* repeat process until no replacements made
*/
void
SubstErrorClass(f)
set *f;
{
int max, done = 0;
ListNode *p;
ECnode *ec, *maxclass = NULL;
set a;
require(f!=NULL, "SubstErrorClass: NULL eset");
if ( eclasses == NULL ) return;
while ( !done )
{
max = 0;
maxclass = NULL;
for (p=eclasses->next; p!=NULL; p=p->next) /* chk all error classes */
{
ec = (ECnode *) p->elem;
if ( ec->setdeg > max )
{
if ( set_sub(ec->eset, *f) || set_equ(ec->eset, *f) )
{maxclass = ec; max=ec->setdeg;}
}
}
if ( maxclass != NULL ) /* if subset found, replace with token */
{
a = set_dif(*f, maxclass->eset);
set_orel(maxclass->tok, &a);
set_free(*f);
*f = a;
}
else done = 1;
}
}
/* Define a new error set. WARNING...set-implementation dependent */
int
DefErrSet(f)
set *f;
{
unsigned *p, *endp;
int e=1;
require(!set_nil(*f), "DefErrSet: nil set to dump?");
SubstErrorClass(f);
p = f->setword;
endp = &(f->setword[NumWords(TokenNum-1)]);
esetnum++;
fprintf(DefFile, "extern unsigned zzerr%d[];\n", esetnum);
fprintf(ErrFile, "unsigned zzerr%d[%d] = {", esetnum, NumWords(TokenNum-1));
while ( p < endp )
{
if ( e > 1 ) fprintf(ErrFile, ", ");
fprintf(ErrFile, "0x%x", *p++);
if ( e == 7 )
{
if ( p < endp ) fprintf(ErrFile, ",");
fprintf(ErrFile, "\n\t");
e=1;
}
else e++;
}
fprintf(ErrFile, "};\n");
return esetnum;
}
void
GenErrHdr()
{
int i, j;
fprintf(ErrFile, "/*\n");
fprintf(ErrFile, " * A n t l r S e t s / E r r o r F i l e H e a d e r\n");
fprintf(ErrFile, " *\n");
fprintf(ErrFile, " * Generated from:");
for (i=0; i<NumFiles; i++) fprintf(ErrFile, " %s", FileStr[i]);
fprintf(ErrFile, "\n");
fprintf(ErrFile, " *\n");
fprintf(ErrFile, " * Terence Parr, Hank Dietz and Will Cohen: 1989-1992\n");
fprintf(ErrFile, " * Purdue University Electrical Engineering\n");
fprintf(ErrFile, " * ANTLR Version %s\n", Version);
fprintf(ErrFile, " */\n\n");
fprintf(ErrFile, "#include <stdio.h>\n");
if ( HdrAction != NULL ) dumpAction( HdrAction, ErrFile, 0, -1, 0, 1 );
if ( LL_k > 1 ) fprintf(ErrFile, "#define LL_K %d\n", OutputLL_k);
fprintf(ErrFile, "#define zzEOF_TOKEN %d\n", EofToken);
fprintf(ErrFile, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1));
if ( DemandLookahead ) fprintf(ErrFile, "#define DEMAND_LOOK\n");
fprintf(ErrFile, "#include \"antlr.h\"\n");
fprintf(ErrFile, "#include \"dlgdef.h\"\n");
fprintf(ErrFile, "#include \"err.h\"\n\n");
/* Dump a zztokens for each automaton */
fprintf(ErrFile, "char *zztokens[%d]={\n", TokenNum-1);
fprintf(ErrFile, "\t/* 00 */\t\"Invalid\",\n");
if ( TokenStr[EofToken] != NULL )
fprintf(ErrFile, "\t/* %02d */\t\"%s\"", EofToken, TokenStr[i]);
else
fprintf(ErrFile, "\t/* %02d */\t\"EOF\"", EofToken);
for (i=TokenStart; i<TokenNum-1; i++)
{
if ( i == EpToken ) continue;
if ( TokenStr[i] != NULL )
fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, TokenStr[i]);
else
{
/* look in all lexclasses for the reg expr */
for (j=0; j<NumLexClasses; j++)
{
lexmode(j);
if ( ExprStr[i] != NULL )
{
fprintf(ErrFile, ",\n\t/* %02d */\t", i);
dumpExpr(ExprStr[i]);
break;
}
}
require(j<NumLexClasses, eMsgd("No label or expr for token %d",i));
}
}
fprintf(ErrFile, "\n};\n");
}
void
dumpExpr(e)
char *e;
{
while ( *e!='\0' )
{
if ( *e=='\\' && *(e+1)=='\\' )
{putc('\\', ErrFile); putc('\\', ErrFile); e+=2;}
else if ( *e=='\\' && *(e+1)=='"' )
{putc('\\', ErrFile); putc('"', ErrFile); e+=2;}
else if ( *e=='\\' ) {putc('\\', ErrFile); putc('\\', ErrFile); e++;}
else {putc(*e, ErrFile); e++;}
}
}