produce ANSI C under -a option
This commit is contained in:
parent
f4ecd50601
commit
35260bae58
10 changed files with 253 additions and 59 deletions
|
@ -4,7 +4,7 @@
|
||||||
.SH NAME
|
.SH NAME
|
||||||
LLgen, an extended LL(1) parser generator
|
LLgen, an extended LL(1) parser generator
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
LLgen [ \-vxw ] [ \-j[\fInum\fP] ] [ \-l\fInum\fP ] [ \-h\fInum\fP ] file ...
|
LLgen [ \-vxwa ] [ \-j[\fInum\fP] ] [ \-l\fInum\fP ] [ \-h\fInum\fP ] file ...
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fILLgen\fP
|
\fILLgen\fP
|
||||||
converts a context-free grammar into a set of
|
converts a context-free grammar into a set of
|
||||||
|
@ -76,6 +76,8 @@ symbols and these extended sets are also included in the
|
||||||
file.
|
file.
|
||||||
.IP \fB\-w\fP
|
.IP \fB\-w\fP
|
||||||
no warnings are given.
|
no warnings are given.
|
||||||
|
.IP \fB\-a\fP
|
||||||
|
Produce ANSI C function headers and prototypes.
|
||||||
.IP \fB\-j\fP[\fInum\fP]
|
.IP \fB\-j\fP[\fInum\fP]
|
||||||
when this flag is given, \fILLgen\fP will generate dense switches,
|
when this flag is given, \fILLgen\fP will generate dense switches,
|
||||||
so that the compiler can generate a jump table for it. This will only be
|
so that the compiler can generate a jump table for it. This will only be
|
||||||
|
|
|
@ -25,3 +25,32 @@ extern int LLcsymb;
|
||||||
#define LLtdecr(d) {LL_assert(LLtcnt[d] > 0); LLtcnt[d]--;}
|
#define LLtdecr(d) {LL_assert(LLtcnt[d] > 0); LLtcnt[d]--;}
|
||||||
#define LLsincr(d) LLscnt[d]++
|
#define LLsincr(d) LLscnt[d]++
|
||||||
#define LLtincr(d) LLtcnt[d]++
|
#define LLtincr(d) LLtcnt[d]++
|
||||||
|
|
||||||
|
#if LL_ANSI_C
|
||||||
|
extern int LL_LEXI(void);
|
||||||
|
extern void LLread(void);
|
||||||
|
extern int LLskip(void);
|
||||||
|
extern int LLnext(int);
|
||||||
|
extern void LLerror(int);
|
||||||
|
extern void LLnewlevel(unsigned int *);
|
||||||
|
extern void LLoldlevel(unsigned int *);
|
||||||
|
#ifndef LL_FASTER
|
||||||
|
extern void LLscan(int);
|
||||||
|
#endif
|
||||||
|
#ifndef LLNOFIRSTS
|
||||||
|
extern int LLfirst(int, int);
|
||||||
|
#endif
|
||||||
|
#else /* not LL_ANSI_C */
|
||||||
|
extern LLread();
|
||||||
|
extern int LLskip();
|
||||||
|
extern int LLnext();
|
||||||
|
extern LLerror();
|
||||||
|
extern LLnewlevel();
|
||||||
|
extern LLoldlevel();
|
||||||
|
#ifndef LL_FASTER
|
||||||
|
extern LLscan();
|
||||||
|
#endif
|
||||||
|
#ifndef LLNOFIRSTS
|
||||||
|
extern int LLfirst();
|
||||||
|
#endif
|
||||||
|
#endif /* not LL_ANSI_C */
|
||||||
|
|
|
@ -12,28 +12,26 @@ unsigned int LLscnt[LL_NSETS];
|
||||||
int LLcsymb, LLsymb;
|
int LLcsymb, LLsymb;
|
||||||
static int LLlevel;
|
static int LLlevel;
|
||||||
|
|
||||||
/* In this file are defined: */
|
#if LL_ANSI_C
|
||||||
extern LLread();
|
void LLmessage(int);
|
||||||
extern int LLskip();
|
|
||||||
extern int LLnext();
|
|
||||||
#ifndef LL_FASTER
|
|
||||||
extern LLscan();
|
|
||||||
#endif
|
#endif
|
||||||
extern LLerror();
|
|
||||||
# ifndef LLNOFIRSTS
|
|
||||||
extern int LLfirst();
|
|
||||||
# endif
|
|
||||||
extern LLnewlevel();
|
|
||||||
extern LLoldlevel();
|
|
||||||
|
|
||||||
#ifdef LL_USERHOOK
|
#ifdef LL_USERHOOK
|
||||||
|
#if LL_ANSI_C
|
||||||
|
static void LLdoskip(int);
|
||||||
|
static int LLuserhook(int, int*);
|
||||||
|
#else
|
||||||
static LLdoskip();
|
static LLdoskip();
|
||||||
static int LLuserhook();
|
static int LLuserhook();
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef LL_FASTER
|
#ifndef LL_FASTER
|
||||||
|
#if LL_ANSI_C
|
||||||
|
void LLscan(int t)
|
||||||
|
#else
|
||||||
LLscan(t)
|
LLscan(t)
|
||||||
int t;
|
int t;
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Check if the next symbol is equal to the parameter
|
* Check if the next symbol is equal to the parameter
|
||||||
|
@ -48,7 +46,11 @@ LLscan(t)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LL_ANSI_C
|
||||||
|
void LLread(void) {
|
||||||
|
#else
|
||||||
LLread() {
|
LLread() {
|
||||||
|
#endif
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((LLcsymb = LLindex[(LLsymb = LL_LEXI())]) >= 0) return;
|
if ((LLcsymb = LLindex[(LLsymb = LL_LEXI())]) >= 0) return;
|
||||||
LLmessage(0);
|
LLmessage(0);
|
||||||
|
@ -56,8 +58,12 @@ LLread() {
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LL_ANSI_C
|
||||||
|
void LLerror(int t)
|
||||||
|
#else
|
||||||
LLerror(t)
|
LLerror(t)
|
||||||
int t;
|
int t;
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
|
@ -67,7 +73,7 @@ LLerror(t)
|
||||||
#ifdef LL_USERHOOK
|
#ifdef LL_USERHOOK
|
||||||
static int lst[] = { EOFILE, 0 };
|
static int lst[] = { EOFILE, 0 };
|
||||||
if (LLuserhook(EOFILE, lst)) /* nothing */;
|
if (LLuserhook(EOFILE, lst)) /* nothing */;
|
||||||
#endif LL_USERHOOK
|
#endif /* LL_USERHOOK */
|
||||||
if (LLsymb != EOFILE && LLsymb > 0) {
|
if (LLsymb != EOFILE && LLsymb > 0) {
|
||||||
LLmessage(-1);
|
LLmessage(-1);
|
||||||
while ((LLsymb = LL_LEXI()) > 0 && LLsymb != EOFILE)
|
while ((LLsymb = LL_LEXI()) > 0 && LLsymb != EOFILE)
|
||||||
|
@ -92,7 +98,11 @@ LLerror(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef LLNOFIRSTS
|
#ifndef LLNOFIRSTS
|
||||||
LLfirst(x, d) {
|
#if LL_ANSI_C
|
||||||
|
int LLfirst(int x, int d) {
|
||||||
|
#else
|
||||||
|
int LLfirst(x, d) {
|
||||||
|
#endif
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
return (i = LLindex[x]) >= 0 &&
|
return (i = LLindex[x]) >= 0 &&
|
||||||
|
@ -100,8 +110,12 @@ LLfirst(x, d) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LLnext(n)
|
#if LL_ANSI_C
|
||||||
|
int LLnext(int n)
|
||||||
|
#else
|
||||||
|
int LLnext(n)
|
||||||
int n;
|
int n;
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
/* returns: 0 if the current symbol is'nt skipped, and it
|
/* returns: 0 if the current symbol is'nt skipped, and it
|
||||||
is'nt a member of "n",
|
is'nt a member of "n",
|
||||||
|
@ -122,7 +136,11 @@ LLnext(n)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLskip() {
|
#if LL_ANSI_C
|
||||||
|
int LLskip(void) {
|
||||||
|
#else
|
||||||
|
int LLskip() {
|
||||||
|
#endif
|
||||||
/* returns 0 if the current symbol is'nt skipped, and
|
/* returns 0 if the current symbol is'nt skipped, and
|
||||||
1 if it is, t.i., we have a new symbol
|
1 if it is, t.i., we have a new symbol
|
||||||
*/
|
*/
|
||||||
|
@ -130,20 +148,27 @@ LLskip() {
|
||||||
return LLdoskip(0);
|
return LLdoskip(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
#if LL_ANSI_C
|
||||||
LLuserhook(exp, list)
|
extern void LL_USERHOOK(int, int *);
|
||||||
int exp;
|
static int LLuserhook(int e, int *list)
|
||||||
|
#else
|
||||||
|
static int LLuserhook(e, list)
|
||||||
|
int e;
|
||||||
int *list;
|
int *list;
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
int old = LLsymb;
|
int old = LLsymb;
|
||||||
LL_USERHOOK(exp, list);
|
LL_USERHOOK(e, list);
|
||||||
LLread();
|
LLread();
|
||||||
return LLsymb != old;
|
return LLsymb != old;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
#if LL_ANSI_C
|
||||||
LLmklist(list)
|
static void LLmklist(register int *list)
|
||||||
|
#else
|
||||||
|
static LLmklist(list)
|
||||||
register int *list;
|
register int *list;
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
char Xset[LL_SSIZE];
|
char Xset[LL_SSIZE];
|
||||||
register char *p;
|
register char *p;
|
||||||
|
@ -167,13 +192,16 @@ LLmklist(list)
|
||||||
*list = 0;
|
*list = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
#if LL_ANSI_C
|
||||||
LLdoskip(exp)
|
static int LLdoskip(int e)
|
||||||
int exp;
|
#else
|
||||||
|
static int LLdoskip(e)
|
||||||
|
int e;
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
int LLx;
|
int LLx;
|
||||||
int list[LL_NTERMINALS+1];
|
int list[LL_NTERMINALS+1];
|
||||||
#endif LL_USERHOOK
|
#endif /* LL_USERHOOK */
|
||||||
register int i;
|
register int i;
|
||||||
int retval;
|
int retval;
|
||||||
int LLi, LLb;
|
int LLi, LLb;
|
||||||
|
@ -181,13 +209,13 @@ LLdoskip(exp)
|
||||||
retval = 0;
|
retval = 0;
|
||||||
#ifdef LL_USERHOOK
|
#ifdef LL_USERHOOK
|
||||||
LLmklist(list);
|
LLmklist(list);
|
||||||
LLx = LLuserhook(exp, list);
|
LLx = LLuserhook(e, list);
|
||||||
if (LLx) retval = 1;
|
if (LLx) retval = 1;
|
||||||
#endif LL_USERHOOK
|
#endif /* LL_USERHOOK */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (LLtcnt[LLcsymb] != 0) {
|
if (LLtcnt[LLcsymb] != 0) {
|
||||||
#ifdef LL_USERHOOK
|
#ifdef LL_USERHOOK
|
||||||
if (!exp || !LLx || LLcsymb == LLindex[exp])
|
if (!e || !LLx || LLcsymb == LLindex[e])
|
||||||
#endif
|
#endif
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -197,7 +225,7 @@ LLdoskip(exp)
|
||||||
if (LLscnt[i] != 0) {
|
if (LLscnt[i] != 0) {
|
||||||
if (LLsets[LL_SSIZE*i+LLi] & LLb) {
|
if (LLsets[LL_SSIZE*i+LLi] & LLb) {
|
||||||
#ifdef LL_USERHOOK
|
#ifdef LL_USERHOOK
|
||||||
if (!exp || !LLx || LLcsymb == LLindex[exp])
|
if (!e || !LLx || LLcsymb == LLindex[e])
|
||||||
#endif
|
#endif
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -205,10 +233,10 @@ LLdoskip(exp)
|
||||||
}
|
}
|
||||||
#ifdef LL_USERHOOK
|
#ifdef LL_USERHOOK
|
||||||
if (LLx) {
|
if (LLx) {
|
||||||
LLx = LLuserhook(exp, list);
|
LLx = LLuserhook(e, list);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif LL_USERHOOK
|
#endif /* LL_USERHOOK */
|
||||||
LLmessage(0);
|
LLmessage(0);
|
||||||
retval = 1;
|
retval = 1;
|
||||||
LLread();
|
LLread();
|
||||||
|
@ -216,7 +244,11 @@ LLdoskip(exp)
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LL_ANSI_C
|
||||||
|
void LLnewlevel(unsigned int *LLsinfo) {
|
||||||
|
#else
|
||||||
LLnewlevel(LLsinfo) unsigned int *LLsinfo; {
|
LLnewlevel(LLsinfo) unsigned int *LLsinfo; {
|
||||||
|
#endif
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
if (LLlevel++) {
|
if (LLlevel++) {
|
||||||
|
@ -234,9 +266,11 @@ LLnewlevel(LLsinfo) unsigned int *LLsinfo; {
|
||||||
LLtincr(0);
|
LLtincr(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
LLoldlevel(LLsinfo)
|
#if LL_ANSI_C
|
||||||
unsigned int *LLsinfo;
|
void LLoldlevel(unsigned int *LLsinfo) {
|
||||||
{
|
#else
|
||||||
|
LLoldlevel(LLsinfo) unsigned int *LLsinfo; {
|
||||||
|
#endif
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
LLtdecr(0);
|
LLtdecr(0);
|
||||||
|
|
|
@ -29,6 +29,7 @@ static string rcsid = "$Header$";
|
||||||
p_mem alloc(), ralloc();
|
p_mem alloc(), ralloc();
|
||||||
string store();
|
string store();
|
||||||
p_gram search();
|
p_gram search();
|
||||||
|
long ftell();
|
||||||
|
|
||||||
static int nparams; /* parameter count for nonterminals */
|
static int nparams; /* parameter count for nonterminals */
|
||||||
static int acount; /* count #of global actions */
|
static int acount; /* count #of global actions */
|
||||||
|
@ -211,6 +212,7 @@ rule { register p_nont p;
|
||||||
p->n_count = acount;
|
p->n_count = acount;
|
||||||
acount = 0;
|
acount = 0;
|
||||||
p->n_lineno = linecount;
|
p->n_lineno = linecount;
|
||||||
|
p->n_off = ftell(fact);
|
||||||
}
|
}
|
||||||
[ params { p->n_flags |= PARAMS;
|
[ params { p->n_flags |= PARAMS;
|
||||||
if (nparams > 15) {
|
if (nparams > 15) {
|
||||||
|
|
|
@ -131,19 +131,48 @@ do_compute() {
|
||||||
STATIC
|
STATIC
|
||||||
createsets() {
|
createsets() {
|
||||||
/*
|
/*
|
||||||
* Allocate space for the sets
|
* Allocate space for the sets. Also determine which files use
|
||||||
|
* which nonterminals, and determine which nonterminals can be
|
||||||
|
* made static.
|
||||||
*/
|
*/
|
||||||
register p_nont p;
|
register p_nont p;
|
||||||
|
register p_file f;
|
||||||
|
register p_start st;
|
||||||
|
register int i;
|
||||||
|
int n = NINTS(NBYTES(nnonterms));
|
||||||
|
p_mem alloc();
|
||||||
|
|
||||||
for (p = nonterms; p < maxnt; p++) {
|
for (f = files; f < maxfiles; f++) {
|
||||||
|
register p_set s;
|
||||||
|
f->f_used = s = (p_set) alloc((unsigned)n*sizeof(*(f->f_used)));
|
||||||
|
for (i = n; i; i--) *s++ = 0;
|
||||||
|
for (i = f->f_nonterminals; i != -1; i = p->n_next) {
|
||||||
|
p = &nonterms[i];
|
||||||
|
p->n_flags |= GENSTATIC;
|
||||||
p->n_first = get_set();
|
p->n_first = get_set();
|
||||||
p->n_follow = get_set();
|
p->n_follow = get_set();
|
||||||
walk(p->n_rule);
|
walk(f->f_used, p->n_rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (f = files; f < maxfiles; f++) {
|
||||||
|
for (i = f->f_nonterminals; i != -1; i = p->n_next) {
|
||||||
|
register p_file f2;
|
||||||
|
|
||||||
|
p = &nonterms[i];
|
||||||
|
for (f2 = files; f2 < maxfiles; f2++) {
|
||||||
|
if (f2 != f && IN(f2->f_used, i)) {
|
||||||
|
p->n_flags &= ~GENSTATIC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (st = start; st; st = st->ff_next) {
|
||||||
|
nonterms[st->ff_nont].n_flags &= ~GENSTATIC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
walk(p) register p_gram p; {
|
walk(u, p) p_set u; register p_gram p; {
|
||||||
/*
|
/*
|
||||||
* Walk through the grammar rule p, allocating sets
|
* Walk through the grammar rule p, allocating sets
|
||||||
*/
|
*/
|
||||||
|
@ -156,7 +185,7 @@ walk(p) register p_gram p; {
|
||||||
q = g_getterm(p);
|
q = g_getterm(p);
|
||||||
q->t_first = get_set();
|
q->t_first = get_set();
|
||||||
q->t_follow = get_set();
|
q->t_follow = get_set();
|
||||||
walk(q->t_rule);
|
walk(u, q->t_rule);
|
||||||
break; }
|
break; }
|
||||||
case ALTERNATION : {
|
case ALTERNATION : {
|
||||||
register p_link l;
|
register p_link l;
|
||||||
|
@ -164,7 +193,12 @@ walk(p) register p_gram p; {
|
||||||
l = g_getlink(p);
|
l = g_getlink(p);
|
||||||
l->l_symbs = get_set();
|
l->l_symbs = get_set();
|
||||||
l->l_others = get_set();
|
l->l_others = get_set();
|
||||||
walk(l->l_rule);
|
walk(u, l->l_rule);
|
||||||
|
break; }
|
||||||
|
case NONTERM : {
|
||||||
|
register int i = g_getcont(p);
|
||||||
|
|
||||||
|
PUTIN(u, i);
|
||||||
break; }
|
break; }
|
||||||
case EORULE :
|
case EORULE :
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -75,3 +75,4 @@ extern string rec_file, incl_file;
|
||||||
extern int low_percentage, high_percentage;
|
extern int low_percentage, high_percentage;
|
||||||
extern int min_cases_for_jmptable;
|
extern int min_cases_for_jmptable;
|
||||||
extern int jmptable_option;
|
extern int jmptable_option;
|
||||||
|
extern int ansi_c;
|
||||||
|
|
|
@ -56,6 +56,8 @@ STATIC prset();
|
||||||
STATIC macro();
|
STATIC macro();
|
||||||
STATIC controlline();
|
STATIC controlline();
|
||||||
STATIC getparams();
|
STATIC getparams();
|
||||||
|
STATIC getansiparams();
|
||||||
|
STATIC genprototypes();
|
||||||
STATIC gettok();
|
STATIC gettok();
|
||||||
STATIC rulecode();
|
STATIC rulecode();
|
||||||
STATIC int * dopush();
|
STATIC int * dopush();
|
||||||
|
@ -113,6 +115,8 @@ gencode(argc) {
|
||||||
opentemp(f_input);
|
opentemp(f_input);
|
||||||
correct_prefix();
|
correct_prefix();
|
||||||
/* generate code ... */
|
/* generate code ... */
|
||||||
|
if (ansi_c) fputs("#define LL_ANSI_C 1\n", fpars);
|
||||||
|
fprintf(fpars, "#define LL_LEXI %s\n", lexical);
|
||||||
copyfile(incl_file);
|
copyfile(incl_file);
|
||||||
generate(p);
|
generate(p);
|
||||||
getaction(2);
|
getaction(2);
|
||||||
|
@ -123,6 +127,7 @@ gencode(argc) {
|
||||||
}
|
}
|
||||||
geninclude();
|
geninclude();
|
||||||
genrecovery();
|
genrecovery();
|
||||||
|
fclose(fact);
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
|
@ -165,8 +170,10 @@ genrecovery() {
|
||||||
opentemp((string) 0);
|
opentemp((string) 0);
|
||||||
f = fpars;
|
f = fpars;
|
||||||
correct_prefix();
|
correct_prefix();
|
||||||
copyfile(incl_file);
|
|
||||||
if (!firsts) fputs("#define LLNOFIRSTS\n", f);
|
if (!firsts) fputs("#define LLNOFIRSTS\n", f);
|
||||||
|
if (ansi_c) fputs("#define LL_ANSI_C 1\n", f);
|
||||||
|
fprintf(f, "#define LL_LEXI %s\n", lexical);
|
||||||
|
copyfile(incl_file);
|
||||||
for (st = start; st; st = st->ff_next) {
|
for (st = start; st; st = st->ff_next) {
|
||||||
/* Make sure that every set the parser needs is in the list
|
/* Make sure that every set the parser needs is in the list
|
||||||
* before generating a define of the number of them!
|
* before generating a define of the number of them!
|
||||||
|
@ -178,17 +185,23 @@ genrecovery() {
|
||||||
}
|
}
|
||||||
i = maxptr - setptr;
|
i = maxptr - setptr;
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"#define LL_LEXI %s\n#define LL_SSIZE %d\n#define LL_NSETS %d\n#define LL_NTERMINALS %d\n",
|
"#define LL_SSIZE %d\n#define LL_NSETS %d\n#define LL_NTERMINALS %d\n",
|
||||||
lexical,
|
|
||||||
nbytes,
|
nbytes,
|
||||||
i > 0 ? i : 1,
|
i > 0 ? i : 1,
|
||||||
ntokens);
|
ntokens);
|
||||||
if (onerror) fprintf(f,"#define LL_USERHOOK %s\n", onerror);
|
if (onerror) fprintf(f,"#define LL_USERHOOK %s\n", onerror);
|
||||||
/* Now generate the routines that call the startsymbols */
|
/* Now generate the routines that call the startsymbols */
|
||||||
for (st = start; st; st = st->ff_next) {
|
if (ansi_c) for (st = start; st; st = st->ff_next) {
|
||||||
fputs(st->ff_name, f);
|
|
||||||
p = &nonterms[st->ff_nont];
|
p = &nonterms[st->ff_nont];
|
||||||
fputs("() {\n\tunsigned int s[LL_NTERMINALS+LL_NSETS+2];\n\tLLnewlevel(s);\n\tLLread();\n", f);
|
fputs("void ", f);
|
||||||
|
genextname(st->ff_nont, p->n_name, f);
|
||||||
|
fputs("(void);\n", f);
|
||||||
|
}
|
||||||
|
for (st = start; st; st = st->ff_next) {
|
||||||
|
if (ansi_c) fputs("void ", f);
|
||||||
|
fprintf(f, "%s(%s)", st->ff_name, ansi_c ? "void" : "");
|
||||||
|
p = &nonterms[st->ff_nont];
|
||||||
|
fputs(" {\n\tunsigned int s[LL_NTERMINALS+LL_NSETS+2];\n\tLLnewlevel(s);\n\tLLread();\n", f);
|
||||||
if (g_gettype(p->n_rule) == ALTERNATION) {
|
if (g_gettype(p->n_rule) == ALTERNATION) {
|
||||||
genpush(findindex(p->n_contains));
|
genpush(findindex(p->n_contains));
|
||||||
}
|
}
|
||||||
|
@ -238,6 +251,7 @@ generate(f) p_file f; {
|
||||||
int i;
|
int i;
|
||||||
register p_first ff;
|
register p_first ff;
|
||||||
int mustpop;
|
int mustpop;
|
||||||
|
int is_first = 1;
|
||||||
|
|
||||||
fprintf(fpars, "#define LL_LEXI %s\n", lexical);
|
fprintf(fpars, "#define LL_LEXI %s\n", lexical);
|
||||||
listcount = 0;
|
listcount = 0;
|
||||||
|
@ -258,13 +272,18 @@ generate(f) p_file f; {
|
||||||
getntparams(p) == 0) {
|
getntparams(p) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (is_first) genprototypes(f);
|
||||||
|
is_first = 0;
|
||||||
|
if (p->n_flags & GENSTATIC) fputs("static ", fpars);
|
||||||
|
if (ansi_c) fputs("void ", fpars);
|
||||||
genextname(s, p->n_name, fpars);
|
genextname(s, p->n_name, fpars);
|
||||||
if (p->n_flags & PARAMS) {
|
if (p->n_flags & PARAMS) {
|
||||||
fputs("(\n", fpars);
|
fputs("(\n", fpars);
|
||||||
controlline();
|
controlline();
|
||||||
getparams();
|
if (ansi_c) getansiparams(1);
|
||||||
|
else getparams();
|
||||||
}
|
}
|
||||||
else fputs("() {\n", fpars);
|
else fprintf(fpars, "(%s) {\n", ansi_c ? "void" : "");
|
||||||
if (p->n_flags & LOCALS) getaction(1);
|
if (p->n_flags & LOCALS) getaction(1);
|
||||||
i = getntsafe(p);
|
i = getntsafe(p);
|
||||||
mustpop = NOPOP;
|
mustpop = NOPOP;
|
||||||
|
@ -380,6 +399,71 @@ getparams() {
|
||||||
fprintf(fpars, "%c {\n",add_semi);
|
fprintf(fpars, "%c {\n",add_semi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
genprototypes(f)
|
||||||
|
register p_file f;
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Generate prototypes for all nonterminals
|
||||||
|
*/
|
||||||
|
register int i;
|
||||||
|
register p_nont p;
|
||||||
|
long off = ftell(fact);
|
||||||
|
|
||||||
|
for (i = 0; i < nnonterms; i++) {
|
||||||
|
if (! IN(f->f_used, i)) continue;
|
||||||
|
p = &nonterms[i];
|
||||||
|
if (g_gettype(p->n_rule) == EORULE &&
|
||||||
|
getntparams(p) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ansi_c || (p->n_flags & GENSTATIC)) {
|
||||||
|
if (p->n_flags & GENSTATIC) fputs("static ", fpars);
|
||||||
|
if (ansi_c) fputs("void ", fpars);
|
||||||
|
genextname(i, p->n_name, fpars);
|
||||||
|
if (! ansi_c) fputs("();\n", fpars);
|
||||||
|
else if (p->n_flags & PARAMS) {
|
||||||
|
fputs("(\n", fpars);
|
||||||
|
fseek(fact, p->n_off, 0);
|
||||||
|
controlline();
|
||||||
|
getansiparams(0);
|
||||||
|
fseek(fact, off, 0);
|
||||||
|
}
|
||||||
|
else fputs("(void);\n", fpars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
getansiparams(mkdef) {
|
||||||
|
/* getansiparams is called if a nonterminal has parameters
|
||||||
|
* and an ANSI C function definition/declaration has to be produced.
|
||||||
|
* If a definition has to be produced, "mkdef" is set to 1.
|
||||||
|
*/
|
||||||
|
register int l;
|
||||||
|
char add_semi = ' ';
|
||||||
|
int delayed = 0;
|
||||||
|
|
||||||
|
ltext[0] = '\0';
|
||||||
|
while ((l = gettok()) != ENDDECL) {
|
||||||
|
if (delayed) {
|
||||||
|
fputc(',', fpars);
|
||||||
|
delayed = 0;
|
||||||
|
}
|
||||||
|
if ((l == ';' || l == ',') && ltext[0] != '\0') {
|
||||||
|
/*
|
||||||
|
* The last identifier found before a ';' or a ','
|
||||||
|
* must be a parameter
|
||||||
|
*/
|
||||||
|
delayed = 1;
|
||||||
|
ltext[0] = '\0';
|
||||||
|
}
|
||||||
|
else if (l == IDENT) fprintf(fpars, "%s", ltext);
|
||||||
|
else fputc(l, fpars);
|
||||||
|
}
|
||||||
|
fprintf(fpars, ") %c\n", mkdef ? '{' : ';');
|
||||||
|
}
|
||||||
|
|
||||||
STATIC
|
STATIC
|
||||||
gettok() {
|
gettok() {
|
||||||
/* Read from the action file. */
|
/* Read from the action file. */
|
||||||
|
|
|
@ -66,3 +66,4 @@ string rec_file, incl_file;
|
||||||
int low_percentage = 10, high_percentage = 30;
|
int low_percentage = 10, high_percentage = 30;
|
||||||
int min_cases_for_jmptable = 8;
|
int min_cases_for_jmptable = 8;
|
||||||
int jmptable_option;
|
int jmptable_option;
|
||||||
|
int ansi_c = 0;
|
||||||
|
|
|
@ -100,6 +100,10 @@ main(argc,argv) register string argv[]; {
|
||||||
ntneeded = 1;
|
ntneeded = 1;
|
||||||
ntprint = 1;
|
ntprint = 1;
|
||||||
continue;
|
continue;
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
ansi_c = 1;
|
||||||
|
continue;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,"illegal option : %c\n",*arg);
|
fprintf(stderr,"illegal option : %c\n",*arg);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -105,6 +105,7 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
# define getntparams(p) ((p)->n_flags&017)
|
# define getntparams(p) ((p)->n_flags&017)
|
||||||
# define setntparams(p,i) {assert(((unsigned)(i))<=017);(p)->n_flags&=~017;(p)->n_flags|=(i);}
|
# define setntparams(p,i) {assert(((unsigned)(i))<=017);(p)->n_flags&=~017;(p)->n_flags|=(i);}
|
||||||
|
# define GENSTATIC 01000 /* set if routine can be made static */
|
||||||
# define RECURSIVE 02000 /* Set if the default rule is recursive */
|
# define RECURSIVE 02000 /* Set if the default rule is recursive */
|
||||||
# define PARAMS 04000 /* tells if a nonterminal has parameters */
|
# define PARAMS 04000 /* tells if a nonterminal has parameters */
|
||||||
# define EMPTY 010000 /* tells if a nonterminal produces empty */
|
# define EMPTY 010000 /* tells if a nonterminal produces empty */
|
||||||
|
@ -133,6 +134,7 @@ typedef struct {
|
||||||
p_set n_contains; /* pointer to symbols that can be produced */
|
p_set n_contains; /* pointer to symbols that can be produced */
|
||||||
string n_name; /* name of nonterminal */
|
string n_name; /* name of nonterminal */
|
||||||
int n_next; /* index of next nonterminal */
|
int n_next; /* index of next nonterminal */
|
||||||
|
long n_off; /* index of parameters in action file */
|
||||||
} t_nont, *p_nont;
|
} t_nont, *p_nont;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -225,6 +227,7 @@ typedef struct f_file {
|
||||||
*/
|
*/
|
||||||
int f_nonterminals; /* list of nonterminals in this file */
|
int f_nonterminals; /* list of nonterminals in this file */
|
||||||
int f_terminals; /* list of terminals in this file */
|
int f_terminals; /* list of terminals in this file */
|
||||||
|
p_set f_used; /* set of nonterminals used in this file */
|
||||||
} t_file, *p_file;
|
} t_file, *p_file;
|
||||||
|
|
||||||
typedef struct info_alloc {
|
typedef struct info_alloc {
|
||||||
|
|
Loading…
Reference in a new issue