mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
Plan 9 lex (to be installed as lex.9, if at all).
This commit is contained in:
parent
7d3bbe1652
commit
e37302c4b9
8 changed files with 2903 additions and 0 deletions
115
src/cmd/lex/header.c
Normal file
115
src/cmd/lex/header.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
# include "ldefs.h"
|
||||
|
||||
extern int nine;
|
||||
|
||||
void
|
||||
phead1(void)
|
||||
{
|
||||
Bprint(&fout,"typedef unsigned char Uchar;\n");
|
||||
if (nine) {
|
||||
Bprint(&fout,"# include <u.h>\n");
|
||||
Bprint(&fout,"# include <libc.h>\n");
|
||||
}
|
||||
Bprint(&fout,"# include <stdio.h>\n");
|
||||
Bprint(&fout, "# define U(x) x\n");
|
||||
Bprint(&fout, "# define NLSTATE yyprevious=YYNEWLINE\n");
|
||||
Bprint(&fout,"# define BEGIN yybgin = yysvec + 1 +\n");
|
||||
Bprint(&fout,"# define INITIAL 0\n");
|
||||
Bprint(&fout,"# define YYLERR yysvec\n");
|
||||
Bprint(&fout,"# define YYSTATE (yyestate-yysvec-1)\n");
|
||||
Bprint(&fout,"# define YYOPTIM 1\n");
|
||||
# ifdef DEBUG
|
||||
Bprint(&fout,"# define LEXDEBUG 1\n");
|
||||
# endif
|
||||
Bprint(&fout,"# define YYLMAX 200\n");
|
||||
Bprint(&fout,
|
||||
"# define unput(c) {yytchar= (c);if(yytchar=='\\n')yylineno--;*yysptr++=yytchar;}\n");
|
||||
Bprint(&fout,"# define yymore() (yymorfg=1)\n");
|
||||
Bprint(&fout,"# define ECHO fprintf(yyout, \"%%s\",yytext)\n");
|
||||
Bprint(&fout,"# define REJECT { nstr = yyreject(); goto yyfussy;}\n");
|
||||
Bprint(&fout,"int yyleng; extern char yytext[];\n");
|
||||
Bprint(&fout,"int yymorfg;\n");
|
||||
Bprint(&fout,"extern Uchar *yysptr, yysbuf[];\n");
|
||||
Bprint(&fout,"int yytchar;\n");
|
||||
// Bprint(&fout,"FILE *yyin = stdin, *yyout = stdout;\n");
|
||||
Bprint(&fout,"FILE *yyin, *yyout;\n");
|
||||
Bprint(&fout,"extern int yylineno;\n");
|
||||
Bprint(&fout,"struct yysvf { \n");
|
||||
Bprint(&fout,"\tstruct yywork *yystoff;\n");
|
||||
Bprint(&fout,"\tstruct yysvf *yyother;\n");
|
||||
Bprint(&fout,"\tint *yystops;};\n");
|
||||
Bprint(&fout,"struct yysvf *yyestate;\n");
|
||||
Bprint(&fout,"extern struct yysvf yysvec[], *yybgin;\n");
|
||||
Bprint(&fout,"int yylook(void), yywrap(void), yyback(int *, int);\n");
|
||||
if(nine) {
|
||||
Bprint(&fout,
|
||||
"int infd, outfd;\n"
|
||||
"\n"
|
||||
"void\n"
|
||||
"output(char c)\n"
|
||||
"{\n"
|
||||
" int rv;\n"
|
||||
" if ((rv = write(outfd, &c, 1)) < 0)\n"
|
||||
" sysfatal(\"output: %%r\");\n"
|
||||
" if (rv == 0)\n"
|
||||
" sysfatal(\"output: EOF?\");\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"int\n"
|
||||
"input(void)\n"
|
||||
"{\n"
|
||||
" if(yysptr > yysbuf)\n"
|
||||
" yytchar = U(*--yysptr);\n"
|
||||
" else {\n"
|
||||
" int rv;\n"
|
||||
" if ((rv = read(infd, &yytchar, 1)) < 0)\n"
|
||||
" sysfatal(\"input: %%r\");\n"
|
||||
" if (rv == 0)\n"
|
||||
" return 0;\n"
|
||||
" }\n"
|
||||
" if (yytchar == '\\n')\n"
|
||||
" yylineno++;\n"
|
||||
" return yytchar;\n"
|
||||
"}\n");
|
||||
}
|
||||
else {
|
||||
Bprint(&fout,"# define output(c) putc(c,yyout)\n");
|
||||
Bprint(&fout, "%s%d%s\n",
|
||||
"# define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==",
|
||||
'\n',
|
||||
"?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
phead2(void)
|
||||
{
|
||||
Bprint(&fout,"while((nstr = yylook()) >= 0)\n");
|
||||
Bprint(&fout,"yyfussy: switch(nstr){\n");
|
||||
Bprint(&fout,"case 0:\n");
|
||||
Bprint(&fout,"if(yywrap()) return(0); break;\n");
|
||||
}
|
||||
|
||||
void
|
||||
ptail(void)
|
||||
{
|
||||
if(!pflag){
|
||||
Bprint(&fout,"case -1:\nbreak;\n"); /* for reject */
|
||||
Bprint(&fout,"default:\n");
|
||||
Bprint(&fout,"fprintf(yyout,\"bad switch yylook %%d\",nstr);\n");
|
||||
Bprint(&fout,"} return(0); }\n");
|
||||
Bprint(&fout,"/* end of yylex */\n");
|
||||
}
|
||||
pflag = 1;
|
||||
}
|
||||
|
||||
void
|
||||
statistics(void)
|
||||
{
|
||||
fprint(errorf,"%d/%d nodes(%%e), %d/%d positions(%%p), %d/%d (%%n), %ld transitions\n",
|
||||
tptr, treesize, (int)(nxtpos-positions), maxpos, stnum+1, nstates, rcount);
|
||||
fprint(errorf, ", %d/%d packed char classes(%%k)", (int)(pcptr-pchar), pchlen);
|
||||
fprint(errorf,", %d/%d packed transitions(%%a)",nptr, ntrans);
|
||||
fprint(errorf, ", %d/%d output slots(%%o)", yytop, outsize);
|
||||
fprint(errorf,"\n");
|
||||
}
|
180
src/cmd/lex/ldefs.h
Normal file
180
src/cmd/lex/ldefs.h
Normal file
|
@ -0,0 +1,180 @@
|
|||
# include <u.h>
|
||||
# include <libc.h>
|
||||
# include <ctype.h>
|
||||
# include <bio.h>
|
||||
# define PP 1
|
||||
|
||||
#ifdef NOTDEF
|
||||
# define CWIDTH 8
|
||||
# define CMASK 0377
|
||||
#endif
|
||||
# define NCH 256
|
||||
|
||||
|
||||
# define TOKENSIZE 1000
|
||||
# define DEFSIZE 40
|
||||
# define DEFCHAR 1000
|
||||
# define STARTCHAR 100
|
||||
# define STARTSIZE 256
|
||||
# define CCLSIZE 1000
|
||||
|
||||
# define TREESIZE 1000
|
||||
# define NSTATES 500
|
||||
# define MAXPOS 2500
|
||||
# define NTRANS 2000
|
||||
# define NOUTPUT 5000
|
||||
|
||||
# define NACTIONS 100
|
||||
# define ALITTLEEXTRA 30
|
||||
|
||||
# define RCCL NCH+90
|
||||
# define RNCCL NCH+91
|
||||
# define RSTR NCH+92
|
||||
# define RSCON NCH+93
|
||||
# define RNEWE NCH+94
|
||||
# define FINAL NCH+95
|
||||
# define RNULLS NCH+96
|
||||
# define RCAT NCH+97
|
||||
# define STAR NCH+98
|
||||
# define PLUS NCH+99
|
||||
# define QUEST NCH+100
|
||||
# define DIV NCH+101
|
||||
# define BAR NCH+102
|
||||
# define CARAT NCH+103
|
||||
# define S1FINAL NCH+104
|
||||
# define S2FINAL NCH+105
|
||||
|
||||
# define DEFSECTION 1
|
||||
# define RULESECTION 2
|
||||
# define ENDSECTION 5
|
||||
# define TRUE 1
|
||||
# define FALSE 0
|
||||
|
||||
# define PC 1
|
||||
# define PS 1
|
||||
|
||||
# ifdef DEBUG
|
||||
# define LINESIZE 110
|
||||
extern int yydebug;
|
||||
extern int debug; /* 1 = on */
|
||||
extern int charc;
|
||||
# endif
|
||||
|
||||
# ifdef DEBUG
|
||||
extern int freturn(int);
|
||||
# else
|
||||
# define freturn(s) s
|
||||
# endif
|
||||
|
||||
extern int sargc;
|
||||
extern char **sargv;
|
||||
extern uchar buf[520];
|
||||
extern int yyline; /* line number of file */
|
||||
extern int sect;
|
||||
extern int eof;
|
||||
extern int lgatflg;
|
||||
extern int divflg;
|
||||
extern int funcflag;
|
||||
extern int pflag;
|
||||
extern int casecount;
|
||||
extern int chset; /* 1 = char set modified */
|
||||
extern Biobuf *fin, fout, *fother;
|
||||
extern int foutopen;
|
||||
extern int errorf;
|
||||
extern int fptr;
|
||||
extern char *cname;
|
||||
extern int prev; /* previous input character */
|
||||
extern int pres; /* present input character */
|
||||
extern int peek; /* next input character */
|
||||
extern int *name;
|
||||
extern int *left;
|
||||
extern int *right;
|
||||
extern int *parent;
|
||||
extern uchar *nullstr;
|
||||
extern int tptr;
|
||||
extern uchar pushc[TOKENSIZE];
|
||||
extern uchar *pushptr;
|
||||
extern uchar slist[STARTSIZE];
|
||||
extern uchar *slptr;
|
||||
extern uchar **def, **subs, *dchar;
|
||||
extern uchar **sname, *stchar;
|
||||
extern uchar *ccl;
|
||||
extern uchar *ccptr;
|
||||
extern uchar *dp, *sp;
|
||||
extern int dptr, sptr;
|
||||
extern uchar *bptr; /* store input position */
|
||||
extern uchar *tmpstat;
|
||||
extern int count;
|
||||
extern int **foll;
|
||||
extern int *nxtpos;
|
||||
extern int *positions;
|
||||
extern int *gotof;
|
||||
extern int *nexts;
|
||||
extern uchar *nchar;
|
||||
extern int **state;
|
||||
extern int *sfall; /* fallback state num */
|
||||
extern uchar *cpackflg; /* true if state has been character packed */
|
||||
extern int *atable, aptr;
|
||||
extern int nptr;
|
||||
extern uchar symbol[NCH];
|
||||
extern uchar cindex[NCH];
|
||||
extern int xstate;
|
||||
extern int stnum;
|
||||
extern int ccount;
|
||||
extern uchar match[NCH];
|
||||
extern uchar extra[NACTIONS];
|
||||
extern uchar *pcptr, *pchar;
|
||||
extern int pchlen;
|
||||
extern int nstates, maxpos;
|
||||
extern int yytop;
|
||||
extern int report;
|
||||
extern int ntrans, treesize, outsize;
|
||||
extern long rcount;
|
||||
extern int *verify, *advance, *stoff;
|
||||
extern int scon;
|
||||
extern uchar *psave;
|
||||
|
||||
extern void acompute(int);
|
||||
extern void add(int **, int);
|
||||
extern void allprint(int);
|
||||
extern void cclinter(int);
|
||||
extern void cgoto(void);
|
||||
extern void cfoll(int);
|
||||
extern int cpyact(void);
|
||||
extern int dupl(int);
|
||||
extern void error(char *,...);
|
||||
extern void first(int);
|
||||
extern void follow(int);
|
||||
extern int gch(void);
|
||||
extern uchar *getl(uchar *);
|
||||
extern void layout(void);
|
||||
extern void lgate(void);
|
||||
extern int lookup(uchar *, uchar **);
|
||||
extern int member(int, uchar *);
|
||||
extern void mkmatch(void);
|
||||
extern int mn0(int);
|
||||
extern int mn1(int, int);
|
||||
extern int mn2(int, int, int);
|
||||
extern void munputc(int);
|
||||
extern void munputs(uchar *);
|
||||
extern void *myalloc(int, int);
|
||||
extern void nextstate(int, int);
|
||||
extern int notin(int);
|
||||
extern void packtrans(int, uchar *, int *, int, int);
|
||||
extern void padd(int **, int);
|
||||
extern void pccl(void);
|
||||
extern void pfoll(void);
|
||||
extern void phead1(void);
|
||||
extern void phead2(void);
|
||||
extern void pstate(int);
|
||||
extern void ptail(void);
|
||||
extern void sect1dump(void);
|
||||
extern void sect2dump(void);
|
||||
extern void statistics(void);
|
||||
extern void stprt(int);
|
||||
extern void strpt(uchar *);
|
||||
extern void treedump(void);
|
||||
extern int usescape(int);
|
||||
extern void warning(char *,...);
|
||||
extern int yyparse(void);
|
||||
extern void yyerror(char *);
|
292
src/cmd/lex/lmain.c
Normal file
292
src/cmd/lex/lmain.c
Normal file
|
@ -0,0 +1,292 @@
|
|||
/* lex [-[dynvt]] [file] ... [file] */
|
||||
|
||||
/* Copyright 1976, Bell Telephone Laboratories, Inc.,
|
||||
written by Eric Schmidt, August 27, 1976 */
|
||||
|
||||
# include "ldefs.h"
|
||||
Biobuf fout;
|
||||
int foutopen;
|
||||
int errorf = 1;
|
||||
int sect = DEFSECTION;
|
||||
int prev = '\n'; /* previous input character */
|
||||
int pres = '\n'; /* present input character */
|
||||
int peek = '\n'; /* next input character */
|
||||
uchar *pushptr = pushc;
|
||||
uchar *slptr = slist;
|
||||
|
||||
char *cname = SYS9 "/sys/lib/lex/ncform";
|
||||
|
||||
int nine;
|
||||
int ccount = 1;
|
||||
int casecount = 1;
|
||||
int aptr = 1;
|
||||
int nstates = NSTATES, maxpos = MAXPOS;
|
||||
int treesize = TREESIZE, ntrans = NTRANS;
|
||||
int yytop;
|
||||
int outsize = NOUTPUT;
|
||||
int sptr = 1;
|
||||
int report = 2;
|
||||
int debug; /* 1 = on */
|
||||
int charc;
|
||||
int sargc;
|
||||
char **sargv;
|
||||
uchar buf[520];
|
||||
int yyline; /* line number of file */
|
||||
int eof;
|
||||
int lgatflg;
|
||||
int divflg;
|
||||
int funcflag;
|
||||
int pflag;
|
||||
int chset; /* 1 = char set modified */
|
||||
Biobuf *fin, *fother;
|
||||
int fptr;
|
||||
int *name;
|
||||
int *left;
|
||||
int *right;
|
||||
int *parent;
|
||||
uchar *nullstr;
|
||||
int tptr;
|
||||
uchar pushc[TOKENSIZE];
|
||||
uchar slist[STARTSIZE];
|
||||
uchar **def, **subs, *dchar;
|
||||
uchar **sname, *stchar;
|
||||
uchar *ccl;
|
||||
uchar *ccptr;
|
||||
uchar *dp, *sp;
|
||||
int dptr;
|
||||
uchar *bptr; /* store input position */
|
||||
uchar *tmpstat;
|
||||
int count;
|
||||
int **foll;
|
||||
int *nxtpos;
|
||||
int *positions;
|
||||
int *gotof;
|
||||
int *nexts;
|
||||
uchar *nchar;
|
||||
int **state;
|
||||
int *sfall; /* fallback state num */
|
||||
uchar *cpackflg; /* true if state has been character packed */
|
||||
int *atable;
|
||||
int nptr;
|
||||
uchar symbol[NCH];
|
||||
uchar cindex[NCH];
|
||||
int xstate;
|
||||
int stnum;
|
||||
uchar match[NCH];
|
||||
uchar extra[NACTIONS];
|
||||
uchar *pchar, *pcptr;
|
||||
int pchlen = TOKENSIZE;
|
||||
long rcount;
|
||||
int *verify, *advance, *stoff;
|
||||
int scon;
|
||||
uchar *psave;
|
||||
|
||||
static void free1core(void);
|
||||
static void free2core(void);
|
||||
#ifdef DEBUG
|
||||
static void free3core(void);
|
||||
#endif
|
||||
static void get1core(void);
|
||||
static void get2core(void);
|
||||
static void get3core(void);
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
ARGBEGIN {
|
||||
# ifdef DEBUG
|
||||
case 'd': debug++; break;
|
||||
case 'y': yydebug = TRUE; break;
|
||||
# endif
|
||||
case 't': case 'T':
|
||||
Binit(&fout, 1, OWRITE);
|
||||
errorf= 2;
|
||||
foutopen = 1;
|
||||
break;
|
||||
case 'v': case 'V':
|
||||
report = 1;
|
||||
break;
|
||||
case 'n': case 'N':
|
||||
report = 0;
|
||||
break;
|
||||
case '9':
|
||||
nine = 1;
|
||||
break;
|
||||
default:
|
||||
warning("Unknown option %c", ARGC());
|
||||
} ARGEND
|
||||
sargc = argc;
|
||||
sargv = argv;
|
||||
if (argc > 0){
|
||||
fin = Bopen(argv[fptr++], OREAD);
|
||||
if(fin == 0)
|
||||
error ("Can't read input file %s",argv[0]);
|
||||
sargc--;
|
||||
sargv++;
|
||||
}
|
||||
else {
|
||||
fin = myalloc(sizeof(Biobuf), 1);
|
||||
if(fin == 0)
|
||||
exits("core");
|
||||
Binit(fin, 0, OREAD);
|
||||
}
|
||||
if(Bgetc(fin) == Beof) /* no input */
|
||||
exits(0);
|
||||
Bseek(fin, 0, 0);
|
||||
gch();
|
||||
/* may be gotten: def, subs, sname, stchar, ccl, dchar */
|
||||
get1core();
|
||||
/* may be gotten: name, left, right, nullstr, parent */
|
||||
strcpy((char*)sp, "INITIAL");
|
||||
sname[0] = sp;
|
||||
sp += strlen("INITIAL") + 1;
|
||||
sname[1] = 0;
|
||||
if(yyparse()) exits("error"); /* error return code */
|
||||
/* may be disposed of: def, subs, dchar */
|
||||
free1core();
|
||||
/* may be gotten: tmpstat, foll, positions, gotof, nexts, nchar, state, atable, sfall, cpackflg */
|
||||
get2core();
|
||||
ptail();
|
||||
mkmatch();
|
||||
# ifdef DEBUG
|
||||
if(debug) pccl();
|
||||
# endif
|
||||
sect = ENDSECTION;
|
||||
if(tptr>0)cfoll(tptr-1);
|
||||
# ifdef DEBUG
|
||||
if(debug)pfoll();
|
||||
# endif
|
||||
cgoto();
|
||||
# ifdef DEBUG
|
||||
if(debug){
|
||||
print("Print %d states:\n",stnum+1);
|
||||
for(i=0;i<=stnum;i++)stprt(i);
|
||||
}
|
||||
# endif
|
||||
/* may be disposed of: positions, tmpstat, foll, state, name, left, right, parent, ccl, stchar, sname */
|
||||
/* may be gotten: verify, advance, stoff */
|
||||
free2core();
|
||||
get3core();
|
||||
layout();
|
||||
/* may be disposed of: verify, advance, stoff, nexts, nchar,
|
||||
gotof, atable, ccpackflg, sfall */
|
||||
# ifdef DEBUG
|
||||
free3core();
|
||||
# endif
|
||||
fother = Bopen(cname,OREAD);
|
||||
if(fother == 0)
|
||||
error("Lex driver missing, file %s",cname);
|
||||
while ( (i=Bgetc(fother)) != Beof)
|
||||
Bputc(&fout, i);
|
||||
|
||||
Bterm(fother);
|
||||
Bterm(&fout);
|
||||
if(
|
||||
# ifdef DEBUG
|
||||
debug ||
|
||||
# endif
|
||||
report == 1)statistics();
|
||||
Bterm(fin);
|
||||
exits(0); /* success return code */
|
||||
}
|
||||
|
||||
static void
|
||||
get1core(void)
|
||||
{
|
||||
ccptr = ccl = myalloc(CCLSIZE,sizeof(*ccl));
|
||||
pcptr = pchar = myalloc(pchlen, sizeof(*pchar));
|
||||
def = myalloc(DEFSIZE,sizeof(*def));
|
||||
subs = myalloc(DEFSIZE,sizeof(*subs));
|
||||
dp = dchar = myalloc(DEFCHAR,sizeof(*dchar));
|
||||
sname = myalloc(STARTSIZE,sizeof(*sname));
|
||||
sp = stchar = myalloc(STARTCHAR,sizeof(*stchar));
|
||||
if(ccl == 0 || def == 0 || subs == 0 || dchar == 0 || sname == 0 || stchar == 0)
|
||||
error("Too little core to begin");
|
||||
}
|
||||
|
||||
static void
|
||||
free1core(void)
|
||||
{
|
||||
free(def);
|
||||
free(subs);
|
||||
free(dchar);
|
||||
}
|
||||
|
||||
static void
|
||||
get2core(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
gotof = myalloc(nstates,sizeof(*gotof));
|
||||
nexts = myalloc(ntrans,sizeof(*nexts));
|
||||
nchar = myalloc(ntrans,sizeof(*nchar));
|
||||
state = myalloc(nstates,sizeof(*state));
|
||||
atable = myalloc(nstates,sizeof(*atable));
|
||||
sfall = myalloc(nstates,sizeof(*sfall));
|
||||
cpackflg = myalloc(nstates,sizeof(*cpackflg));
|
||||
tmpstat = myalloc(tptr+1,sizeof(*tmpstat));
|
||||
foll = myalloc(tptr+1,sizeof(*foll));
|
||||
nxtpos = positions = myalloc(maxpos,sizeof(*positions));
|
||||
if(tmpstat == 0 || foll == 0 || positions == 0 ||
|
||||
gotof == 0 || nexts == 0 || nchar == 0 || state == 0 || atable == 0 || sfall == 0 || cpackflg == 0 )
|
||||
error("Too little core for state generation");
|
||||
for(i=0;i<=tptr;i++)foll[i] = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free2core(void)
|
||||
{
|
||||
free(positions);
|
||||
free(tmpstat);
|
||||
free(foll);
|
||||
free(name);
|
||||
free(left);
|
||||
free(right);
|
||||
free(parent);
|
||||
free(nullstr);
|
||||
free(state);
|
||||
free(sname);
|
||||
free(stchar);
|
||||
free(ccl);
|
||||
}
|
||||
|
||||
static void
|
||||
get3core(void)
|
||||
{
|
||||
verify = myalloc(outsize,sizeof(*verify));
|
||||
advance = myalloc(outsize,sizeof(*advance));
|
||||
stoff = myalloc(stnum+2,sizeof(*stoff));
|
||||
if(verify == 0 || advance == 0 || stoff == 0)
|
||||
error("Too little core for final packing");
|
||||
}
|
||||
# ifdef DEBUG
|
||||
static void
|
||||
free3core(void){
|
||||
free(advance);
|
||||
free(verify);
|
||||
free(stoff);
|
||||
free(gotof);
|
||||
free(nexts);
|
||||
free(nchar);
|
||||
free(atable);
|
||||
free(sfall);
|
||||
free(cpackflg);
|
||||
}
|
||||
# endif
|
||||
void *
|
||||
myalloc(int a, int b)
|
||||
{
|
||||
void *i;
|
||||
i = calloc(a, b);
|
||||
if(i==0)
|
||||
warning("OOPS - calloc returns a 0");
|
||||
return(i);
|
||||
}
|
||||
|
||||
void
|
||||
yyerror(char *s)
|
||||
{
|
||||
fprint(2, "line %d: %s\n", yyline, s);
|
||||
}
|
30
src/cmd/lex/mkfile
Normal file
30
src/cmd/lex/mkfile
Normal file
|
@ -0,0 +1,30 @@
|
|||
<$PLAN9/src/mkhdr
|
||||
|
||||
#TARG=lex
|
||||
TARG=lex.9
|
||||
OFILES=lmain.$O\
|
||||
y.tab.$O\
|
||||
sub1.$O\
|
||||
sub2.$O\
|
||||
header.$O\
|
||||
|
||||
HFILES=ldefs.h\
|
||||
|
||||
YFILES=parser.y\
|
||||
|
||||
SHORTLIB=bio 9
|
||||
UPDATE=\
|
||||
mkfile\
|
||||
$HFILES\
|
||||
lmain.c\
|
||||
sub1.c\
|
||||
sub2.c\
|
||||
header.c
|
||||
|
||||
<$PLAN9/src/mkone
|
||||
|
||||
installall:V:
|
||||
for objtype in $CPUS ; do
|
||||
mk install
|
||||
done
|
||||
cp ncform $SYS9/lib/lex
|
188
src/cmd/lex/ncform
Normal file
188
src/cmd/lex/ncform
Normal file
|
@ -0,0 +1,188 @@
|
|||
#pragma lib "libl.a"
|
||||
int yylineno =1;
|
||||
# define YYU(x) x
|
||||
char yytext[YYLMAX];
|
||||
struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp;
|
||||
Uchar yysbuf[YYLMAX];
|
||||
Uchar *yysptr = yysbuf;
|
||||
int *yyfnd;
|
||||
extern struct yysvf *yyestate;
|
||||
int yyprevious = YYNEWLINE;
|
||||
# ifdef LEXDEBUG
|
||||
extern void allprint(char);
|
||||
# endif
|
||||
yylook(void){
|
||||
struct yysvf *yystate, **lsp;
|
||||
struct yywork *yyt;
|
||||
struct yysvf *yyz;
|
||||
int yych;
|
||||
struct yywork *yyr;
|
||||
# ifdef LEXDEBUG
|
||||
int debug;
|
||||
# endif
|
||||
Uchar *yylastch;
|
||||
/* start off machines */
|
||||
# ifdef LEXDEBUG
|
||||
debug = 0;
|
||||
# endif
|
||||
if (!yymorfg)
|
||||
yylastch = (Uchar*)yytext;
|
||||
else {
|
||||
yymorfg=0;
|
||||
yylastch = (Uchar*)yytext+yyleng;
|
||||
}
|
||||
for(;;){
|
||||
lsp = yylstate;
|
||||
yyestate = yystate = yybgin;
|
||||
if (yyprevious==YYNEWLINE) yystate++;
|
||||
for (;;){
|
||||
# ifdef LEXDEBUG
|
||||
if(debug)fprintf(yyout,"state %d\n",yystate-yysvec-1);
|
||||
# endif
|
||||
yyt = yystate->yystoff;
|
||||
if(yyt == yycrank){ /* may not be any transitions */
|
||||
yyz = yystate->yyother;
|
||||
if(yyz == 0)break;
|
||||
if(yyz->yystoff == yycrank)break;
|
||||
}
|
||||
*yylastch++ = yych = input();
|
||||
tryagain:
|
||||
# ifdef LEXDEBUG
|
||||
if(debug){
|
||||
fprintf(yyout,"char ");
|
||||
allprint(yych);
|
||||
putchar('\n');
|
||||
}
|
||||
# endif
|
||||
yyr = yyt;
|
||||
if ( (int)yyt > (int)yycrank){
|
||||
yyt = yyr + yych;
|
||||
if (yyt <= yytop && yyt->verify+yysvec == yystate){
|
||||
if(yyt->advance+yysvec == YYLERR) /* error transitions */
|
||||
{unput(*--yylastch);break;}
|
||||
*lsp++ = yystate = yyt->advance+yysvec;
|
||||
goto contin;
|
||||
}
|
||||
}
|
||||
# ifdef YYOPTIM
|
||||
else if((int)yyt < (int)yycrank) { /* r < yycrank */
|
||||
yyt = yyr = yycrank+(yycrank-yyt);
|
||||
# ifdef LEXDEBUG
|
||||
if(debug)fprintf(yyout,"compressed state\n");
|
||||
# endif
|
||||
yyt = yyt + yych;
|
||||
if(yyt <= yytop && yyt->verify+yysvec == yystate){
|
||||
if(yyt->advance+yysvec == YYLERR) /* error transitions */
|
||||
{unput(*--yylastch);break;}
|
||||
*lsp++ = yystate = yyt->advance+yysvec;
|
||||
goto contin;
|
||||
}
|
||||
yyt = yyr + YYU(yymatch[yych]);
|
||||
# ifdef LEXDEBUG
|
||||
if(debug){
|
||||
fprintf(yyout,"try fall back character ");
|
||||
allprint(YYU(yymatch[yych]));
|
||||
putchar('\n');
|
||||
}
|
||||
# endif
|
||||
if(yyt <= yytop && yyt->verify+yysvec == yystate){
|
||||
if(yyt->advance+yysvec == YYLERR) /* error transition */
|
||||
{unput(*--yylastch);break;}
|
||||
*lsp++ = yystate = yyt->advance+yysvec;
|
||||
goto contin;
|
||||
}
|
||||
}
|
||||
if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){
|
||||
# ifdef LEXDEBUG
|
||||
if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1);
|
||||
# endif
|
||||
goto tryagain;
|
||||
}
|
||||
# endif
|
||||
else
|
||||
{unput(*--yylastch);break;}
|
||||
contin:
|
||||
# ifdef LEXDEBUG
|
||||
if(debug){
|
||||
fprintf(yyout,"state %d char ",yystate-yysvec-1);
|
||||
allprint(yych);
|
||||
putchar('\n');
|
||||
}
|
||||
# endif
|
||||
;
|
||||
}
|
||||
# ifdef LEXDEBUG
|
||||
if(debug){
|
||||
fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1);
|
||||
allprint(yych);
|
||||
putchar('\n');
|
||||
}
|
||||
# endif
|
||||
while (lsp-- > yylstate){
|
||||
*yylastch-- = 0;
|
||||
if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){
|
||||
yyolsp = lsp;
|
||||
if(yyextra[*yyfnd]){ /* must backup */
|
||||
while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){
|
||||
lsp--;
|
||||
unput(*yylastch--);
|
||||
}
|
||||
}
|
||||
yyprevious = YYU(*yylastch);
|
||||
yylsp = lsp;
|
||||
yyleng = yylastch-(Uchar*)yytext+1;
|
||||
yytext[yyleng] = 0;
|
||||
# ifdef LEXDEBUG
|
||||
if(debug){
|
||||
fprintf(yyout,"\nmatch '%s'", yytext);
|
||||
fprintf(yyout," action %d\n",*yyfnd);
|
||||
}
|
||||
# endif
|
||||
return(*yyfnd++);
|
||||
}
|
||||
unput(*yylastch);
|
||||
}
|
||||
if (yytext[0] == 0 /* && feof(yyin) */)
|
||||
{
|
||||
yysptr=yysbuf;
|
||||
return(0);
|
||||
}
|
||||
yyprevious = input();
|
||||
yytext[0] = yyprevious;
|
||||
if (yyprevious>0)
|
||||
output(yyprevious);
|
||||
yylastch = (Uchar*)yytext;
|
||||
# ifdef LEXDEBUG
|
||||
if(debug)putchar('\n');
|
||||
# endif
|
||||
}
|
||||
return(0); /* shut up the compiler; i have no idea what should be returned */
|
||||
}
|
||||
yyback(int *p, int m)
|
||||
{
|
||||
if (p==0) return(0);
|
||||
while (*p)
|
||||
{
|
||||
if (*p++ == m)
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
/* the following are only used in the lex library */
|
||||
yyinput(void){
|
||||
if(yyin == ((void*)0))
|
||||
yyin = stdin;
|
||||
return(input());
|
||||
}
|
||||
void
|
||||
yyoutput(int c)
|
||||
{
|
||||
if(yyout == ((void*)0))
|
||||
yyout = stdin;
|
||||
output(c);
|
||||
}
|
||||
void
|
||||
yyunput(int c)
|
||||
{
|
||||
unput(c);
|
||||
}
|
651
src/cmd/lex/parser.y
Normal file
651
src/cmd/lex/parser.y
Normal file
|
@ -0,0 +1,651 @@
|
|||
%token CHAR CCL NCCL STR DELIM SCON ITER NEWE NULLS
|
||||
%left SCON '/' NEWE
|
||||
%left '|'
|
||||
%left '$' '^'
|
||||
%left CHAR CCL NCCL '(' '.' STR NULLS
|
||||
%left ITER
|
||||
%left CAT
|
||||
%left '*' '+' '?'
|
||||
|
||||
%{
|
||||
# include "ldefs.h"
|
||||
#define YYSTYPE union _yystype_
|
||||
union _yystype_
|
||||
{
|
||||
int i;
|
||||
uchar *cp;
|
||||
};
|
||||
%}
|
||||
%%
|
||||
%{
|
||||
int i;
|
||||
int j,k;
|
||||
int g;
|
||||
uchar *p;
|
||||
%}
|
||||
acc : lexinput
|
||||
={
|
||||
# ifdef DEBUG
|
||||
if(debug) sect2dump();
|
||||
# endif
|
||||
}
|
||||
;
|
||||
lexinput: defns delim prods end
|
||||
| defns delim end
|
||||
={
|
||||
if(!funcflag)phead2();
|
||||
funcflag = TRUE;
|
||||
}
|
||||
| error
|
||||
={
|
||||
# ifdef DEBUG
|
||||
if(debug) {
|
||||
sect1dump();
|
||||
sect2dump();
|
||||
}
|
||||
# endif
|
||||
}
|
||||
;
|
||||
end: delim | ;
|
||||
defns: defns STR STR
|
||||
={ strcpy((char*)dp,(char*)$2.cp);
|
||||
def[dptr] = dp;
|
||||
dp += strlen((char*)$2.cp) + 1;
|
||||
strcpy((char*)dp,(char*)$3.cp);
|
||||
subs[dptr++] = dp;
|
||||
if(dptr >= DEFSIZE)
|
||||
error("Too many definitions");
|
||||
dp += strlen((char*)$3.cp) + 1;
|
||||
if(dp >= dchar+DEFCHAR)
|
||||
error("Definitions too long");
|
||||
subs[dptr]=def[dptr]=0; /* for lookup - require ending null */
|
||||
}
|
||||
|
|
||||
;
|
||||
delim: DELIM
|
||||
={
|
||||
# ifdef DEBUG
|
||||
if(sect == DEFSECTION && debug) sect1dump();
|
||||
# endif
|
||||
sect++;
|
||||
}
|
||||
;
|
||||
prods: prods pr
|
||||
={ $$.i = mn2(RNEWE,$1.i,$2.i);
|
||||
}
|
||||
| pr
|
||||
={ $$.i = $1.i;}
|
||||
;
|
||||
pr: r NEWE
|
||||
={
|
||||
if(divflg == TRUE)
|
||||
i = mn1(S1FINAL,casecount);
|
||||
else i = mn1(FINAL,casecount);
|
||||
$$.i = mn2(RCAT,$1.i,i);
|
||||
divflg = FALSE;
|
||||
casecount++;
|
||||
}
|
||||
| error NEWE
|
||||
={
|
||||
# ifdef DEBUG
|
||||
if(debug) sect2dump();
|
||||
# endif
|
||||
}
|
||||
r: CHAR
|
||||
={ $$.i = mn0($1.i); }
|
||||
| STR
|
||||
={
|
||||
p = $1.cp;
|
||||
i = mn0(*p++);
|
||||
while(*p)
|
||||
i = mn2(RSTR,i,*p++);
|
||||
$$.i = i;
|
||||
}
|
||||
| '.'
|
||||
={ symbol['\n'] = 0;
|
||||
if(psave == FALSE){
|
||||
p = ccptr;
|
||||
psave = ccptr;
|
||||
for(i=1;i<'\n';i++){
|
||||
symbol[i] = 1;
|
||||
*ccptr++ = i;
|
||||
}
|
||||
for(i='\n'+1;i<NCH;i++){
|
||||
symbol[i] = 1;
|
||||
*ccptr++ = i;
|
||||
}
|
||||
*ccptr++ = 0;
|
||||
if(ccptr > ccl+CCLSIZE)
|
||||
error("Too many large character classes");
|
||||
}
|
||||
else
|
||||
p = psave;
|
||||
$$.i = mn1(RCCL,(int)p);
|
||||
cclinter(1);
|
||||
}
|
||||
| CCL
|
||||
={ $$.i = mn1(RCCL,$1.i); }
|
||||
| NCCL
|
||||
={ $$.i = mn1(RNCCL,$1.i); }
|
||||
| r '*'
|
||||
={ $$.i = mn1(STAR,$1.i); }
|
||||
| r '+'
|
||||
={ $$.i = mn1(PLUS,$1.i); }
|
||||
| r '?'
|
||||
={ $$.i = mn1(QUEST,$1.i); }
|
||||
| r '|' r
|
||||
={ $$.i = mn2(BAR,$1.i,$3.i); }
|
||||
| r r %prec CAT
|
||||
={ $$.i = mn2(RCAT,$1.i,$2.i); }
|
||||
| r '/' r
|
||||
={ if(!divflg){
|
||||
j = mn1(S2FINAL,-casecount);
|
||||
i = mn2(RCAT,$1.i,j);
|
||||
$$.i = mn2(DIV,i,$3.i);
|
||||
}
|
||||
else {
|
||||
$$.i = mn2(RCAT,$1.i,$3.i);
|
||||
warning("Extra slash removed");
|
||||
}
|
||||
divflg = TRUE;
|
||||
}
|
||||
| r ITER ',' ITER '}'
|
||||
={ if($2.i > $4.i){
|
||||
i = $2.i;
|
||||
$2.i = $4.i;
|
||||
$4.i = i;
|
||||
}
|
||||
if($4.i <= 0)
|
||||
warning("Iteration range must be positive");
|
||||
else {
|
||||
j = $1.i;
|
||||
for(k = 2; k<=$2.i;k++)
|
||||
j = mn2(RCAT,j,dupl($1.i));
|
||||
for(i = $2.i+1; i<=$4.i; i++){
|
||||
g = dupl($1.i);
|
||||
for(k=2;k<=i;k++)
|
||||
g = mn2(RCAT,g,dupl($1.i));
|
||||
j = mn2(BAR,j,g);
|
||||
}
|
||||
$$.i = j;
|
||||
}
|
||||
}
|
||||
| r ITER '}'
|
||||
={
|
||||
if($2.i < 0)warning("Can't have negative iteration");
|
||||
else if($2.i == 0) $$.i = mn0(RNULLS);
|
||||
else {
|
||||
j = $1.i;
|
||||
for(k=2;k<=$2.i;k++)
|
||||
j = mn2(RCAT,j,dupl($1.i));
|
||||
$$.i = j;
|
||||
}
|
||||
}
|
||||
| r ITER ',' '}'
|
||||
={
|
||||
/* from n to infinity */
|
||||
if($2.i < 0)warning("Can't have negative iteration");
|
||||
else if($2.i == 0) $$.i = mn1(STAR,$1.i);
|
||||
else if($2.i == 1)$$.i = mn1(PLUS,$1.i);
|
||||
else { /* >= 2 iterations minimum */
|
||||
j = $1.i;
|
||||
for(k=2;k<$2.i;k++)
|
||||
j = mn2(RCAT,j,dupl($1.i));
|
||||
k = mn1(PLUS,dupl($1.i));
|
||||
$$.i = mn2(RCAT,j,k);
|
||||
}
|
||||
}
|
||||
| SCON r
|
||||
={ $$.i = mn2(RSCON,$2.i,$1.i); }
|
||||
| '^' r
|
||||
={ $$.i = mn1(CARAT,$2.i); }
|
||||
| r '$'
|
||||
={ i = mn0('\n');
|
||||
if(!divflg){
|
||||
j = mn1(S2FINAL,-casecount);
|
||||
k = mn2(RCAT,$1.i,j);
|
||||
$$.i = mn2(DIV,k,i);
|
||||
}
|
||||
else $$.i = mn2(RCAT,$1.i,i);
|
||||
divflg = TRUE;
|
||||
}
|
||||
| '(' r ')'
|
||||
={ $$.i = $2.i; }
|
||||
| NULLS
|
||||
={ $$.i = mn0(RNULLS); }
|
||||
;
|
||||
%%
|
||||
int
|
||||
yylex(void)
|
||||
{
|
||||
uchar *p;
|
||||
int c, i;
|
||||
uchar *t, *xp;
|
||||
int n, j, k, x;
|
||||
static int sectbegin;
|
||||
static uchar token[TOKENSIZE];
|
||||
static int iter;
|
||||
|
||||
# ifdef DEBUG
|
||||
yylval.i = 0;
|
||||
# endif
|
||||
|
||||
if(sect == DEFSECTION) { /* definitions section */
|
||||
while(!eof) {
|
||||
if(prev == '\n'){ /* next char is at beginning of line */
|
||||
getl(p=buf);
|
||||
switch(*p){
|
||||
case '%':
|
||||
switch(*(p+1)){
|
||||
case '%':
|
||||
lgate();
|
||||
Bprint(&fout,"#define YYNEWLINE %d\n",'\n');
|
||||
Bprint(&fout,"yylex(void){\nint nstr; extern int yyprevious;\n");
|
||||
sectbegin = TRUE;
|
||||
i = treesize*(sizeof(*name)+sizeof(*left)+
|
||||
sizeof(*right)+sizeof(*nullstr)+sizeof(*parent))+ALITTLEEXTRA;
|
||||
p = myalloc(i,1);
|
||||
if(p == 0)
|
||||
error("Too little core for parse tree");
|
||||
free(p);
|
||||
name = myalloc(treesize,sizeof(*name));
|
||||
left = myalloc(treesize,sizeof(*left));
|
||||
right = myalloc(treesize,sizeof(*right));
|
||||
nullstr = myalloc(treesize,sizeof(*nullstr));
|
||||
parent = myalloc(treesize,sizeof(*parent));
|
||||
if(name == 0 || left == 0 || right == 0 || parent == 0 || nullstr == 0)
|
||||
error("Too little core for parse tree");
|
||||
return(freturn(DELIM));
|
||||
case 'p': case 'P': /* has overridden number of positions */
|
||||
while(*p && !isdigit(*p))p++;
|
||||
maxpos = atol((char*)p);
|
||||
# ifdef DEBUG
|
||||
if (debug) print("positions (%%p) now %d\n",maxpos);
|
||||
# endif
|
||||
if(report == 2)report = 1;
|
||||
continue;
|
||||
case 'n': case 'N': /* has overridden number of states */
|
||||
while(*p && !isdigit(*p))p++;
|
||||
nstates = atol((char*)p);
|
||||
# ifdef DEBUG
|
||||
if(debug)print( " no. states (%%n) now %d\n",nstates);
|
||||
# endif
|
||||
if(report == 2)report = 1;
|
||||
continue;
|
||||
case 'e': case 'E': /* has overridden number of tree nodes */
|
||||
while(*p && !isdigit(*p))p++;
|
||||
treesize = atol((char*)p);
|
||||
# ifdef DEBUG
|
||||
if (debug) print("treesize (%%e) now %d\n",treesize);
|
||||
# endif
|
||||
if(report == 2)report = 1;
|
||||
continue;
|
||||
case 'o': case 'O':
|
||||
while (*p && !isdigit(*p))p++;
|
||||
outsize = atol((char*)p);
|
||||
if (report ==2) report=1;
|
||||
continue;
|
||||
case 'a': case 'A': /* has overridden number of transitions */
|
||||
while(*p && !isdigit(*p))p++;
|
||||
if(report == 2)report = 1;
|
||||
ntrans = atol((char*)p);
|
||||
# ifdef DEBUG
|
||||
if (debug)print("N. trans (%%a) now %d\n",ntrans);
|
||||
# endif
|
||||
continue;
|
||||
case 'k': case 'K': /* overriden packed char classes */
|
||||
while (*p && !isdigit(*p))p++;
|
||||
if (report==2) report=1;
|
||||
free(pchar);
|
||||
pchlen = atol((char*)p);
|
||||
# ifdef DEBUG
|
||||
if (debug) print( "Size classes (%%k) now %d\n",pchlen);
|
||||
# endif
|
||||
pchar=pcptr=myalloc(pchlen, sizeof(*pchar));
|
||||
continue;
|
||||
case '{':
|
||||
lgate();
|
||||
while(getl(p) && strcmp((char*)p,"%}") != 0)
|
||||
Bprint(&fout, "%s\n",(char*)p);
|
||||
if(p[0] == '%') continue;
|
||||
error("Premature eof");
|
||||
case 's': case 'S': /* start conditions */
|
||||
lgate();
|
||||
while(*p && strchr(" \t,", *p) == 0) p++;
|
||||
n = TRUE;
|
||||
while(n){
|
||||
while(*p && strchr(" \t,", *p)) p++;
|
||||
t = p;
|
||||
while(*p && strchr(" \t,", *p) == 0)p++;
|
||||
if(!*p) n = FALSE;
|
||||
*p++ = 0;
|
||||
if (*t == 0) continue;
|
||||
i = sptr*2;
|
||||
Bprint(&fout,"#define %s %d\n",(char*)t,i);
|
||||
strcpy((char*)sp, (char*)t);
|
||||
sname[sptr++] = sp;
|
||||
sname[sptr] = 0; /* required by lookup */
|
||||
if(sptr >= STARTSIZE)
|
||||
error("Too many start conditions");
|
||||
sp += strlen((char*)sp) + 1;
|
||||
if(sp >= stchar+STARTCHAR)
|
||||
error("Start conditions too long");
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
warning("Invalid request %s",p);
|
||||
continue;
|
||||
} /* end of switch after seeing '%' */
|
||||
case ' ': case '\t': /* must be code */
|
||||
lgate();
|
||||
Bprint(&fout, "%s\n",(char*)p);
|
||||
continue;
|
||||
default: /* definition */
|
||||
while(*p && !isspace(*p)) p++;
|
||||
if(*p == 0)
|
||||
continue;
|
||||
prev = *p;
|
||||
*p = 0;
|
||||
bptr = p+1;
|
||||
yylval.cp = buf;
|
||||
if(isdigit(buf[0]))
|
||||
warning("Substitution strings may not begin with digits");
|
||||
return(freturn(STR));
|
||||
}
|
||||
}
|
||||
/* still sect 1, but prev != '\n' */
|
||||
else {
|
||||
p = bptr;
|
||||
while(*p && isspace(*p)) p++;
|
||||
if(*p == 0)
|
||||
warning("No translation given - null string assumed");
|
||||
strcpy((char*)token, (char*)p);
|
||||
yylval.cp = token;
|
||||
prev = '\n';
|
||||
return(freturn(STR));
|
||||
}
|
||||
}
|
||||
/* end of section one processing */
|
||||
} else if(sect == RULESECTION){ /* rules and actions */
|
||||
while(!eof){
|
||||
switch(c=gch()){
|
||||
case '\0':
|
||||
return(freturn(0));
|
||||
case '\n':
|
||||
if(prev == '\n') continue;
|
||||
x = NEWE;
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
if(sectbegin == TRUE){
|
||||
cpyact();
|
||||
while((c=gch()) && c != '\n');
|
||||
continue;
|
||||
}
|
||||
if(!funcflag)phead2();
|
||||
funcflag = TRUE;
|
||||
Bprint(&fout,"case %d:\n",casecount);
|
||||
if(cpyact())
|
||||
Bprint(&fout,"break;\n");
|
||||
while((c=gch()) && c != '\n');
|
||||
if(peek == ' ' || peek == '\t' || sectbegin == TRUE){
|
||||
warning("Executable statements should occur right after %%");
|
||||
continue;
|
||||
}
|
||||
x = NEWE;
|
||||
break;
|
||||
case '%':
|
||||
if(prev != '\n') goto character;
|
||||
if(peek == '{'){ /* included code */
|
||||
getl(buf);
|
||||
while(!eof && getl(buf) && strcmp("%}",(char*)buf) != 0)
|
||||
Bprint(&fout,"%s\n",(char*)buf);
|
||||
continue;
|
||||
}
|
||||
if(peek == '%'){
|
||||
gch();
|
||||
gch();
|
||||
x = DELIM;
|
||||
break;
|
||||
}
|
||||
goto character;
|
||||
case '|':
|
||||
if(peek == ' ' || peek == '\t' || peek == '\n'){
|
||||
Bprint(&fout,"%d\n",30000+casecount++);
|
||||
continue;
|
||||
}
|
||||
x = '|';
|
||||
break;
|
||||
case '$':
|
||||
if(peek == '\n' || peek == ' ' || peek == '\t' || peek == '|' || peek == '/'){
|
||||
x = c;
|
||||
break;
|
||||
}
|
||||
goto character;
|
||||
case '^':
|
||||
if(prev != '\n' && scon != TRUE) goto character; /* valid only at line begin */
|
||||
x = c;
|
||||
break;
|
||||
case '?':
|
||||
case '+':
|
||||
case '.':
|
||||
case '*':
|
||||
case '(':
|
||||
case ')':
|
||||
case ',':
|
||||
case '/':
|
||||
x = c;
|
||||
break;
|
||||
case '}':
|
||||
iter = FALSE;
|
||||
x = c;
|
||||
break;
|
||||
case '{': /* either iteration or definition */
|
||||
if(isdigit(c=gch())){ /* iteration */
|
||||
iter = TRUE;
|
||||
ieval:
|
||||
i = 0;
|
||||
while(isdigit(c)){
|
||||
token[i++] = c;
|
||||
c = gch();
|
||||
}
|
||||
token[i] = 0;
|
||||
yylval.i = atol((char*)token);
|
||||
munputc(c);
|
||||
x = ITER;
|
||||
break;
|
||||
} else { /* definition */
|
||||
i = 0;
|
||||
while(c && c!='}'){
|
||||
token[i++] = c;
|
||||
c = gch();
|
||||
}
|
||||
token[i] = 0;
|
||||
i = lookup(token,def);
|
||||
if(i < 0)
|
||||
warning("Definition %s not found",token);
|
||||
else
|
||||
munputs(subs[i]);
|
||||
continue;
|
||||
}
|
||||
case '<': /* start condition ? */
|
||||
if(prev != '\n') /* not at line begin, not start */
|
||||
goto character;
|
||||
t = slptr;
|
||||
do {
|
||||
i = 0;
|
||||
c = gch();
|
||||
while(c != ',' && c && c != '>'){
|
||||
token[i++] = c;
|
||||
c = gch();
|
||||
}
|
||||
token[i] = 0;
|
||||
if(i == 0)
|
||||
goto character;
|
||||
i = lookup(token,sname);
|
||||
if(i < 0) {
|
||||
warning("Undefined start condition %s",token);
|
||||
continue;
|
||||
}
|
||||
*slptr++ = i+1;
|
||||
} while(c && c != '>');
|
||||
*slptr++ = 0;
|
||||
/* check if previous value re-usable */
|
||||
for (xp=slist; xp<t; ){
|
||||
if (strcmp((char*)xp, (char*)t)==0)
|
||||
break;
|
||||
while (*xp++);
|
||||
}
|
||||
if (xp<t){
|
||||
/* re-use previous pointer to string */
|
||||
slptr=t;
|
||||
t=xp;
|
||||
}
|
||||
if(slptr > slist+STARTSIZE) /* note not packed ! */
|
||||
error("Too many start conditions used");
|
||||
yylval.cp = t;
|
||||
x = SCON;
|
||||
break;
|
||||
case '"':
|
||||
i = 0;
|
||||
while((c=gch()) && c != '"' && c != '\n'){
|
||||
if(c == '\\') c = usescape(gch());
|
||||
token[i++] = c;
|
||||
if(i > TOKENSIZE){
|
||||
warning("String too long");
|
||||
i = TOKENSIZE-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(c == '\n') {
|
||||
yyline--;
|
||||
warning("Non-terminated string");
|
||||
yyline++;
|
||||
}
|
||||
token[i] = 0;
|
||||
if(i == 0)x = NULLS;
|
||||
else if(i == 1){
|
||||
yylval.i = token[0];
|
||||
x = CHAR;
|
||||
} else {
|
||||
yylval.cp = token;
|
||||
x = STR;
|
||||
}
|
||||
break;
|
||||
case '[':
|
||||
for(i=1;i<NCH;i++) symbol[i] = 0;
|
||||
x = CCL;
|
||||
if((c = gch()) == '^'){
|
||||
x = NCCL;
|
||||
c = gch();
|
||||
}
|
||||
while(c != ']' && c){
|
||||
if(c == '\\') c = usescape(gch());
|
||||
symbol[c] = 1;
|
||||
j = c;
|
||||
if((c=gch()) == '-' && peek != ']'){ /* range specified */
|
||||
c = gch();
|
||||
if(c == '\\') c = usescape(gch());
|
||||
k = c;
|
||||
if(j > k) {
|
||||
n = j;
|
||||
j = k;
|
||||
k = n;
|
||||
}
|
||||
if(!(('A' <= j && k <= 'Z') ||
|
||||
('a' <= j && k <= 'z') ||
|
||||
('0' <= j && k <= '9')))
|
||||
warning("Non-portable Character Class");
|
||||
for(n=j+1;n<=k;n++)
|
||||
symbol[n] = 1; /* implementation dependent */
|
||||
c = gch();
|
||||
}
|
||||
}
|
||||
/* try to pack ccl's */
|
||||
i = 0;
|
||||
for(j=0;j<NCH;j++)
|
||||
if(symbol[j])token[i++] = j;
|
||||
token[i] = 0;
|
||||
p = ccl;
|
||||
while(p <ccptr && strcmp((char*)token,(char*)p) != 0)p++;
|
||||
if(p < ccptr) /* found it */
|
||||
yylval.cp = p;
|
||||
else {
|
||||
yylval.cp = ccptr;
|
||||
strcpy((char*)ccptr,(char*)token);
|
||||
ccptr += strlen((char*)token) + 1;
|
||||
if(ccptr >= ccl+CCLSIZE)
|
||||
error("Too many large character classes");
|
||||
}
|
||||
cclinter(x==CCL);
|
||||
break;
|
||||
case '\\':
|
||||
c = usescape(gch());
|
||||
default:
|
||||
character:
|
||||
if(iter){ /* second part of an iteration */
|
||||
iter = FALSE;
|
||||
if('0' <= c && c <= '9')
|
||||
goto ieval;
|
||||
}
|
||||
if(isalpha(peek)){
|
||||
i = 0;
|
||||
yylval.cp = token;
|
||||
token[i++] = c;
|
||||
while(isalpha(peek))
|
||||
token[i++] = gch();
|
||||
if(peek == '?' || peek == '*' || peek == '+')
|
||||
munputc(token[--i]);
|
||||
token[i] = 0;
|
||||
if(i == 1){
|
||||
yylval.i = token[0];
|
||||
x = CHAR;
|
||||
}
|
||||
else x = STR;
|
||||
} else {
|
||||
yylval.i = c;
|
||||
x = CHAR;
|
||||
}
|
||||
}
|
||||
scon = FALSE;
|
||||
if(x == SCON)scon = TRUE;
|
||||
sectbegin = FALSE;
|
||||
return(freturn(x));
|
||||
}
|
||||
}
|
||||
/* section three */
|
||||
ptail();
|
||||
# ifdef DEBUG
|
||||
if(debug)
|
||||
Bprint(&fout,"\n/*this comes from section three - debug */\n");
|
||||
# endif
|
||||
while(getl(buf) && !eof)
|
||||
Bprint(&fout,"%s\n",(char*)buf);
|
||||
return(freturn(0));
|
||||
}
|
||||
/* end of yylex */
|
||||
# ifdef DEBUG
|
||||
int
|
||||
freturn(int i)
|
||||
{
|
||||
if(yydebug) {
|
||||
print("now return ");
|
||||
if(i < NCH) allprint(i);
|
||||
else print("%d",i);
|
||||
printf(" yylval = ");
|
||||
switch(i){
|
||||
case STR: case CCL: case NCCL:
|
||||
strpt(yylval.cp);
|
||||
break;
|
||||
case CHAR:
|
||||
allprint(yylval.i);
|
||||
break;
|
||||
default:
|
||||
print("%d",yylval.i);
|
||||
break;
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
# endif
|
591
src/cmd/lex/sub1.c
Normal file
591
src/cmd/lex/sub1.c
Normal file
|
@ -0,0 +1,591 @@
|
|||
# include "ldefs.h"
|
||||
uchar *
|
||||
getl(uchar *p) /* return next line of input, throw away trailing '\n' */
|
||||
/* returns 0 if eof is had immediately */
|
||||
{
|
||||
int c;
|
||||
uchar *s, *t;
|
||||
|
||||
t = s = p;
|
||||
while(((c = gch()) != 0) && c != '\n')
|
||||
*t++ = c;
|
||||
*t = 0;
|
||||
if(c == 0 && s == t) return((uchar *)0);
|
||||
prev = '\n';
|
||||
pres = '\n';
|
||||
return(s);
|
||||
}
|
||||
|
||||
void
|
||||
printerr(char *type, char *fmt, va_list argl)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
if(!eof)fprint(errorf,"%d: ",yyline);
|
||||
fprint(errorf,"(%s) ", type);
|
||||
vseprint(buf, buf+sizeof(buf), fmt, argl);
|
||||
fprint(errorf, "%s\n", buf);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
error(char *s,...)
|
||||
{
|
||||
va_list argl;
|
||||
|
||||
va_start(argl, s);
|
||||
printerr("Error", s, argl);
|
||||
va_end(argl);
|
||||
# ifdef DEBUG
|
||||
if(debug && sect != ENDSECTION) {
|
||||
sect1dump();
|
||||
sect2dump();
|
||||
}
|
||||
# endif
|
||||
if(
|
||||
# ifdef DEBUG
|
||||
debug ||
|
||||
# endif
|
||||
report == 1) statistics();
|
||||
exits("error"); /* error return code */
|
||||
}
|
||||
|
||||
void
|
||||
warning(char *s,...)
|
||||
{
|
||||
va_list argl;
|
||||
|
||||
va_start(argl, s);
|
||||
printerr("Warning", s, argl);
|
||||
va_end(argl);
|
||||
Bflush(&fout);
|
||||
}
|
||||
|
||||
void
|
||||
lgate(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if (lgatflg) return;
|
||||
lgatflg=1;
|
||||
if(foutopen == 0){
|
||||
fd = create("lex.yy.c", OWRITE, 0666);
|
||||
if(fd < 0)
|
||||
error("Can't open lex.yy.c");
|
||||
Binit(&fout, fd, OWRITE);
|
||||
foutopen = 1;
|
||||
}
|
||||
phead1();
|
||||
}
|
||||
|
||||
void
|
||||
cclinter(int sw)
|
||||
{
|
||||
/* sw = 1 ==> ccl */
|
||||
int i, j, k;
|
||||
int m;
|
||||
if(!sw){ /* is NCCL */
|
||||
for(i=1;i<NCH;i++)
|
||||
symbol[i] ^= 1; /* reverse value */
|
||||
}
|
||||
for(i=1;i<NCH;i++)
|
||||
if(symbol[i]) break;
|
||||
if(i >= NCH) return;
|
||||
i = cindex[i];
|
||||
/* see if ccl is already in our table */
|
||||
j = 0;
|
||||
if(i){
|
||||
for(j=1;j<NCH;j++){
|
||||
if((symbol[j] && cindex[j] != i) ||
|
||||
(!symbol[j] && cindex[j] == i)) break;
|
||||
}
|
||||
}
|
||||
if(j >= NCH) return; /* already in */
|
||||
m = 0;
|
||||
k = 0;
|
||||
for(i=1;i<NCH;i++)
|
||||
if(symbol[i]){
|
||||
if(!cindex[i]){
|
||||
cindex[i] = ccount;
|
||||
symbol[i] = 0;
|
||||
m = 1;
|
||||
} else k = 1;
|
||||
}
|
||||
/* m == 1 implies last value of ccount has been used */
|
||||
if(m)ccount++;
|
||||
if(k == 0) return; /* is now in as ccount wholly */
|
||||
/* intersection must be computed */
|
||||
for(i=1;i<NCH;i++){
|
||||
if(symbol[i]){
|
||||
m = 0;
|
||||
j = cindex[i]; /* will be non-zero */
|
||||
for(k=1;k<NCH;k++){
|
||||
if(cindex[k] == j){
|
||||
if(symbol[k]) symbol[k] = 0;
|
||||
else {
|
||||
cindex[k] = ccount;
|
||||
m = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(m)ccount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
usescape(int c)
|
||||
{
|
||||
int d;
|
||||
switch(c){
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'b': c = '\b'; break;
|
||||
case 'f': c = 014; break; /* form feed for ascii */
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
c -= '0';
|
||||
while('0' <= (d=gch()) && d <= '7'){
|
||||
c = c * 8 + (d-'0');
|
||||
if(!('0' <= peek && peek <= '7')) break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return(c);
|
||||
}
|
||||
|
||||
int
|
||||
lookup(uchar *s, uchar **t)
|
||||
{
|
||||
int i;
|
||||
i = 0;
|
||||
while(*t){
|
||||
if(strcmp((char *)s, *(char **)t) == 0)
|
||||
return(i);
|
||||
i++;
|
||||
t++;
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int
|
||||
cpyact(void)
|
||||
{ /* copy C action to the next ; or closing } */
|
||||
int brac, c, mth;
|
||||
int savline, sw;
|
||||
|
||||
brac = 0;
|
||||
sw = TRUE;
|
||||
savline = 0;
|
||||
|
||||
while(!eof){
|
||||
c = gch();
|
||||
swt:
|
||||
switch( c ){
|
||||
|
||||
case '|': if(brac == 0 && sw == TRUE){
|
||||
if(peek == '|')gch(); /* eat up an extra '|' */
|
||||
return(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case ';':
|
||||
if( brac == 0 ){
|
||||
Bputc(&fout, c);
|
||||
Bputc(&fout, '\n');
|
||||
return(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case '{':
|
||||
brac++;
|
||||
savline=yyline;
|
||||
break;
|
||||
|
||||
case '}':
|
||||
brac--;
|
||||
if( brac == 0 ){
|
||||
Bputc(&fout, c);
|
||||
Bputc(&fout, '\n');
|
||||
return(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case '/': /* look for comments */
|
||||
Bputc(&fout, c);
|
||||
c = gch();
|
||||
if( c != '*' ) goto swt;
|
||||
|
||||
/* it really is a comment */
|
||||
|
||||
Bputc(&fout, c);
|
||||
savline=yyline;
|
||||
while( c=gch() ){
|
||||
if( c=='*' ){
|
||||
Bputc(&fout, c);
|
||||
if( (c=gch()) == '/' ) goto loop;
|
||||
}
|
||||
Bputc(&fout, c);
|
||||
}
|
||||
yyline=savline;
|
||||
error( "EOF inside comment" );
|
||||
|
||||
case '\'': /* character constant */
|
||||
mth = '\'';
|
||||
goto string;
|
||||
|
||||
case '"': /* character string */
|
||||
mth = '"';
|
||||
|
||||
string:
|
||||
|
||||
Bputc(&fout, c);
|
||||
while( c=gch() ){
|
||||
if( c=='\\' ){
|
||||
Bputc(&fout, c);
|
||||
c=gch();
|
||||
}
|
||||
else if( c==mth ) goto loop;
|
||||
Bputc(&fout, c);
|
||||
if (c == '\n') {
|
||||
yyline--;
|
||||
error( "Non-terminated string or character constant");
|
||||
}
|
||||
}
|
||||
error( "EOF in string or character constant" );
|
||||
|
||||
case '\0':
|
||||
yyline = savline;
|
||||
error("Action does not terminate");
|
||||
default:
|
||||
break; /* usual character */
|
||||
}
|
||||
loop:
|
||||
if(c != ' ' && c != '\t' && c != '\n') sw = FALSE;
|
||||
Bputc(&fout, c);
|
||||
}
|
||||
error("Premature EOF");
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
gch(void){
|
||||
int c;
|
||||
prev = pres;
|
||||
c = pres = peek;
|
||||
peek = pushptr > pushc ? *--pushptr : Bgetc(fin);
|
||||
if(peek == Beof && sargc > 1){
|
||||
Bterm(fin);
|
||||
fin = Bopen(sargv[fptr++],OREAD);
|
||||
if(fin == 0)
|
||||
error("Cannot open file %s",sargv[fptr-1]);
|
||||
peek = Bgetc(fin);
|
||||
sargc--;
|
||||
sargv++;
|
||||
}
|
||||
if(c == Beof) {
|
||||
eof = TRUE;
|
||||
Bterm(fin);
|
||||
return(0);
|
||||
}
|
||||
if(c == '\n')yyline++;
|
||||
return(c);
|
||||
}
|
||||
|
||||
int
|
||||
mn2(int a, int d, int c)
|
||||
{
|
||||
name[tptr] = a;
|
||||
left[tptr] = d;
|
||||
right[tptr] = c;
|
||||
parent[tptr] = 0;
|
||||
nullstr[tptr] = 0;
|
||||
switch(a){
|
||||
case RSTR:
|
||||
parent[d] = tptr;
|
||||
break;
|
||||
case BAR:
|
||||
case RNEWE:
|
||||
if(nullstr[d] || nullstr[c]) nullstr[tptr] = TRUE;
|
||||
parent[d] = parent[c] = tptr;
|
||||
break;
|
||||
case RCAT:
|
||||
case DIV:
|
||||
if(nullstr[d] && nullstr[c])nullstr[tptr] = TRUE;
|
||||
parent[d] = parent[c] = tptr;
|
||||
break;
|
||||
case RSCON:
|
||||
parent[d] = tptr;
|
||||
nullstr[tptr] = nullstr[d];
|
||||
break;
|
||||
# ifdef DEBUG
|
||||
default:
|
||||
warning("bad switch mn2 %d %d",a,d);
|
||||
break;
|
||||
# endif
|
||||
}
|
||||
if(tptr > treesize)
|
||||
error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
|
||||
return(tptr++);
|
||||
}
|
||||
|
||||
int
|
||||
mn1(int a, int d)
|
||||
{
|
||||
name[tptr] = a;
|
||||
left[tptr] = d;
|
||||
parent[tptr] = 0;
|
||||
nullstr[tptr] = 0;
|
||||
switch(a){
|
||||
case RCCL:
|
||||
case RNCCL:
|
||||
if(strlen((char *)d) == 0) nullstr[tptr] = TRUE;
|
||||
break;
|
||||
case STAR:
|
||||
case QUEST:
|
||||
nullstr[tptr] = TRUE;
|
||||
parent[d] = tptr;
|
||||
break;
|
||||
case PLUS:
|
||||
case CARAT:
|
||||
nullstr[tptr] = nullstr[d];
|
||||
parent[d] = tptr;
|
||||
break;
|
||||
case S2FINAL:
|
||||
nullstr[tptr] = TRUE;
|
||||
break;
|
||||
# ifdef DEBUG
|
||||
case FINAL:
|
||||
case S1FINAL:
|
||||
break;
|
||||
default:
|
||||
warning("bad switch mn1 %d %d",a,d);
|
||||
break;
|
||||
# endif
|
||||
}
|
||||
if(tptr > treesize)
|
||||
error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
|
||||
return(tptr++);
|
||||
}
|
||||
|
||||
int
|
||||
mn0(int a)
|
||||
{
|
||||
name[tptr] = a;
|
||||
parent[tptr] = 0;
|
||||
nullstr[tptr] = 0;
|
||||
if(a >= NCH) switch(a){
|
||||
case RNULLS: nullstr[tptr] = TRUE; break;
|
||||
# ifdef DEBUG
|
||||
default:
|
||||
warning("bad switch mn0 %d",a);
|
||||
break;
|
||||
# endif
|
||||
}
|
||||
if(tptr > treesize)
|
||||
error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":""));
|
||||
return(tptr++);
|
||||
}
|
||||
|
||||
void
|
||||
munputc(int p)
|
||||
{
|
||||
*pushptr++ = peek; /* watch out for this */
|
||||
peek = p;
|
||||
if(pushptr >= pushc+TOKENSIZE)
|
||||
error("Too many characters pushed");
|
||||
}
|
||||
|
||||
void
|
||||
munputs(uchar *p)
|
||||
{
|
||||
int i,j;
|
||||
*pushptr++ = peek;
|
||||
peek = p[0];
|
||||
i = strlen((char*)p);
|
||||
for(j = i-1; j>=1; j--)
|
||||
*pushptr++ = p[j];
|
||||
if(pushptr >= pushc+TOKENSIZE)
|
||||
error("Too many characters pushed");
|
||||
}
|
||||
|
||||
int
|
||||
dupl(int n)
|
||||
{
|
||||
/* duplicate the subtree whose root is n, return ptr to it */
|
||||
int i;
|
||||
|
||||
i = name[n];
|
||||
if(i < NCH) return(mn0(i));
|
||||
switch(i){
|
||||
case RNULLS:
|
||||
return(mn0(i));
|
||||
case RCCL: case RNCCL: case FINAL: case S1FINAL: case S2FINAL:
|
||||
return(mn1(i,left[n]));
|
||||
case STAR: case QUEST: case PLUS: case CARAT:
|
||||
return(mn1(i,dupl(left[n])));
|
||||
case RSTR: case RSCON:
|
||||
return(mn2(i,dupl(left[n]),right[n]));
|
||||
case BAR: case RNEWE: case RCAT: case DIV:
|
||||
return(mn2(i,dupl(left[n]),dupl(right[n])));
|
||||
# ifdef DEBUG
|
||||
default:
|
||||
warning("bad switch dupl %d",n);
|
||||
# endif
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
# ifdef DEBUG
|
||||
void
|
||||
allprint(int c)
|
||||
{
|
||||
switch(c){
|
||||
case 014:
|
||||
print("\\f");
|
||||
charc++;
|
||||
break;
|
||||
case '\n':
|
||||
print("\\n");
|
||||
charc++;
|
||||
break;
|
||||
case '\t':
|
||||
print("\\t");
|
||||
charc++;
|
||||
break;
|
||||
case '\b':
|
||||
print("\\b");
|
||||
charc++;
|
||||
break;
|
||||
case ' ':
|
||||
print("\\\bb");
|
||||
break;
|
||||
default:
|
||||
if(!isprint(c)){
|
||||
print("\\%-3o",c);
|
||||
charc += 3;
|
||||
} else
|
||||
print("%c", c);
|
||||
break;
|
||||
}
|
||||
charc++;
|
||||
}
|
||||
|
||||
void
|
||||
strpt(uchar *s)
|
||||
{
|
||||
charc = 0;
|
||||
while(*s){
|
||||
allprint(*s++);
|
||||
if(charc > LINESIZE){
|
||||
charc = 0;
|
||||
print("\n\t");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sect1dump(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
print("Sect 1:\n");
|
||||
if(def[0]){
|
||||
print("str trans\n");
|
||||
i = -1;
|
||||
while(def[++i])
|
||||
print("%s\t%s\n",def[i],subs[i]);
|
||||
}
|
||||
if(sname[0]){
|
||||
print("start names\n");
|
||||
i = -1;
|
||||
while(sname[++i])
|
||||
print("%s\n",sname[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sect2dump(void)
|
||||
{
|
||||
print("Sect 2:\n");
|
||||
treedump();
|
||||
}
|
||||
|
||||
void
|
||||
treedump(void)
|
||||
{
|
||||
int t;
|
||||
uchar *p;
|
||||
print("treedump %d nodes:\n",tptr);
|
||||
for(t=0;t<tptr;t++){
|
||||
print("%4d ",t);
|
||||
parent[t] ? print("p=%4d",parent[t]) : print(" ");
|
||||
print(" ");
|
||||
if(name[t] < NCH)
|
||||
allprint(name[t]);
|
||||
else switch(name[t]){
|
||||
case RSTR:
|
||||
print("%d ",left[t]);
|
||||
allprint(right[t]);
|
||||
break;
|
||||
case RCCL:
|
||||
print("ccl ");
|
||||
strpt(left[t]);
|
||||
break;
|
||||
case RNCCL:
|
||||
print("nccl ");
|
||||
strpt(left[t]);
|
||||
break;
|
||||
case DIV:
|
||||
print("/ %d %d",left[t],right[t]);
|
||||
break;
|
||||
case BAR:
|
||||
print("| %d %d",left[t],right[t]);
|
||||
break;
|
||||
case RCAT:
|
||||
print("cat %d %d",left[t],right[t]);
|
||||
break;
|
||||
case PLUS:
|
||||
print("+ %d",left[t]);
|
||||
break;
|
||||
case STAR:
|
||||
print("* %d",left[t]);
|
||||
break;
|
||||
case CARAT:
|
||||
print("^ %d",left[t]);
|
||||
break;
|
||||
case QUEST:
|
||||
print("? %d",left[t]);
|
||||
break;
|
||||
case RNULLS:
|
||||
print("nullstring");
|
||||
break;
|
||||
case FINAL:
|
||||
print("final %d",left[t]);
|
||||
break;
|
||||
case S1FINAL:
|
||||
print("s1final %d",left[t]);
|
||||
break;
|
||||
case S2FINAL:
|
||||
print("s2final %d",left[t]);
|
||||
break;
|
||||
case RNEWE:
|
||||
print("new %d %d",left[t],right[t]);
|
||||
break;
|
||||
case RSCON:
|
||||
p = (uchar *)right[t];
|
||||
print("start %s",sname[*p++-1]);
|
||||
while(*p)
|
||||
print(", %s",sname[*p++-1]);
|
||||
print(" %d",left[t]);
|
||||
break;
|
||||
default:
|
||||
print("unknown %d %d %d",name[t],left[t],right[t]);
|
||||
break;
|
||||
}
|
||||
if(nullstr[t])print("\t(null poss.)");
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
# endif
|
856
src/cmd/lex/sub2.c
Normal file
856
src/cmd/lex/sub2.c
Normal file
|
@ -0,0 +1,856 @@
|
|||
# include "ldefs.h"
|
||||
void
|
||||
cfoll(int v)
|
||||
{
|
||||
int i,j,k;
|
||||
uchar *p;
|
||||
i = name[v];
|
||||
if(i < NCH) i = 1; /* character */
|
||||
switch(i){
|
||||
case 1: case RSTR: case RCCL: case RNCCL: case RNULLS:
|
||||
for(j=0;j<tptr;j++)
|
||||
tmpstat[j] = FALSE;
|
||||
count = 0;
|
||||
follow(v);
|
||||
# ifdef PP
|
||||
padd(foll,v); /* packing version */
|
||||
# endif
|
||||
# ifndef PP
|
||||
add(foll,v); /* no packing version */
|
||||
# endif
|
||||
if(i == RSTR) cfoll(left[v]);
|
||||
else if(i == RCCL || i == RNCCL){ /* compress ccl list */
|
||||
for(j=1; j<NCH;j++)
|
||||
symbol[j] = (i==RNCCL);
|
||||
p = (uchar *)left[v];
|
||||
while(*p)
|
||||
symbol[*p++] = (i == RCCL);
|
||||
p = pcptr;
|
||||
for(j=1;j<NCH;j++)
|
||||
if(symbol[j]){
|
||||
for(k=0;p+k < pcptr; k++)
|
||||
if(cindex[j] == *(p+k))
|
||||
break;
|
||||
if(p+k >= pcptr)*pcptr++ = cindex[j];
|
||||
}
|
||||
*pcptr++ = 0;
|
||||
if(pcptr > pchar + pchlen)
|
||||
error("Too many packed character classes");
|
||||
left[v] = (int)p;
|
||||
name[v] = RCCL; /* RNCCL eliminated */
|
||||
# ifdef DEBUG
|
||||
if(debug && *p){
|
||||
print("ccl %d: %d",v,*p++);
|
||||
while(*p)
|
||||
print(", %d",*p++);
|
||||
print("\n");
|
||||
}
|
||||
# endif
|
||||
}
|
||||
break;
|
||||
case CARAT:
|
||||
cfoll(left[v]);
|
||||
break;
|
||||
case STAR: case PLUS: case QUEST: case RSCON:
|
||||
cfoll(left[v]);
|
||||
break;
|
||||
case BAR: case RCAT: case DIV: case RNEWE:
|
||||
cfoll(left[v]);
|
||||
cfoll(right[v]);
|
||||
break;
|
||||
# ifdef DEBUG
|
||||
case FINAL:
|
||||
case S1FINAL:
|
||||
case S2FINAL:
|
||||
break;
|
||||
default:
|
||||
warning("bad switch cfoll %d",v);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef DEBUG
|
||||
void
|
||||
pfoll(void)
|
||||
{
|
||||
int i,k,*p;
|
||||
int j;
|
||||
/* print sets of chars which may follow positions */
|
||||
print("pos\tchars\n");
|
||||
for(i=0;i<tptr;i++)
|
||||
if(p=foll[i]){
|
||||
j = *p++;
|
||||
if(j >= 1){
|
||||
print("%d:\t%d",i,*p++);
|
||||
for(k=2;k<=j;k++)
|
||||
print(", %d",*p++);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
void
|
||||
add(int **array, int n)
|
||||
{
|
||||
int i, *temp;
|
||||
uchar *ctemp;
|
||||
|
||||
temp = nxtpos;
|
||||
ctemp = tmpstat;
|
||||
array[n] = nxtpos; /* note no packing is done in positions */
|
||||
*temp++ = count;
|
||||
for(i=0;i<tptr;i++)
|
||||
if(ctemp[i] == TRUE)
|
||||
*temp++ = i;
|
||||
nxtpos = temp;
|
||||
if(nxtpos >= positions+maxpos)
|
||||
error("Too many positions %s",(maxpos== MAXPOS?"\nTry using %p num":""));
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
follow(int v)
|
||||
{
|
||||
int p;
|
||||
if(v >= tptr-1)return;
|
||||
p = parent[v];
|
||||
if(p == 0) return;
|
||||
switch(name[p]){
|
||||
/* will not be CHAR RNULLS FINAL S1FINAL S2FINAL RCCL RNCCL */
|
||||
case RSTR:
|
||||
if(tmpstat[p] == FALSE){
|
||||
count++;
|
||||
tmpstat[p] = TRUE;
|
||||
}
|
||||
break;
|
||||
case STAR: case PLUS:
|
||||
first(v);
|
||||
follow(p);
|
||||
break;
|
||||
case BAR: case QUEST: case RNEWE:
|
||||
follow(p);
|
||||
break;
|
||||
case RCAT: case DIV:
|
||||
if(v == left[p]){
|
||||
if(nullstr[right[p]])
|
||||
follow(p);
|
||||
first(right[p]);
|
||||
}
|
||||
else follow(p);
|
||||
break;
|
||||
case RSCON: case CARAT:
|
||||
follow(p);
|
||||
break;
|
||||
# ifdef DEBUG
|
||||
default:
|
||||
warning("bad switch follow %d",p);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
first(int v) /* calculate set of positions with v as root which can be active initially */
|
||||
{
|
||||
int i;
|
||||
uchar *p;
|
||||
i = name[v];
|
||||
if(i < NCH)i = 1;
|
||||
switch(i){
|
||||
case 1: case RCCL: case RNCCL: case RNULLS: case FINAL: case S1FINAL: case S2FINAL:
|
||||
if(tmpstat[v] == FALSE){
|
||||
count++;
|
||||
tmpstat[v] = TRUE;
|
||||
}
|
||||
break;
|
||||
case BAR: case RNEWE:
|
||||
first(left[v]);
|
||||
first(right[v]);
|
||||
break;
|
||||
case CARAT:
|
||||
if(stnum % 2 == 1)
|
||||
first(left[v]);
|
||||
break;
|
||||
case RSCON:
|
||||
i = stnum/2 +1;
|
||||
p = (uchar *)right[v];
|
||||
while(*p)
|
||||
if(*p++ == i){
|
||||
first(left[v]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case STAR: case QUEST: case PLUS: case RSTR:
|
||||
first(left[v]);
|
||||
break;
|
||||
case RCAT: case DIV:
|
||||
first(left[v]);
|
||||
if(nullstr[left[v]])
|
||||
first(right[v]);
|
||||
break;
|
||||
# ifdef DEBUG
|
||||
default:
|
||||
warning("bad switch first %d",v);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cgoto(void)
|
||||
{
|
||||
int i, j, s;
|
||||
int npos, curpos, n;
|
||||
int tryit;
|
||||
uchar tch[NCH];
|
||||
int tst[NCH];
|
||||
uchar *q;
|
||||
|
||||
/* generate initial state, for each start condition */
|
||||
Bprint(&fout,"int yyvstop[] = {\n0,\n");
|
||||
while(stnum < 2 || stnum/2 < sptr){
|
||||
for(i = 0; i<tptr; i++) tmpstat[i] = 0;
|
||||
count = 0;
|
||||
if(tptr > 0)first(tptr-1);
|
||||
add(state,stnum);
|
||||
# ifdef DEBUG
|
||||
if(debug){
|
||||
if(stnum > 1)
|
||||
print("%s:\n",sname[stnum/2]);
|
||||
pstate(stnum);
|
||||
}
|
||||
# endif
|
||||
stnum++;
|
||||
}
|
||||
stnum--;
|
||||
/* even stnum = might not be at line begin */
|
||||
/* odd stnum = must be at line begin */
|
||||
/* even states can occur anywhere, odd states only at line begin */
|
||||
for(s = 0; s <= stnum; s++){
|
||||
tryit = FALSE;
|
||||
cpackflg[s] = FALSE;
|
||||
sfall[s] = -1;
|
||||
acompute(s);
|
||||
for(i=0;i<NCH;i++) symbol[i] = 0;
|
||||
npos = *state[s];
|
||||
for(i = 1; i<=npos; i++){
|
||||
curpos = *(state[s]+i);
|
||||
if(name[curpos] < NCH) symbol[name[curpos]] = TRUE;
|
||||
else switch(name[curpos]){
|
||||
case RCCL:
|
||||
tryit = TRUE;
|
||||
q = (uchar *)left[curpos];
|
||||
while(*q){
|
||||
for(j=1;j<NCH;j++)
|
||||
if(cindex[j] == *q)
|
||||
symbol[j] = TRUE;
|
||||
q++;
|
||||
}
|
||||
break;
|
||||
case RSTR:
|
||||
symbol[right[curpos]] = TRUE;
|
||||
break;
|
||||
# ifdef DEBUG
|
||||
case RNULLS:
|
||||
case FINAL:
|
||||
case S1FINAL:
|
||||
case S2FINAL:
|
||||
break;
|
||||
default:
|
||||
warning("bad switch cgoto %d state %d",curpos,s);
|
||||
break;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
# ifdef DEBUG
|
||||
if(debug){
|
||||
print("State %d transitions on:\n\t",s);
|
||||
charc = 0;
|
||||
for(i = 1; i<NCH; i++){
|
||||
if(symbol[i]) allprint(i);
|
||||
if(charc > LINESIZE){
|
||||
charc = 0;
|
||||
print("\n\t");
|
||||
}
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
# endif
|
||||
/* for each char, calculate next state */
|
||||
n = 0;
|
||||
for(i = 1; i<NCH; i++){
|
||||
if(symbol[i]){
|
||||
nextstate(s,i); /* executed for each state, transition pair */
|
||||
xstate = notin(stnum);
|
||||
if(xstate == -2) warning("bad state %d %o",s,i);
|
||||
else if(xstate == -1){
|
||||
if(stnum >= nstates)
|
||||
error("Too many states %s",(nstates == NSTATES ? "\nTry using %n num":""));
|
||||
add(state,++stnum);
|
||||
# ifdef DEBUG
|
||||
if(debug)pstate(stnum);
|
||||
# endif
|
||||
tch[n] = i;
|
||||
tst[n++] = stnum;
|
||||
} else { /* xstate >= 0 ==> state exists */
|
||||
tch[n] = i;
|
||||
tst[n++] = xstate;
|
||||
}
|
||||
}
|
||||
}
|
||||
tch[n] = 0;
|
||||
tst[n] = -1;
|
||||
/* pack transitions into permanent array */
|
||||
if(n > 0) packtrans(s,tch,tst,n,tryit);
|
||||
else gotof[s] = -1;
|
||||
}
|
||||
Bprint(&fout,"0};\n");
|
||||
}
|
||||
|
||||
/* Beware -- 70% of total CPU time is spent in this subroutine -
|
||||
if you don't believe me - try it yourself ! */
|
||||
void
|
||||
nextstate(int s, int c)
|
||||
{
|
||||
int j, *newpos;
|
||||
uchar *temp, *tz;
|
||||
int *pos, i, *f, num, curpos, number;
|
||||
/* state to goto from state s on char c */
|
||||
num = *state[s];
|
||||
temp = tmpstat;
|
||||
pos = state[s] + 1;
|
||||
for(i = 0; i<num; i++){
|
||||
curpos = *pos++;
|
||||
j = name[curpos];
|
||||
if(j < NCH && j == c
|
||||
|| j == RSTR && c == right[curpos]
|
||||
|| j == RCCL && member(c, (uchar *)left[curpos])){
|
||||
f = foll[curpos];
|
||||
number = *f;
|
||||
newpos = f+1;
|
||||
for(j=0;j<number;j++)
|
||||
temp[*newpos++] = 2;
|
||||
}
|
||||
}
|
||||
j = 0;
|
||||
tz = temp + tptr;
|
||||
while(temp < tz){
|
||||
if(*temp == 2){
|
||||
j++;
|
||||
*temp++ = 1;
|
||||
}
|
||||
else *temp++ = 0;
|
||||
}
|
||||
count = j;
|
||||
}
|
||||
|
||||
int
|
||||
notin(int n)
|
||||
{ /* see if tmpstat occurs previously */
|
||||
int *j,k;
|
||||
uchar *temp;
|
||||
int i;
|
||||
|
||||
if(count == 0)
|
||||
return(-2);
|
||||
temp = tmpstat;
|
||||
for(i=n;i>=0;i--){ /* for each state */
|
||||
j = state[i];
|
||||
if(count == *j++){
|
||||
for(k=0;k<count;k++)
|
||||
if(!temp[*j++])break;
|
||||
if(k >= count)
|
||||
return(i);
|
||||
}
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void
|
||||
packtrans(int st, uchar *tch, int *tst, int cnt, int tryit)
|
||||
{
|
||||
/* pack transitions into nchar, nexts */
|
||||
/* nchar is terminated by '\0', nexts uses cnt, followed by elements */
|
||||
/* gotof[st] = index into nchr, nexts for state st */
|
||||
|
||||
/* sfall[st] = t implies t is fall back state for st */
|
||||
/* == -1 implies no fall back */
|
||||
|
||||
int i,j,k;
|
||||
int cmin, cval, tcnt, diff, p, *ast;
|
||||
uchar *ach;
|
||||
int go[NCH], temp[NCH], c;
|
||||
int swork[NCH];
|
||||
uchar cwork[NCH];
|
||||
int upper;
|
||||
|
||||
rcount += cnt;
|
||||
cmin = -1;
|
||||
cval = NCH;
|
||||
ast = tst;
|
||||
ach = tch;
|
||||
/* try to pack transitions using ccl's */
|
||||
if(tryit){ /* ccl's used */
|
||||
for(i=1;i<NCH;i++){
|
||||
go[i] = temp[i] = -1;
|
||||
symbol[i] = 1;
|
||||
}
|
||||
for(i=0;i<cnt;i++){
|
||||
go[tch[i]] = tst[i];
|
||||
symbol[tch[i]] = 0;
|
||||
}
|
||||
for(i=0; i<cnt;i++){
|
||||
c = match[tch[i]];
|
||||
if(go[c] != tst[i] || c == tch[i])
|
||||
temp[tch[i]] = tst[i];
|
||||
}
|
||||
/* fill in error entries */
|
||||
for(i=1;i<NCH;i++)
|
||||
if(symbol[i]) temp[i] = -2; /* error trans */
|
||||
/* count them */
|
||||
k = 0;
|
||||
for(i=1;i<NCH;i++)
|
||||
if(temp[i] != -1)k++;
|
||||
if(k <cnt){ /* compress by char */
|
||||
# ifdef DEBUG
|
||||
if(debug) print("use compression %d, %d vs %d\n",st,k,cnt);
|
||||
# endif
|
||||
k = 0;
|
||||
for(i=1;i<NCH;i++)
|
||||
if(temp[i] != -1){
|
||||
cwork[k] = i;
|
||||
swork[k++] = (temp[i] == -2 ? -1 : temp[i]);
|
||||
}
|
||||
cwork[k] = 0;
|
||||
# ifdef PC
|
||||
ach = cwork;
|
||||
ast = swork;
|
||||
cnt = k;
|
||||
cpackflg[st] = TRUE;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
for(i=0; i<st; i++){ /* get most similar state */
|
||||
/* reject state with more transitions, state already represented by a third state,
|
||||
and state which is compressed by char if ours is not to be */
|
||||
if(sfall[i] != -1) continue;
|
||||
if(cpackflg[st] == 1) if(!(cpackflg[i] == 1)) continue;
|
||||
p = gotof[i];
|
||||
if(p == -1) /* no transitions */ continue;
|
||||
tcnt = nexts[p];
|
||||
if(tcnt > cnt) continue;
|
||||
diff = 0;
|
||||
j = 0;
|
||||
upper = p + tcnt;
|
||||
while(ach[j] && p < upper){
|
||||
while(ach[j] < nchar[p] && ach[j]){diff++; j++; }
|
||||
if(ach[j] == 0)break;
|
||||
if(ach[j] > nchar[p]){diff=NCH;break;}
|
||||
/* ach[j] == nchar[p] */
|
||||
if(ast[j] != nexts[++p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]]))diff++;
|
||||
j++;
|
||||
}
|
||||
while(ach[j]){
|
||||
diff++;
|
||||
j++;
|
||||
}
|
||||
if(p < upper)diff = NCH;
|
||||
if(diff < cval && diff < tcnt){
|
||||
cval = diff;
|
||||
cmin = i;
|
||||
if(cval == 0)break;
|
||||
}
|
||||
}
|
||||
/* cmin = state "most like" state st */
|
||||
# ifdef DEBUG
|
||||
if(debug)print("select st %d for st %d diff %d\n",cmin,st,cval);
|
||||
# endif
|
||||
# ifdef PS
|
||||
if(cmin != -1){ /* if we can use st cmin */
|
||||
gotof[st] = nptr;
|
||||
k = 0;
|
||||
sfall[st] = cmin;
|
||||
p = gotof[cmin]+1;
|
||||
j = 0;
|
||||
while(ach[j]){
|
||||
/* if cmin has a transition on c, then so will st */
|
||||
/* st may be "larger" than cmin, however */
|
||||
while(ach[j] < nchar[p-1] && ach[j]){
|
||||
k++;
|
||||
nchar[nptr] = ach[j];
|
||||
nexts[++nptr] = ast[j];
|
||||
j++;
|
||||
}
|
||||
if(nchar[p-1] == 0)break;
|
||||
if(ach[j] > nchar[p-1]){
|
||||
warning("bad transition %d %d",st,cmin);
|
||||
goto nopack;
|
||||
}
|
||||
/* ach[j] == nchar[p-1] */
|
||||
if(ast[j] != nexts[p] || ast[j] == -1 || (cpackflg[st] && ach[j] != match[ach[j]])){
|
||||
k++;
|
||||
nchar[nptr] = ach[j];
|
||||
nexts[++nptr] = ast[j];
|
||||
}
|
||||
p++;
|
||||
j++;
|
||||
}
|
||||
while(ach[j]){
|
||||
nchar[nptr] = ach[j];
|
||||
nexts[++nptr] = ast[j++];
|
||||
k++;
|
||||
}
|
||||
nexts[gotof[st]] = cnt = k;
|
||||
nchar[nptr++] = 0;
|
||||
} else {
|
||||
# endif
|
||||
nopack:
|
||||
/* stick it in */
|
||||
gotof[st] = nptr;
|
||||
nexts[nptr] = cnt;
|
||||
for(i=0;i<cnt;i++){
|
||||
nchar[nptr] = ach[i];
|
||||
nexts[++nptr] = ast[i];
|
||||
}
|
||||
nchar[nptr++] = 0;
|
||||
# ifdef PS
|
||||
}
|
||||
# endif
|
||||
if(cnt < 1){
|
||||
gotof[st] = -1;
|
||||
nptr--;
|
||||
} else
|
||||
if(nptr > ntrans)
|
||||
error("Too many transitions %s",(ntrans==NTRANS?"\nTry using %a num":""));
|
||||
}
|
||||
|
||||
# ifdef DEBUG
|
||||
void
|
||||
pstate(int s)
|
||||
{
|
||||
int *p,i,j;
|
||||
print("State %d:\n",s);
|
||||
p = state[s];
|
||||
i = *p++;
|
||||
if(i == 0) return;
|
||||
print("%4d",*p++);
|
||||
for(j = 1; j<i; j++){
|
||||
print(", %4d",*p++);
|
||||
if(j%30 == 0)print("\n");
|
||||
}
|
||||
print("\n");
|
||||
return;
|
||||
}
|
||||
# endif
|
||||
|
||||
int
|
||||
member(int d, uchar *t)
|
||||
{
|
||||
int c;
|
||||
uchar *s;
|
||||
|
||||
c = d;
|
||||
s = t;
|
||||
c = cindex[c];
|
||||
while(*s)
|
||||
if(*s++ == c) return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
# ifdef DEBUG
|
||||
void
|
||||
stprt(int i)
|
||||
{
|
||||
int p, t;
|
||||
|
||||
print("State %d:",i);
|
||||
/* print actions, if any */
|
||||
t = atable[i];
|
||||
if(t != -1)print(" final");
|
||||
print("\n");
|
||||
if(cpackflg[i] == TRUE)print("backup char in use\n");
|
||||
if(sfall[i] != -1)print("fall back state %d\n",sfall[i]);
|
||||
p = gotof[i];
|
||||
if(p == -1) return;
|
||||
print("(%d transitions)\n",nexts[p]);
|
||||
while(nchar[p]){
|
||||
charc = 0;
|
||||
if(nexts[p+1] >= 0)
|
||||
print("%d\t",nexts[p+1]);
|
||||
else print("err\t");
|
||||
allprint(nchar[p++]);
|
||||
while(nexts[p] == nexts[p+1] && nchar[p]){
|
||||
if(charc > LINESIZE){
|
||||
charc = 0;
|
||||
print("\n\t");
|
||||
}
|
||||
allprint(nchar[p++]);
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
# endif
|
||||
|
||||
void
|
||||
acompute(int s) /* compute action list = set of poss. actions */
|
||||
{
|
||||
int *p, i, j;
|
||||
int cnt, m;
|
||||
int temp[300], k, neg[300], n;
|
||||
|
||||
k = 0;
|
||||
n = 0;
|
||||
p = state[s];
|
||||
cnt = *p++;
|
||||
if(cnt > 300)
|
||||
error("Too many positions for one state - acompute");
|
||||
for(i=0;i<cnt;i++){
|
||||
if(name[*p] == FINAL)temp[k++] = left[*p];
|
||||
else if(name[*p] == S1FINAL){temp[k++] = left[*p];
|
||||
if (left[*p] >= NACTIONS) error("Too many right contexts");
|
||||
extra[left[*p]] = 1;
|
||||
} else if(name[*p] == S2FINAL)neg[n++] = left[*p];
|
||||
p++;
|
||||
}
|
||||
atable[s] = -1;
|
||||
if(k < 1 && n < 1) return;
|
||||
# ifdef DEBUG
|
||||
if(debug) print("final %d actions:",s);
|
||||
# endif
|
||||
/* sort action list */
|
||||
for(i=0; i<k; i++)
|
||||
for(j=i+1;j<k;j++)
|
||||
if(temp[j] < temp[i]){
|
||||
m = temp[j];
|
||||
temp[j] = temp[i];
|
||||
temp[i] = m;
|
||||
}
|
||||
/* remove dups */
|
||||
for(i=0;i<k-1;i++)
|
||||
if(temp[i] == temp[i+1]) temp[i] = 0;
|
||||
/* copy to permanent quarters */
|
||||
atable[s] = aptr;
|
||||
# ifdef DEBUG
|
||||
Bprint(&fout,"/* actions for state %d */",s);
|
||||
# endif
|
||||
Bputc(&fout, '\n');
|
||||
for(i=0;i<k;i++)
|
||||
if(temp[i] != 0){
|
||||
Bprint(&fout,"%d,\n",temp[i]);
|
||||
# ifdef DEBUG
|
||||
if(debug)
|
||||
print("%d ",temp[i]);
|
||||
# endif
|
||||
aptr++;
|
||||
}
|
||||
for(i=0;i<n;i++){ /* copy fall back actions - all neg */
|
||||
Bprint(&fout,"%d,\n",neg[i]);
|
||||
aptr++;
|
||||
# ifdef DEBUG
|
||||
if(debug)print("%d ",neg[i]);
|
||||
# endif
|
||||
}
|
||||
# ifdef DEBUG
|
||||
if(debug)print("\n");
|
||||
# endif
|
||||
Bprint(&fout,"0,\n");
|
||||
aptr++;
|
||||
return;
|
||||
}
|
||||
|
||||
# ifdef DEBUG
|
||||
void
|
||||
pccl(void) {
|
||||
/* print character class sets */
|
||||
int i, j;
|
||||
|
||||
print("char class intersection\n");
|
||||
for(i=0; i< ccount; i++){
|
||||
charc = 0;
|
||||
print("class %d:\n\t",i);
|
||||
for(j=1;j<NCH;j++)
|
||||
if(cindex[j] == i){
|
||||
allprint(j);
|
||||
if(charc > LINESIZE){
|
||||
print("\n\t");
|
||||
charc = 0;
|
||||
}
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
charc = 0;
|
||||
print("match:\n");
|
||||
for(i=0;i<NCH;i++){
|
||||
allprint(match[i]);
|
||||
if(charc > LINESIZE){
|
||||
print("\n");
|
||||
charc = 0;
|
||||
}
|
||||
}
|
||||
print("\n");
|
||||
return;
|
||||
}
|
||||
# endif
|
||||
|
||||
void
|
||||
mkmatch(void)
|
||||
{
|
||||
int i;
|
||||
uchar tab[NCH];
|
||||
|
||||
for(i=0; i<ccount; i++)
|
||||
tab[i] = 0;
|
||||
for(i=1;i<NCH;i++)
|
||||
if(tab[cindex[i]] == 0)
|
||||
tab[cindex[i]] = i;
|
||||
/* tab[i] = principal char for new ccl i */
|
||||
for(i = 1; i<NCH; i++)
|
||||
match[i] = tab[cindex[i]];
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
layout(void)
|
||||
{
|
||||
/* format and output final program's tables */
|
||||
int i, j, k;
|
||||
int top, bot, startup, omin;
|
||||
|
||||
for(i=0; i<outsize;i++)
|
||||
verify[i] = advance[i] = 0;
|
||||
omin = 0;
|
||||
yytop = 0;
|
||||
for(i=0; i<= stnum; i++){ /* for each state */
|
||||
j = gotof[i];
|
||||
if(j == -1){
|
||||
stoff[i] = 0;
|
||||
continue;
|
||||
}
|
||||
bot = j;
|
||||
while(nchar[j])j++;
|
||||
top = j - 1;
|
||||
# ifdef DEBUG
|
||||
if (debug) {
|
||||
print("State %d: (layout)\n", i);
|
||||
for(j=bot; j<=top;j++) {
|
||||
print(" %o", nchar[j]);
|
||||
if (j%10==0) print("\n");
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
# endif
|
||||
while(verify[omin+NCH]) omin++;
|
||||
startup = omin;
|
||||
# ifdef DEBUG
|
||||
if (debug) print("bot,top %d, %d startup begins %d\n",bot,top,startup);
|
||||
# endif
|
||||
do {
|
||||
startup += 1;
|
||||
if(startup > outsize - NCH)
|
||||
error("output table overflow");
|
||||
for(j = bot; j<= top; j++){
|
||||
k = startup + nchar[j];
|
||||
if(verify[k])break;
|
||||
}
|
||||
} while (j <= top);
|
||||
/* have found place */
|
||||
# ifdef DEBUG
|
||||
if (debug) print(" startup going to be %d\n", startup);
|
||||
# endif
|
||||
for(j = bot; j<= top; j++){
|
||||
k = startup + nchar[j];
|
||||
verify[k] = i+1; /* state number + 1*/
|
||||
advance[k] = nexts[j+1]+1; /* state number + 1*/
|
||||
if(yytop < k) yytop = k;
|
||||
}
|
||||
stoff[i] = startup;
|
||||
}
|
||||
|
||||
/* stoff[i] = offset into verify, advance for trans for state i */
|
||||
/* put out yywork */
|
||||
Bprint(&fout,"# define YYTYPE %s\n",stnum+1 >= NCH ? "int" : "Uchar");
|
||||
Bprint(&fout,"struct yywork { YYTYPE verify, advance; } yycrank[] = {\n");
|
||||
for(i=0;i<=yytop;i+=4){
|
||||
for(j=0;j<4;j++){
|
||||
k = i+j;
|
||||
if(verify[k])
|
||||
Bprint(&fout,"%d,%d,\t",verify[k],advance[k]);
|
||||
else
|
||||
Bprint(&fout,"0,0,\t");
|
||||
}
|
||||
Bputc(&fout, '\n');
|
||||
}
|
||||
Bprint(&fout,"0,0};\n");
|
||||
|
||||
/* put out yysvec */
|
||||
|
||||
Bprint(&fout,"struct yysvf yysvec[] = {\n");
|
||||
Bprint(&fout,"0,\t0,\t0,\n");
|
||||
for(i=0;i<=stnum;i++){ /* for each state */
|
||||
if(cpackflg[i])stoff[i] = -stoff[i];
|
||||
Bprint(&fout,"yycrank+%d,\t",stoff[i]);
|
||||
if(sfall[i] != -1)
|
||||
Bprint(&fout,"yysvec+%d,\t", sfall[i]+1); /* state + 1 */
|
||||
else Bprint(&fout,"0,\t\t");
|
||||
if(atable[i] != -1)
|
||||
Bprint(&fout,"yyvstop+%d,",atable[i]);
|
||||
else Bprint(&fout,"0,\t");
|
||||
# ifdef DEBUG
|
||||
Bprint(&fout,"\t\t/* state %d */",i);
|
||||
# endif
|
||||
Bputc(&fout, '\n');
|
||||
}
|
||||
Bprint(&fout,"0,\t0,\t0};\n");
|
||||
|
||||
/* put out yymatch */
|
||||
|
||||
Bprint(&fout,"struct yywork *yytop = yycrank+%d;\n",yytop);
|
||||
Bprint(&fout,"struct yysvf *yybgin = yysvec+1;\n");
|
||||
Bprint(&fout,"Uchar yymatch[] = {\n");
|
||||
for(i=0; i<NCH; i+=8){
|
||||
for(j=0; j<8; j++){
|
||||
int fbch;
|
||||
fbch = match[i+j];
|
||||
if(isprint(fbch) && fbch != '\'' && fbch != '\\')
|
||||
Bprint(&fout,"'%c' ,",fbch);
|
||||
else Bprint(&fout,"0%-3o,",fbch);
|
||||
}
|
||||
Bputc(&fout, '\n');
|
||||
}
|
||||
Bprint(&fout,"0};\n");
|
||||
/* put out yyextra */
|
||||
Bprint(&fout,"Uchar yyextra[] = {\n");
|
||||
for(i=0;i<casecount;i+=8){
|
||||
for(j=0;j<8;j++)
|
||||
Bprint(&fout, "%d,", i+j<NACTIONS ?
|
||||
extra[i+j] : 0);
|
||||
Bputc(&fout, '\n');
|
||||
}
|
||||
Bprint(&fout,"0};\n");
|
||||
}
|
||||
|
||||
# ifdef PP
|
||||
void
|
||||
padd(int **array, int n)
|
||||
{
|
||||
int i, *j, k;
|
||||
|
||||
array[n] = nxtpos;
|
||||
if(count == 0){
|
||||
*nxtpos++ = 0;
|
||||
return;
|
||||
}
|
||||
for(i=tptr-1;i>=0;i--){
|
||||
j = array[i];
|
||||
if(j && *j++ == count){
|
||||
for(k=0;k<count;k++)
|
||||
if(!tmpstat[*j++])break;
|
||||
if(k >= count){
|
||||
array[n] = array[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
add(array,n);
|
||||
}
|
||||
# endif
|
Loading…
Reference in a new issue