Initial revision
This commit is contained in:
parent
6cbb37051b
commit
a21f936651
14 changed files with 1788 additions and 0 deletions
12
util/LLgen/lib/incl
Normal file
12
util/LLgen/lib/incl
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/* $Header$ */
|
||||||
|
|
||||||
|
#define LLin(x) (LLsets[(x)+LLi]&LLb)
|
||||||
|
|
||||||
|
extern short *LLptr;
|
||||||
|
extern char LLsets[];
|
||||||
|
extern int LLi, LLb;
|
||||||
|
extern int LLsymb;
|
||||||
|
extern int LLcsymb;
|
||||||
|
extern int LLscd;
|
||||||
|
|
||||||
|
# include "Lpars.h"
|
215
util/LLgen/lib/rec
Normal file
215
util/LLgen/lib/rec
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
/*
|
||||||
|
* Some grammar independent code.
|
||||||
|
* This file is copied into Lpars.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char *rcsid = "$Header$";
|
||||||
|
|
||||||
|
#define LLSTSIZ 1024
|
||||||
|
static short LLstack[LLSTSIZ]; /* Recovery stack */
|
||||||
|
short * LLptr; /* ptr in it */
|
||||||
|
#define LLmax (&LLstack[LLSTSIZ-1]) /* if beyond this, overflow */
|
||||||
|
int LLscd; /* lookahead done or not? */
|
||||||
|
int LLb,LLi;
|
||||||
|
int LLsymb;
|
||||||
|
int LLcsymb;
|
||||||
|
static int LLlevel;
|
||||||
|
static short * LLbase;
|
||||||
|
|
||||||
|
static struct LLsaved {
|
||||||
|
int LLs_i, LLs_b, LLs_s, LLs_c, LLs_t;
|
||||||
|
short *LLs_p, *LLs_x;
|
||||||
|
} LLsaved[LL_MAX];
|
||||||
|
|
||||||
|
/* In this file are defined: */
|
||||||
|
extern LLcheck();
|
||||||
|
extern LLscan();
|
||||||
|
extern LLpush();
|
||||||
|
extern LLlpush();
|
||||||
|
extern int LLpop();
|
||||||
|
extern int LLsskip();
|
||||||
|
static LLerror();
|
||||||
|
extern LLnewlevel();
|
||||||
|
extern LLoldlevel();
|
||||||
|
|
||||||
|
LLcheck() {
|
||||||
|
register c;
|
||||||
|
/*
|
||||||
|
* The symbol to be checked is on the stack.
|
||||||
|
*/
|
||||||
|
if (!LLscd) {
|
||||||
|
if ((c = LL_LEXI()) <= 0) c = EOFILE;
|
||||||
|
LLsymb = c;
|
||||||
|
}
|
||||||
|
else LLscd = 0;
|
||||||
|
if (LLsymb == *--LLptr) return;
|
||||||
|
/*
|
||||||
|
* If we come here, an error has been detected.
|
||||||
|
* LLpop will try and recover
|
||||||
|
*/
|
||||||
|
LLptr++;
|
||||||
|
while (LLindex[LLsymb] < 0) {
|
||||||
|
LLerror(0);
|
||||||
|
if ((LLsymb = LL_LEXI()) <= 0) LLsymb = EOFILE;
|
||||||
|
}
|
||||||
|
LLcsymb = LLindex[LLsymb];
|
||||||
|
LLb = LLbyte[LLcsymb];
|
||||||
|
LLi = LLcsymb>>3;
|
||||||
|
LLscd = 1;
|
||||||
|
if (!LLpop()) LLerror(*LLptr);
|
||||||
|
LLscd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLscan(t) {
|
||||||
|
/*
|
||||||
|
* Check if the next symbol is equal to the parameter
|
||||||
|
*/
|
||||||
|
if (!LLscd) {
|
||||||
|
if ((LLsymb = LL_LEXI()) <= 0) LLsymb = EOFILE;
|
||||||
|
}
|
||||||
|
else LLscd = 0;
|
||||||
|
if (LLsymb == t) return;
|
||||||
|
/*
|
||||||
|
* If we come here, an error has been detected
|
||||||
|
*/
|
||||||
|
LLpush(t);
|
||||||
|
LLscd = 1;
|
||||||
|
while (LLindex[LLsymb] < 0) {
|
||||||
|
LLerror(0);
|
||||||
|
if ((LLsymb = LL_LEXI()) <= 0) LLsymb = EOFILE;
|
||||||
|
}
|
||||||
|
LLcsymb = LLindex[LLsymb];
|
||||||
|
LLb = LLbyte[LLcsymb];
|
||||||
|
LLi = LLcsymb>>3;
|
||||||
|
if (!LLpop()) LLerror(t);
|
||||||
|
LLscd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLpush(t) {
|
||||||
|
if (LLptr == LLmax) {
|
||||||
|
LLerror(-1);
|
||||||
|
}
|
||||||
|
*LLptr++ = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLlpush(d) {
|
||||||
|
register i;
|
||||||
|
register short *p;
|
||||||
|
|
||||||
|
p = &LLlists[d];
|
||||||
|
i = *p++;
|
||||||
|
while(i--) {
|
||||||
|
if (LLptr == LLmax) {
|
||||||
|
LLerror(-1);
|
||||||
|
}
|
||||||
|
*LLptr++ = *p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LLsskip() {
|
||||||
|
/*
|
||||||
|
* Error recovery, and not only that!
|
||||||
|
* Skip symbols until one is found that is on the stack.
|
||||||
|
* Return 1 if it is on top of the stack
|
||||||
|
*/
|
||||||
|
register short *t;
|
||||||
|
register i;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (!LLscd) {
|
||||||
|
lab:
|
||||||
|
if ((i = LL_LEXI()) <= 0) i = EOFILE;
|
||||||
|
LLsymb = i;
|
||||||
|
if ((i = LLindex[i]) < 0) {
|
||||||
|
LLerror(0);
|
||||||
|
goto lab;
|
||||||
|
/*
|
||||||
|
* Ugly, but we want speed
|
||||||
|
* on possibly correct symbols !!
|
||||||
|
* So, no breaks out of "for (;;)"
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
LLcsymb = i;
|
||||||
|
LLb = LLbyte[i];
|
||||||
|
LLi = (i>>3);
|
||||||
|
LLscd = 1;
|
||||||
|
}
|
||||||
|
t = LLptr-1;
|
||||||
|
i = *t;
|
||||||
|
if (!((i<=0 && LLsets[LLi-i]&LLb)||i==LLsymb)) {
|
||||||
|
while (--t >= LLbase) {
|
||||||
|
/*
|
||||||
|
* If the element on the stack is negative,
|
||||||
|
* its opposite is an index in the setarray,
|
||||||
|
* otherwise it is a terminal symbol
|
||||||
|
*/
|
||||||
|
i = *t;
|
||||||
|
if ((i<=0&&LLsets[LLi-i]&LLb)||i==LLsymb){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t >= LLbase) break;
|
||||||
|
LLerror(0);
|
||||||
|
LLscd = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t == LLptr - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLpop() {
|
||||||
|
register i;
|
||||||
|
|
||||||
|
i = LLsskip();
|
||||||
|
LLptr--;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
LLerror(d) {
|
||||||
|
|
||||||
|
LLmessage(d);
|
||||||
|
if (d < 0) exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLnewlevel() {
|
||||||
|
register struct LLsaved *p;
|
||||||
|
|
||||||
|
if (!LLlevel++) {
|
||||||
|
LLptr = LLstack;
|
||||||
|
LLbase = LLstack;
|
||||||
|
LLpush(EOFILE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (LLlevel > LL_MAX) LLerror(-1);
|
||||||
|
p = &LLsaved[LLlevel - 2];
|
||||||
|
p->LLs_p = LLptr;
|
||||||
|
p->LLs_i = LLi;
|
||||||
|
p->LLs_b = LLb;
|
||||||
|
p->LLs_s = LLsymb;
|
||||||
|
p->LLs_t = LLcsymb;
|
||||||
|
p->LLs_c = LLscd;
|
||||||
|
p->LLs_x = LLbase;
|
||||||
|
LLbase = LLptr;
|
||||||
|
LLpush(EOFILE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LLoldlevel() {
|
||||||
|
register struct LLsaved *p;
|
||||||
|
|
||||||
|
LLcheck();
|
||||||
|
if (--LLlevel) {
|
||||||
|
p = &LLsaved[LLlevel-1];
|
||||||
|
LLptr = p->LLs_p;
|
||||||
|
LLi = p->LLs_i;
|
||||||
|
LLb = p->LLs_b;
|
||||||
|
LLsymb = p->LLs_s;
|
||||||
|
LLcsymb = p->LLs_t;
|
||||||
|
LLbase = p->LLs_x;
|
||||||
|
LLscd = p->LLs_c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
54
util/LLgen/src/alloc.c
Normal file
54
util/LLgen/src/alloc.c
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* alloc.c
|
||||||
|
* Interface to malloc() and realloc()
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "types.h"
|
||||||
|
# include "extern.h"
|
||||||
|
|
||||||
|
static string rcsid = "$Header$";
|
||||||
|
|
||||||
|
static string e_nomem = "Out of memory";
|
||||||
|
|
||||||
|
p_mem
|
||||||
|
alloc(size) unsigned size; {
|
||||||
|
register p_mem p;
|
||||||
|
p_mem malloc();
|
||||||
|
|
||||||
|
if ((p = malloc(size)) == 0) fatal(linecount,e_nomem);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_mem
|
||||||
|
ralloc(p,size) p_mem p; unsigned size; {
|
||||||
|
register p_mem q;
|
||||||
|
p_mem realloc();
|
||||||
|
|
||||||
|
if ((q = realloc(p,size)) == 0) fatal(linecount,e_nomem);
|
||||||
|
return q;
|
||||||
|
}
|
35
util/LLgen/src/assert.h
Normal file
35
util/LLgen/src/assert.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* assert.h $Header$
|
||||||
|
* an assertion macro
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define assert(x) if(!(x)) badassertion("x",__FILE__,__LINE__)
|
||||||
|
#else
|
||||||
|
#define assert(x) /* nothing */
|
||||||
|
#endif
|
86
util/LLgen/src/extern.h
Normal file
86
util/LLgen/src/extern.h
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* extern.h $Header$
|
||||||
|
* Miscellanious constants and
|
||||||
|
* some variables that are visible in more than one file
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* options for the identifier search routine
|
||||||
|
*/
|
||||||
|
# define JUSTLOOKING 0
|
||||||
|
# define ENTERING 1
|
||||||
|
# define BOTH 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now for some declarations
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern char ltext[]; /* input buffer */
|
||||||
|
extern int nnonterms; /* number of nonterminals */
|
||||||
|
extern int nterminals; /* number of terminals */
|
||||||
|
extern p_start start; /* will contain startsymbols */
|
||||||
|
extern int linecount; /* line number */
|
||||||
|
extern int assval; /* to create difference between literals
|
||||||
|
* and other terminals
|
||||||
|
*/
|
||||||
|
extern t_nont nonterms[]; /* the nonterminal array */
|
||||||
|
extern p_nont maxnt; /* is filled up until here */
|
||||||
|
extern int order[]; /* order of nonterminals in the grammar,
|
||||||
|
* important because actions are copied to
|
||||||
|
* a temporary file in the order in which they
|
||||||
|
* were read
|
||||||
|
*/
|
||||||
|
extern int *maxorder; /* will contain &order[nnonterms] */
|
||||||
|
extern t_entry h_entry[]; /* terminal and nonterminal entrys,
|
||||||
|
* first NTERMINAL entrys reserved
|
||||||
|
* for terminals
|
||||||
|
*/
|
||||||
|
extern p_entry max_t_ent; /* will contain &h_entry[nterminals] */
|
||||||
|
# define min_nt_ent &h_entry[NTERMINALS]
|
||||||
|
extern string pentry[]; /* pointers to various allocated things */
|
||||||
|
extern string e_noopen; /* Error message string used often */
|
||||||
|
extern int verbose; /* Level of verbosity */
|
||||||
|
extern string lexical; /* name of lexical analyser */
|
||||||
|
extern int ntneeded; /* ntneeded = 1 if nonterminals are included
|
||||||
|
* in the sets.
|
||||||
|
*/
|
||||||
|
extern int ntprint; /* ntprint = 1 if they must be printed too in
|
||||||
|
* the LL.output file (-x option)
|
||||||
|
*/
|
||||||
|
# ifndef NDEBUG
|
||||||
|
extern int debug;
|
||||||
|
# endif not NDEBUG
|
||||||
|
extern p_file files,pfile; /* pointers to file structure.
|
||||||
|
* "files" points to the start of the
|
||||||
|
* list */
|
||||||
|
extern string LLgenid; /* LLgen identification string */
|
||||||
|
extern t_token lextoken; /* the current token */
|
||||||
|
extern int nerrors;
|
||||||
|
extern int fflag; /* Enable compiler to generate jump tables
|
||||||
|
* for switches?
|
||||||
|
*/
|
71
util/LLgen/src/global.c
Normal file
71
util/LLgen/src/global.c
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* global.c
|
||||||
|
* Contains declarations visible in several other source files
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "types.h"
|
||||||
|
# include "io.h"
|
||||||
|
# include "tunable.h"
|
||||||
|
|
||||||
|
static string rcsid = "$Header$";
|
||||||
|
|
||||||
|
char ltext[LTEXTSZ];
|
||||||
|
t_entry h_entry[NTERMINALS+NNONTERMS+1];
|
||||||
|
p_entry max_t_ent;
|
||||||
|
t_nont nonterms[NNONTERMS+1];
|
||||||
|
int nnonterms;
|
||||||
|
int nterminals;
|
||||||
|
int order[NNONTERMS+1];
|
||||||
|
int *maxorder;
|
||||||
|
p_start start;
|
||||||
|
int linecount;
|
||||||
|
int assval;
|
||||||
|
string pentry[ENTSIZ];
|
||||||
|
FILE *fout;
|
||||||
|
FILE *fpars;
|
||||||
|
FILE *finput;
|
||||||
|
FILE *fact;
|
||||||
|
p_nont maxnt;
|
||||||
|
string f_pars = PARSERFILE;
|
||||||
|
string f_out = OUTFILE;
|
||||||
|
string f_temp = ACTFILE;
|
||||||
|
string f_input;
|
||||||
|
string e_noopen = "Cannot open %s";
|
||||||
|
int verbose;
|
||||||
|
string lexical;
|
||||||
|
int ntneeded;
|
||||||
|
int ntprint;
|
||||||
|
# ifndef NDEBUG
|
||||||
|
int debug;
|
||||||
|
# endif not NDEBUG
|
||||||
|
p_file files;
|
||||||
|
p_file pfile;
|
||||||
|
string LLgenid = "/* LLgen generated code from source %s */\n";
|
||||||
|
t_token lextoken;
|
||||||
|
int nerrors;
|
||||||
|
int fflag;
|
49
util/LLgen/src/io.h
Normal file
49
util/LLgen/src/io.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* io.h $Header$
|
||||||
|
* Some important file names and variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <ctype.h>
|
||||||
|
|
||||||
|
/* FILES */
|
||||||
|
|
||||||
|
# define OUTFILE "LL.output" /* -v option */
|
||||||
|
# define PARSERFILE "LL.xxx" /* This is what we want */
|
||||||
|
# define ACTFILE "LL.temp" /* temporary file to save actions */
|
||||||
|
# define HFILE "Lpars.h" /* file for "#define's " */
|
||||||
|
# define RFILE "Lpars.c" /* Error recovery */
|
||||||
|
|
||||||
|
extern FILE *finput;
|
||||||
|
extern FILE *fpars;
|
||||||
|
extern FILE *fact;
|
||||||
|
extern FILE *fout;
|
||||||
|
extern string f_pars;
|
||||||
|
extern string f_temp;
|
||||||
|
extern string f_out;
|
||||||
|
extern string f_input;
|
58
util/LLgen/src/machdep.c
Normal file
58
util/LLgen/src/machdep.c
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* machdep.c
|
||||||
|
* Machine dependant things
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
# include "types.h"
|
||||||
|
|
||||||
|
static string rcsid = "$Header$";
|
||||||
|
|
||||||
|
/* In this file the following routines are defined: */
|
||||||
|
extern UNLINK();
|
||||||
|
extern RENAME();
|
||||||
|
extern string libpath();
|
||||||
|
|
||||||
|
UNLINK(x) string x; {
|
||||||
|
unlink(x); /* systemcall to remove file */
|
||||||
|
}
|
||||||
|
|
||||||
|
RENAME(x,y) string x,y; {
|
||||||
|
unlink(y);
|
||||||
|
if(link(x,y)!=0)fatal(1,"Cannot link to %s",y);
|
||||||
|
unlink(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
libpath(s) char *s; {
|
||||||
|
static char buf[100];
|
||||||
|
|
||||||
|
strcpy(buf,"/usr/local/lib/LLgen/");
|
||||||
|
strcat(buf,s);
|
||||||
|
return buf;
|
||||||
|
}
|
333
util/LLgen/src/main.c
Normal file
333
util/LLgen/src/main.c
Normal file
|
@ -0,0 +1,333 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* main.c
|
||||||
|
* Contains main program, and some error message routines
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "types.h"
|
||||||
|
# include "io.h"
|
||||||
|
# include "extern.h"
|
||||||
|
# include "sets.h"
|
||||||
|
# include "assert.h"
|
||||||
|
|
||||||
|
static string rcsid = "$Header$";
|
||||||
|
|
||||||
|
static string rec_file;
|
||||||
|
static string incl_file;
|
||||||
|
|
||||||
|
/* In this file the following routines are defined: */
|
||||||
|
extern int main();
|
||||||
|
STATIC readgrammar();
|
||||||
|
extern error();
|
||||||
|
extern fatal();
|
||||||
|
extern comfatal();
|
||||||
|
extern copyfile();
|
||||||
|
extern install();
|
||||||
|
# ifndef NDEBUG
|
||||||
|
extern badassertion();
|
||||||
|
# endif not NDEBUG
|
||||||
|
|
||||||
|
main(argc,argv) register string argv[]; {
|
||||||
|
register string arg;
|
||||||
|
string libpath();
|
||||||
|
int nflag = 0;
|
||||||
|
|
||||||
|
/* Initialize */
|
||||||
|
|
||||||
|
maxorder = order;
|
||||||
|
assval = 0400;
|
||||||
|
/* read options */
|
||||||
|
|
||||||
|
while (argc >= 2 && (arg = argv[1], *arg == '-')) {
|
||||||
|
while (*++arg) {
|
||||||
|
switch(*arg) {
|
||||||
|
case 'v':
|
||||||
|
case 'V':
|
||||||
|
verbose++;
|
||||||
|
continue;
|
||||||
|
case 'n':
|
||||||
|
case 'N':
|
||||||
|
nflag++;
|
||||||
|
continue;
|
||||||
|
case 'f':
|
||||||
|
case 'F':
|
||||||
|
fflag++;
|
||||||
|
continue;
|
||||||
|
# ifndef NDEBUG
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
debug++;
|
||||||
|
continue;
|
||||||
|
# endif not NDEBUG
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
if (rec_file) {
|
||||||
|
fprintf(stderr,"duplicate -r flag\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
rec_file = ++arg;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
case 'I':
|
||||||
|
if (incl_file) {
|
||||||
|
fprintf(stderr,"duplicate -i flag\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
incl_file = ++arg;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
ntneeded = 1;
|
||||||
|
ntprint = 1;
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"illegal option : %c\n",*arg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
argv++;
|
||||||
|
argc--;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Now check wether the sets should include nonterminals
|
||||||
|
*/
|
||||||
|
if (verbose == 2) ntneeded = 1;
|
||||||
|
else if (! verbose) ntneeded = 0;
|
||||||
|
/*
|
||||||
|
* Initialise
|
||||||
|
*/
|
||||||
|
if (!rec_file) rec_file = libpath("rec");
|
||||||
|
if (!incl_file) incl_file = libpath("incl");
|
||||||
|
if ((fact = fopen(f_temp,"w")) == NULL) {
|
||||||
|
fputs("Cannot create temporary\n",stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
name_init();
|
||||||
|
readgrammar(argc,argv);
|
||||||
|
if (nflag) comfatal();
|
||||||
|
setinit(ntneeded);
|
||||||
|
maxnt = &nonterms[nnonterms];
|
||||||
|
max_t_ent = &h_entry[nterminals];
|
||||||
|
fclose(fact);
|
||||||
|
/*
|
||||||
|
* Now, the grammar is read. Do some computations
|
||||||
|
*/
|
||||||
|
co_reach(); /* Check for undefined and unreachable */
|
||||||
|
if (nerrors) comfatal();
|
||||||
|
createsets();
|
||||||
|
co_empty(); /* Which nonterminals produce empty? */
|
||||||
|
co_first(); /* Computes first sets */
|
||||||
|
co_follow(); /* Computes follow sets */
|
||||||
|
co_symb(); /* Computes choice sets in alternations */
|
||||||
|
conflchecks(); /* Checks for conflicts etc, and also
|
||||||
|
* takes care of LL.output etc
|
||||||
|
*/
|
||||||
|
if (nerrors) comfatal();
|
||||||
|
co_contains(); /* Computes the contains sets */
|
||||||
|
co_safes(); /* Computes safe terms and nonterminals.
|
||||||
|
* Safe means : always called with a terminal
|
||||||
|
* symbol that is guarantied to be eaten by
|
||||||
|
* the term
|
||||||
|
*/
|
||||||
|
if (argc-- == 1) {
|
||||||
|
fputs("No code generation for input from standard input\n",stderr);
|
||||||
|
} else gencode(argc);
|
||||||
|
UNLINK(f_temp);
|
||||||
|
UNLINK(f_pars);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
readgrammar(argc,argv) char *argv[]; {
|
||||||
|
/*
|
||||||
|
* Do just what the name suggests : read the grammar
|
||||||
|
*/
|
||||||
|
register p_file p;
|
||||||
|
p_mem alloc();
|
||||||
|
|
||||||
|
linecount = 0;
|
||||||
|
f_input = "no filename";
|
||||||
|
/*
|
||||||
|
* Build the file structure
|
||||||
|
*/
|
||||||
|
files = p = (p_file) alloc((unsigned) (argc+1) * sizeof(t_file));
|
||||||
|
if (argc-- == 1) {
|
||||||
|
finput = stdin;
|
||||||
|
p->f_name = f_input = "standard input";
|
||||||
|
p->f_firsts = 0;
|
||||||
|
p->f_start = maxorder;
|
||||||
|
pfile = p;
|
||||||
|
LLparse();
|
||||||
|
p->f_end = maxorder - 1;
|
||||||
|
p++;
|
||||||
|
} else {
|
||||||
|
while (argc--) {
|
||||||
|
if ((finput = fopen(f_input=argv[1],"r")) == NULL) {
|
||||||
|
fatal(0,e_noopen,f_input);
|
||||||
|
}
|
||||||
|
linecount = 0;
|
||||||
|
p->f_name = f_input;
|
||||||
|
p->f_start = maxorder;
|
||||||
|
p->f_firsts = 0;
|
||||||
|
pfile = p;
|
||||||
|
LLparse();
|
||||||
|
p->f_end = maxorder-1;
|
||||||
|
p++;
|
||||||
|
argv++;
|
||||||
|
fclose(finput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p->f_start = maxorder+1;
|
||||||
|
p->f_end = maxorder;
|
||||||
|
if (! lexical) lexical = "yylex";
|
||||||
|
/*
|
||||||
|
* There must be a start symbol!
|
||||||
|
*/
|
||||||
|
if (start == 0) {
|
||||||
|
fatal(linecount,"Missing %%start");
|
||||||
|
}
|
||||||
|
if (nerrors) comfatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* VARARGS1 */
|
||||||
|
error(lineno,s,t,u) string s,t,u; {
|
||||||
|
/*
|
||||||
|
* Just an error message
|
||||||
|
*/
|
||||||
|
register FILE *f;
|
||||||
|
|
||||||
|
f = stderr;
|
||||||
|
++nerrors;
|
||||||
|
if (lineno) fprintf(f,"\"%s\", line %d : ",f_input,lineno);
|
||||||
|
else fprintf(f,"\"%s\" : ",f_input);
|
||||||
|
fprintf(f,s,t,u);
|
||||||
|
putc('\n',f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* VARARGS1 */
|
||||||
|
fatal(lineno,s,t,u) string s,t,u; {
|
||||||
|
/*
|
||||||
|
* Fatal error
|
||||||
|
*/
|
||||||
|
error(lineno,s,t,u);
|
||||||
|
comfatal();
|
||||||
|
}
|
||||||
|
|
||||||
|
comfatal() {
|
||||||
|
/*
|
||||||
|
* Some common code for exit on errors
|
||||||
|
*/
|
||||||
|
if (fact != NULL) {
|
||||||
|
fclose(fact);
|
||||||
|
UNLINK(f_temp);
|
||||||
|
}
|
||||||
|
if (fpars != NULL) fclose(fpars);
|
||||||
|
UNLINK(f_pars);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
copyfile(n) {
|
||||||
|
/*
|
||||||
|
* Copies a file indicated by the parameter to filedescriptor fpars.
|
||||||
|
* If n != 0, the error recovery routines are copied,
|
||||||
|
* otherwise a standard header is.
|
||||||
|
*/
|
||||||
|
register c;
|
||||||
|
register FILE *f;
|
||||||
|
|
||||||
|
if ((f = fopen(n?rec_file:incl_file,"r")) == NULL) {
|
||||||
|
fatal(0,"Cannot open libraryfile, call an expert");
|
||||||
|
}
|
||||||
|
while ((c = getc(f)) != EOF) putc(c,fpars);
|
||||||
|
}
|
||||||
|
|
||||||
|
install(target, source) string target, source; {
|
||||||
|
/*
|
||||||
|
* Copy the temporary file generated from source to target
|
||||||
|
* if allowed (which means that the target must be generated
|
||||||
|
* by LLgen from the source, or that the target is not present
|
||||||
|
*/
|
||||||
|
register c;
|
||||||
|
register FILE *f1;
|
||||||
|
register FILE *f2;
|
||||||
|
register string s1;
|
||||||
|
register int i;
|
||||||
|
char buf[100];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First open temporary, generated for source
|
||||||
|
*/
|
||||||
|
if ((f1 = fopen(f_pars,"r")) == NULL) {
|
||||||
|
fatal(0,e_noopen,f_pars);
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
/*
|
||||||
|
* Now open target for reading
|
||||||
|
*/
|
||||||
|
if ((f2 = fopen(target,"r")) == NULL) {
|
||||||
|
i = 1;
|
||||||
|
fclose(f1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* Create string recognised by LLgen. The target must
|
||||||
|
* start with that!
|
||||||
|
*/
|
||||||
|
(int) sprintf(buf,LLgenid,source ? source : ".");
|
||||||
|
s1 = buf;
|
||||||
|
while (*s1 != '\0' && *s1++ == getc(f2)) { /* nothing */ }
|
||||||
|
/*
|
||||||
|
* Ai,ai, it did not
|
||||||
|
*/
|
||||||
|
if (*s1 != '\0') {
|
||||||
|
fatal(0,"%s : not a file generated by LLgen",target);
|
||||||
|
}
|
||||||
|
rewind(f2);
|
||||||
|
/*
|
||||||
|
* Now compare the target with the temporary
|
||||||
|
*/
|
||||||
|
while ((c = getc(f1)) != EOF && c == getc(f2)) { /* nothing */}
|
||||||
|
if (c != EOF || getc(f2) != EOF) i = 1;
|
||||||
|
fclose(f1);
|
||||||
|
fclose(f2);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Here, if i != 0 the target must be recreated
|
||||||
|
*/
|
||||||
|
if (i) RENAME(f_pars,target);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
badassertion(asstr,file,line) char *asstr, *file; {
|
||||||
|
|
||||||
|
fprintf(stderr,"Assertion \"%s\" failed %s(%d)\n",asstr,file,line);
|
||||||
|
if (fact != NULL) fclose(fact);
|
||||||
|
if (fpars != NULL) fclose(fpars);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif
|
239
util/LLgen/src/name.c
Normal file
239
util/LLgen/src/name.c
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* name.c
|
||||||
|
* Defines the symboltable search routine and an initialising routine
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "types.h"
|
||||||
|
# include "tunable.h"
|
||||||
|
# include "extern.h"
|
||||||
|
# include "assert.h"
|
||||||
|
# include "io.h"
|
||||||
|
|
||||||
|
static string rcsid = "$Header$";
|
||||||
|
|
||||||
|
# define HASHSIZE 128
|
||||||
|
|
||||||
|
static char name[NAMESZ]; /* space for names */
|
||||||
|
static int iname; /* index in nametable */
|
||||||
|
static p_entry h_root[HASHSIZE]; /* hash table */
|
||||||
|
static string e_literal = "Illegal literal";
|
||||||
|
|
||||||
|
/* Defined in this file are: */
|
||||||
|
extern string store();
|
||||||
|
extern name_init();
|
||||||
|
STATIC int hash();
|
||||||
|
extern t_gram search();
|
||||||
|
|
||||||
|
string
|
||||||
|
store(s) register string s; {
|
||||||
|
/*
|
||||||
|
* Store a string s in the name table
|
||||||
|
*/
|
||||||
|
register string t,u;
|
||||||
|
|
||||||
|
u = t = &name[iname];
|
||||||
|
do { if (u > &name[NAMESZ-1]) fatal(linecount,"name table overflow");
|
||||||
|
else *u++ = *s;
|
||||||
|
} while (*s++);
|
||||||
|
iname = u - name;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_init() {
|
||||||
|
/*
|
||||||
|
* Initialise hash-table and enter special terminal EOFILE
|
||||||
|
*/
|
||||||
|
register p_entry *p;
|
||||||
|
t_gram search();
|
||||||
|
|
||||||
|
for(p = h_root; p<= &h_root[HASHSIZE-1]; p++) *p = 0;
|
||||||
|
search(TERMINAL,"EOFILE",ENTERING);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int
|
||||||
|
hash(str) string str; {
|
||||||
|
/*
|
||||||
|
* Compute the hash for string str
|
||||||
|
*/
|
||||||
|
register i;
|
||||||
|
register string l;
|
||||||
|
|
||||||
|
l = str;
|
||||||
|
i = 0;
|
||||||
|
while (*l != '\0') i += *l++ & 0377;
|
||||||
|
i += l - str;
|
||||||
|
return i % HASHSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_gram
|
||||||
|
search(type,str,option) register string str; {
|
||||||
|
/*
|
||||||
|
* Search for object str.
|
||||||
|
* It has type UNKNOWN, LITERAL, TERMINAL or NONTERM.
|
||||||
|
* option can be ENTERING, JUSTLOOKING or BOTH.
|
||||||
|
*/
|
||||||
|
register int val;
|
||||||
|
register p_entry p;
|
||||||
|
t_gram r;
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
g_init(&r);
|
||||||
|
g_setcont(&r,UNDEFINED);
|
||||||
|
r.g_lineno = linecount;
|
||||||
|
i = hash(str);
|
||||||
|
/*
|
||||||
|
* Walk hash chain
|
||||||
|
*/
|
||||||
|
for (p = h_root[i]; p != (p_entry) 0; p = p->h_next) {
|
||||||
|
if(!strcmp(p->h_name,str)) {
|
||||||
|
val = p - h_entry;
|
||||||
|
if (type == LITERAL &&
|
||||||
|
(val >= NTERMINALS || p->h_num >= 0400)) continue;
|
||||||
|
if (val>=NTERMINALS) {
|
||||||
|
/* Should be a nonterminal */
|
||||||
|
if (type == TERMINAL) {
|
||||||
|
error(linecount,
|
||||||
|
"%s : terminal expected",
|
||||||
|
str);
|
||||||
|
}
|
||||||
|
g_settype(&r,NONTERM);
|
||||||
|
g_setnont(&r,val - NTERMINALS);
|
||||||
|
} else {
|
||||||
|
if (type != LITERAL && p->h_num < 0400) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (type == NONTERM) {
|
||||||
|
error(linecount,
|
||||||
|
"%s : nonterminal expected",
|
||||||
|
str);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
g_setnont(&r, val);
|
||||||
|
g_settype(&r, TERMINAL);
|
||||||
|
}
|
||||||
|
if (option==ENTERING) {
|
||||||
|
error(linecount,
|
||||||
|
"%s : already defined",str);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (option == JUSTLOOKING) return r;
|
||||||
|
if (type == TERMINAL || type == LITERAL) {
|
||||||
|
if (nterminals == NTERMINALS) {
|
||||||
|
fatal(linecount,"too many terminals");
|
||||||
|
}
|
||||||
|
p = &h_entry[nterminals];
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* type == NONTERM || type == UNKNOWN
|
||||||
|
* UNKNOWN and not yet declared means : NONTERM
|
||||||
|
*/
|
||||||
|
if (nnonterms == NNONTERMS) {
|
||||||
|
fatal(linecount,"too many nonterminals");
|
||||||
|
}
|
||||||
|
p = &h_entry[NTERMINALS+nnonterms];
|
||||||
|
}
|
||||||
|
p->h_name = store(str);
|
||||||
|
p->h_next = h_root[i];
|
||||||
|
h_root[i] = p;
|
||||||
|
if (type == NONTERM || type == UNKNOWN) {
|
||||||
|
register p_nont q;
|
||||||
|
|
||||||
|
q = &nonterms[nnonterms];
|
||||||
|
q->n_rule = 0;
|
||||||
|
q->n_string = f_input;
|
||||||
|
q->n_follow = 0;
|
||||||
|
q->n_flags = 0;
|
||||||
|
q->n_contains = 0;
|
||||||
|
p->h_num = 0;
|
||||||
|
g_settype(&r, NONTERM);
|
||||||
|
g_setnont(&r, nnonterms);
|
||||||
|
nnonterms++;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
if (type == LITERAL) {
|
||||||
|
if (str[0] == '\\') {
|
||||||
|
/*
|
||||||
|
* Handle escapes in literals
|
||||||
|
*/
|
||||||
|
if (str[2] == '\0') {
|
||||||
|
switch(str[1]) {
|
||||||
|
case 'n' :
|
||||||
|
val = '\n';
|
||||||
|
break;
|
||||||
|
case 'r' :
|
||||||
|
val = '\r';
|
||||||
|
break;
|
||||||
|
case 'b' :
|
||||||
|
val = '\b';
|
||||||
|
break;
|
||||||
|
case 'f' :
|
||||||
|
val = '\f';
|
||||||
|
break;
|
||||||
|
case 't' :
|
||||||
|
val = '\t';
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
val = '\'';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
val = '\\';
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
error(linecount,e_literal);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Here, str[2] != '\0'
|
||||||
|
*/
|
||||||
|
if (str[1] > '3' || str[1] < '0' ||
|
||||||
|
str[2] > '7' || str[2] < '0' ||
|
||||||
|
str[3] > '7' || str[3] < '0' ||
|
||||||
|
str[4] != '\0') error(linecount,e_literal);
|
||||||
|
val = 64*str[1] - 73*'0' + 8*str[2] + str[3];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* No escape in literal
|
||||||
|
*/
|
||||||
|
if (str[1] == '\0') val = str[0];
|
||||||
|
else error(linecount,e_literal);
|
||||||
|
}
|
||||||
|
p->h_num = val;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Here, type = TERMINAL
|
||||||
|
*/
|
||||||
|
p->h_num = assval++;
|
||||||
|
}
|
||||||
|
g_settype(&r, TERMINAL);
|
||||||
|
g_setnont(&r, nterminals);
|
||||||
|
nterminals++;
|
||||||
|
return r;
|
||||||
|
}
|
121
util/LLgen/src/reach.c
Normal file
121
util/LLgen/src/reach.c
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* reach.c
|
||||||
|
* Determine which nonterminals are reachable, and also check that they
|
||||||
|
* are all defined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# include "tunable.h"
|
||||||
|
# include "types.h"
|
||||||
|
# include "extern.h"
|
||||||
|
# include "io.h"
|
||||||
|
# include "assert.h"
|
||||||
|
|
||||||
|
static string rcsid = "$Header$";
|
||||||
|
|
||||||
|
/* In this file the following routines are defined: */
|
||||||
|
extern co_reach();
|
||||||
|
STATIC reachable();
|
||||||
|
STATIC reachwalk();
|
||||||
|
|
||||||
|
co_reach() {
|
||||||
|
/*
|
||||||
|
* Check for undefined or unreachable nonterminals.
|
||||||
|
* An undefined nonterminal is a fatal error!
|
||||||
|
*/
|
||||||
|
register p_nont p;
|
||||||
|
register p_start st;
|
||||||
|
register p_file x = files;
|
||||||
|
register int *s;
|
||||||
|
|
||||||
|
/* Check for undefined nonterminals */
|
||||||
|
for (p = nonterms; p < maxnt; p++) {
|
||||||
|
if (! p->n_rule) {
|
||||||
|
f_input = p->n_string;
|
||||||
|
fatal(p->n_lineno,"nonterminal %s not defined",
|
||||||
|
(min_nt_ent + (p - nonterms))->h_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Walk the grammar rules, starting with the startsymbols
|
||||||
|
* Mark the nonterminals that are encountered with the flag
|
||||||
|
* REACHABLE, and walk their rules, if not done before
|
||||||
|
*/
|
||||||
|
for (st = start; st; st = st->ff_next) reachable(st->ff_nont);
|
||||||
|
/*
|
||||||
|
* Now check for unreachable nonterminals
|
||||||
|
*/
|
||||||
|
for (; x->f_end < maxorder; x++) {
|
||||||
|
f_input = x->f_name;
|
||||||
|
for (s = x->f_start; s <= x->f_end; s++) {
|
||||||
|
p = &nonterms[*s];
|
||||||
|
if (! (p->n_flags & REACHABLE)) {
|
||||||
|
error(p->n_lineno,"nonterminal %s unreachable",
|
||||||
|
(min_nt_ent + (p - nonterms))->h_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
reachable(p) register p_nont p; {
|
||||||
|
/*
|
||||||
|
* Enter the fact that p is reachable, and look for implications
|
||||||
|
*/
|
||||||
|
if (! (p->n_flags & REACHABLE)) {
|
||||||
|
p->n_flags |= REACHABLE;
|
||||||
|
/*
|
||||||
|
* Now walk its grammar rule
|
||||||
|
*/
|
||||||
|
reachwalk(p->n_rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
reachwalk(p) register p_gram p; {
|
||||||
|
/*
|
||||||
|
* Walk through rule p, looking for nonterminals.
|
||||||
|
* The nonterminals found are entered as reachable
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
switch(g_gettype(p)) {
|
||||||
|
case ALTERNATION :
|
||||||
|
reachwalk(((p_link) pentry[g_getcont(p)])->l_rule);
|
||||||
|
break;
|
||||||
|
case TERM :
|
||||||
|
reachwalk(((p_term) pentry[g_getcont(p)])->t_rule);
|
||||||
|
break;
|
||||||
|
case NONTERM :
|
||||||
|
reachable(&nonterms[g_getnont(p)]);
|
||||||
|
break;
|
||||||
|
case EORULE :
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
45
util/LLgen/src/sets.h
Normal file
45
util/LLgen/src/sets.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sets.h $Header$
|
||||||
|
* Some macros that deal with bitsets and their size
|
||||||
|
*/
|
||||||
|
|
||||||
|
# define BITS (8 * sizeof (int))
|
||||||
|
# define IN(a,i) ((a)[(i)/BITS] & (1<<((i) % BITS)))
|
||||||
|
# define NTIN(a,i) ((a)[((i)+tbitset)/BITS]&(1<<((i)%BITS)))
|
||||||
|
# define PUTIN(a,i) ((a)[(i)/BITS] |=(1<<((i) % BITS)))
|
||||||
|
# define NTPUTIN(a,i) ((a)[((i)+tbitset)/BITS]|=(1<<((i)%BITS)))
|
||||||
|
# define NBYTES(n) (((n) + 7) / 8)
|
||||||
|
/*
|
||||||
|
* The next two macros operate on byte counts!
|
||||||
|
*/
|
||||||
|
# define NINTS(n) (((n) + (int) (sizeof(int) - 1)) / (int) sizeof(int))
|
||||||
|
# define ALIGN(n) (NINTS(n) * (int) sizeof (int))
|
||||||
|
|
||||||
|
extern int tbitset;
|
||||||
|
extern p_set *setptr,*maxptr,*topptr;
|
||||||
|
extern int tsetsize,setsize;
|
435
util/LLgen/src/tokens.g
Normal file
435
util/LLgen/src/tokens.g
Normal file
|
@ -0,0 +1,435 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tokens.g
|
||||||
|
* Defines the tokens for the grammar of LLgen.
|
||||||
|
* The lexical analyser and LLmes are also included here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
# include "types.h"
|
||||||
|
# include "io.h"
|
||||||
|
# include "tunable.h"
|
||||||
|
# include "extern.h"
|
||||||
|
# include "assert.h"
|
||||||
|
|
||||||
|
static string rcsid = "$Header$";
|
||||||
|
|
||||||
|
/* Here are defined : */
|
||||||
|
extern int scanner();
|
||||||
|
extern LLmessage();
|
||||||
|
extern int input();
|
||||||
|
extern unput();
|
||||||
|
extern skipcomment();
|
||||||
|
STATIC linedirective();
|
||||||
|
STATIC string cpy();
|
||||||
|
STATIC string vallookup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Classes */
|
||||||
|
|
||||||
|
%token C_IDENT ; /* lextoken.t_string contains the identifier read */
|
||||||
|
%token C_NUMBER ; /* lextoken.t_num contains the number read */
|
||||||
|
%token C_LITERAL ; /* lextoken.t_string contains the literal read */
|
||||||
|
|
||||||
|
/* Keywords */
|
||||||
|
|
||||||
|
%token C_TOKEN ;
|
||||||
|
%token C_START ;
|
||||||
|
%token C_IF ;
|
||||||
|
%token C_WHILE ;
|
||||||
|
%token C_PERSISTENT ;
|
||||||
|
%token C_FIRST ;
|
||||||
|
%token C_LEXICAL ;
|
||||||
|
%token C_AVOID ;
|
||||||
|
%token C_PREFER ;
|
||||||
|
%token C_DEFAULT ;
|
||||||
|
|
||||||
|
%lexical scanner ;
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure for a keyword
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct keyword {
|
||||||
|
string w_word;
|
||||||
|
int w_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The list of keywords, the most often used keywords come first.
|
||||||
|
* Linear search is used, as there are not many keywords
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct keyword resword[] = {
|
||||||
|
{ "token", C_TOKEN },
|
||||||
|
{ "avoid", C_AVOID },
|
||||||
|
{ "prefer", C_PREFER },
|
||||||
|
{ "persistent", C_PERSISTENT },
|
||||||
|
{ "default", C_DEFAULT },
|
||||||
|
{ "if", C_IF },
|
||||||
|
{ "while", C_WHILE },
|
||||||
|
{ "first", C_FIRST },
|
||||||
|
{ "start", C_START },
|
||||||
|
{ "lexical", C_LEXICAL },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static t_token savedtok; /* to save lextoken in case of an insertion */
|
||||||
|
static int nostartline; /* = 0 if at the start of a line */
|
||||||
|
|
||||||
|
scanner() {
|
||||||
|
/*
|
||||||
|
* Lexical analyser, what else
|
||||||
|
*/
|
||||||
|
register ch; /* Current char */
|
||||||
|
register i;
|
||||||
|
register reserved = 0; /* reserved word? */
|
||||||
|
int last; /* Char before current char */
|
||||||
|
|
||||||
|
if (savedtok.t_tokno) { /*
|
||||||
|
* A token has been inserted.
|
||||||
|
* Now deliver the last lextoken again
|
||||||
|
*/
|
||||||
|
lextoken = savedtok;
|
||||||
|
savedtok.t_tokno = 0;
|
||||||
|
return lextoken.t_tokno;
|
||||||
|
}
|
||||||
|
for (;;) { /*
|
||||||
|
* First, skip space, comments, line directives, etc
|
||||||
|
*/
|
||||||
|
do ch = input();
|
||||||
|
while(isspace(ch));
|
||||||
|
if (ch == '/') skipcomment(0);
|
||||||
|
else if (ch == '#' && !nostartline) linedirective();
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Now we have a first character of a token
|
||||||
|
*/
|
||||||
|
switch(ch) {
|
||||||
|
case EOF :
|
||||||
|
return EOF;
|
||||||
|
case '\'': /*
|
||||||
|
* Literal, put it in ltext
|
||||||
|
*/
|
||||||
|
i = 0;
|
||||||
|
for (;;) {
|
||||||
|
last = ch;
|
||||||
|
ch = input();
|
||||||
|
if (ch == '\n' || ch == EOF) {
|
||||||
|
error(linecount,"missing '");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ch == '\'' && last != '\\') break;
|
||||||
|
ltext[i] = ch;
|
||||||
|
if (i < LTEXTSZ - 1) ++i;
|
||||||
|
}
|
||||||
|
ltext[i] = '\0';
|
||||||
|
lextoken.t_string = ltext;
|
||||||
|
return C_LITERAL;
|
||||||
|
case '%' : /*
|
||||||
|
* Start of a reserved word
|
||||||
|
*/
|
||||||
|
reserved = 1;
|
||||||
|
ch = input();
|
||||||
|
/* Fall through */
|
||||||
|
default :
|
||||||
|
i = 0;
|
||||||
|
if (isdigit(ch)) {
|
||||||
|
if (reserved) {
|
||||||
|
error(linecount," A reserved number ?");
|
||||||
|
}
|
||||||
|
while (isdigit(ch)) {
|
||||||
|
i = 10 * i + (ch - '0');
|
||||||
|
ch= input();
|
||||||
|
}
|
||||||
|
lextoken.t_num = i;
|
||||||
|
unput(ch);
|
||||||
|
return C_NUMBER;
|
||||||
|
}
|
||||||
|
if (isalpha(ch) || ch == '_') {
|
||||||
|
do {
|
||||||
|
if (reserved && isupper(ch)) ch += 'a' - 'A';
|
||||||
|
ltext[i] = ch;
|
||||||
|
if (i < LTEXTSZ - 1) ++i;
|
||||||
|
ch = input();
|
||||||
|
} while (isalnum(ch) || ch == '_');
|
||||||
|
} else return ch;
|
||||||
|
unput(ch);
|
||||||
|
}
|
||||||
|
ltext[i] = '\0';
|
||||||
|
if (reserved) { /*
|
||||||
|
* Now search for the keyword
|
||||||
|
*/
|
||||||
|
register struct keyword *w;
|
||||||
|
|
||||||
|
w = resword;
|
||||||
|
while (w->w_word) {
|
||||||
|
if (! strcmp(ltext,w->w_word)) {
|
||||||
|
/*
|
||||||
|
* Found it. Return token number.
|
||||||
|
*/
|
||||||
|
return w->w_value;
|
||||||
|
}
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
error(linecount,"illegal reserved word");
|
||||||
|
}
|
||||||
|
lextoken.t_string = ltext;
|
||||||
|
return C_IDENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int backupc; /* for unput() */
|
||||||
|
static int nonline; /* = 1 if last char read was a newline */
|
||||||
|
|
||||||
|
input() {
|
||||||
|
/*
|
||||||
|
* Low level input routine, used by all other input routines
|
||||||
|
*/
|
||||||
|
register c;
|
||||||
|
register FILE *f;
|
||||||
|
|
||||||
|
if(backupc) { /*
|
||||||
|
* Last char was "unput()". Deliver it again
|
||||||
|
*/
|
||||||
|
c = backupc;
|
||||||
|
backupc = 0;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
f = finput;
|
||||||
|
if ((c = getc(f)) == EOF) return c;
|
||||||
|
nostartline = 1;
|
||||||
|
if (!nonline) {
|
||||||
|
linecount++;
|
||||||
|
nostartline = 0;
|
||||||
|
nonline = 1;
|
||||||
|
}
|
||||||
|
if (c == ' ' || c == '\t') { /*
|
||||||
|
* Deliver space, but only once
|
||||||
|
*/
|
||||||
|
do c = getc(f);
|
||||||
|
while (c == ' ' || c == '\t');
|
||||||
|
ungetc(c,f);
|
||||||
|
return ' ';
|
||||||
|
}
|
||||||
|
if (c == '\n') nonline = 0;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
unput(c) {
|
||||||
|
/*
|
||||||
|
* "unread" c
|
||||||
|
*/
|
||||||
|
backupc = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
skipcomment(flag) {
|
||||||
|
/*
|
||||||
|
* Skip comment. If flag != 0, the comment is inside a fragment
|
||||||
|
* of C-code, so the newlines in it must be copied to enable the
|
||||||
|
* C-compiler to keep a correct line count
|
||||||
|
*/
|
||||||
|
register ch;
|
||||||
|
int saved; /* line count on which comment starts */
|
||||||
|
|
||||||
|
saved = linecount;
|
||||||
|
if (input() != '*') error(linecount,"illegal comment");
|
||||||
|
ch = input();
|
||||||
|
while (ch != EOF) {
|
||||||
|
if (flag && ch == '\n') putc(ch,fact);
|
||||||
|
while (ch == '*') {
|
||||||
|
if ((ch = input()) == '/') return;
|
||||||
|
if (flag && ch == '\n') putc(ch,fact);
|
||||||
|
}
|
||||||
|
ch = input();
|
||||||
|
}
|
||||||
|
error(saved,"Comment does not terminate");
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC
|
||||||
|
linedirective() {
|
||||||
|
/*
|
||||||
|
* Read a line directive
|
||||||
|
*/
|
||||||
|
register ch;
|
||||||
|
register i;
|
||||||
|
string s_error = "Illegal line directive";
|
||||||
|
string store();
|
||||||
|
register string c;
|
||||||
|
|
||||||
|
do { /*
|
||||||
|
* Skip to next digit
|
||||||
|
* Do not skip newlines
|
||||||
|
*/
|
||||||
|
ch = input();
|
||||||
|
} while (ch != '\n' && ! isdigit(ch));
|
||||||
|
if (ch == '\n') {
|
||||||
|
error(linecount,s_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i = ch - '0';
|
||||||
|
ch = input();
|
||||||
|
while (isdigit(ch)) {
|
||||||
|
i = i*10 + (ch - '0');
|
||||||
|
ch = input();
|
||||||
|
}
|
||||||
|
while (ch != '\n' && ch != '"') ch = input();
|
||||||
|
if (ch == '"') {
|
||||||
|
c = ltext;
|
||||||
|
do {
|
||||||
|
*c++ = ch = input();
|
||||||
|
} while (ch != '"' && ch != '\n');
|
||||||
|
if (ch == '\n') {
|
||||||
|
error(linecount,s_error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*--c = '\0';
|
||||||
|
do {
|
||||||
|
ch = input();
|
||||||
|
} while (ch != '\n');
|
||||||
|
/*
|
||||||
|
* Remember the file name
|
||||||
|
*/
|
||||||
|
if (strcmp(f_input,ltext)) f_input = store(ltext);
|
||||||
|
}
|
||||||
|
linecount = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC string
|
||||||
|
vallookup(s) {
|
||||||
|
/*
|
||||||
|
* Look up the keyword that has token number s
|
||||||
|
*/
|
||||||
|
register struct keyword *p = resword;
|
||||||
|
|
||||||
|
while (p->w_value) {
|
||||||
|
if (p->w_value == s) return p->w_word;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC string
|
||||||
|
cpy(s,p,flag) register s; register string p; {
|
||||||
|
/*
|
||||||
|
* Create a piece of error message for token s and put it at p.
|
||||||
|
* flag = 0 if the token s was deleted (in which case we have
|
||||||
|
* attributes), else it was inserted
|
||||||
|
*/
|
||||||
|
register string t = 0;
|
||||||
|
|
||||||
|
switch(s) {
|
||||||
|
case C_IDENT :
|
||||||
|
if (!flag) t = lextoken.t_string;
|
||||||
|
else t = "identifier";
|
||||||
|
break;
|
||||||
|
case C_NUMBER :
|
||||||
|
t = "number";
|
||||||
|
break;
|
||||||
|
case C_LITERAL :
|
||||||
|
if (!flag) {
|
||||||
|
*p++ = '"';
|
||||||
|
*p++ = '\'';
|
||||||
|
t = lextoken.t_string;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
t = "literal";
|
||||||
|
break;
|
||||||
|
case EOFILE :
|
||||||
|
t = "endoffile";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!t) {
|
||||||
|
t = vallookup(s);
|
||||||
|
if (t) {
|
||||||
|
*p++ = '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t) { /*
|
||||||
|
* We have a string for the token. Copy it
|
||||||
|
*/
|
||||||
|
while (*t) *p++ = *t++;
|
||||||
|
if (s == C_LITERAL && !flag) {
|
||||||
|
*p++ = '\'';
|
||||||
|
*p++ = '"';
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* The token is a literal
|
||||||
|
*/
|
||||||
|
*p++ = '\'';
|
||||||
|
if (s >= 040 && s <= 0176) *p++ = s;
|
||||||
|
else switch(s) {
|
||||||
|
case '\b' : *p++ = '\\'; *p++ = 'b'; break;
|
||||||
|
case '\f' : *p++ = '\\'; *p++ = 'f'; break;
|
||||||
|
case '\n' : *p++ = '\\'; *p++ = 'n'; break;
|
||||||
|
case '\r' : *p++ = '\\'; *p++ = 'r'; break;
|
||||||
|
case '\t' : *p++ = '\\'; *p++ = 't'; break;
|
||||||
|
default : *p++='0'+((s&0377)>>6); *p++='0'+((s>>3)&07);
|
||||||
|
*p++='0'+(s&07);
|
||||||
|
}
|
||||||
|
*p++ = '\'';
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLmessage(d) {
|
||||||
|
/*
|
||||||
|
* d is either 0, in which case the current token has been deleted,
|
||||||
|
* or non-zero, in which case it represents a token that is inserted
|
||||||
|
* before the current token
|
||||||
|
*/
|
||||||
|
register string s,t;
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
|
nerrors++;
|
||||||
|
s = buf;
|
||||||
|
if (d == 0) {
|
||||||
|
s = cpy(LLsymb,s,0);
|
||||||
|
t = " deleted";
|
||||||
|
do *s++ = *t; while (*t++);
|
||||||
|
} else {
|
||||||
|
s = cpy(d,s,1);
|
||||||
|
t = " inserted in front of ";
|
||||||
|
do *s++ = *t++; while (*t);
|
||||||
|
s = cpy(LLsymb,s,0);
|
||||||
|
*s = '\0';
|
||||||
|
}
|
||||||
|
error(linecount,buf);
|
||||||
|
if (d) { /*
|
||||||
|
* Save the current token and make up some
|
||||||
|
* attributes for the inserted token
|
||||||
|
*/
|
||||||
|
savedtok = lextoken;
|
||||||
|
if (d == C_IDENT) lextoken.t_string = "dummy_identifier";
|
||||||
|
else if (d == C_LITERAL) lextoken.t_string = "dummy_literal";
|
||||||
|
else if (d == C_NUMBER) lextoken.t_num = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
util/LLgen/src/tunable.h
Normal file
35
util/LLgen/src/tunable.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
*
|
||||||
|
* This product is part of the Amsterdam Compiler Kit.
|
||||||
|
*
|
||||||
|
* Permission to use, sell, duplicate or disclose this software must be
|
||||||
|
* obtained in writing. Requests for such permissions may be sent to
|
||||||
|
*
|
||||||
|
* Dr. Andrew S. Tanenbaum
|
||||||
|
* Wiskundig Seminarium
|
||||||
|
* Vrije Universiteit
|
||||||
|
* Postbox 7161
|
||||||
|
* 1007 MC Amsterdam
|
||||||
|
* The Netherlands
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* L L G E N
|
||||||
|
*
|
||||||
|
* An Extended LL(1) Parser Generator
|
||||||
|
*
|
||||||
|
* Author : Ceriel J.H. Jacobs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tunable.h $Header$
|
||||||
|
* Tunable constants
|
||||||
|
*/
|
||||||
|
|
||||||
|
# define NNONTERMS 150 /* size of nonterminal array */
|
||||||
|
# define NTERMINALS 150 /* size of terminal array */
|
||||||
|
# define NAMESZ 3000 /* size of name table */
|
||||||
|
# define LTEXTSZ 51 /* size of token */
|
||||||
|
# define ENTSIZ 900 /* size of entry table, max 8191 */
|
Loading…
Add table
Reference in a new issue