|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 7439 (0x1d0f)
Types: TextFile
Notes: UNIX file
Names: »lex1.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/lex/lex1.c«
/*
* lex1.c
* main and parsing routines
*/
#include "lex.h"
main(argc, argv)
char **argv;
{
register i, s;
int pflag = 0, tflag = 0, vflag = 0;
while (argc>1 && **++argv=='-') {
while (*++*argv) switch (**argv) {
case 'p':
++pflag;
break;
case 't':
++tflag;
break;
case 'v':
++vflag;
break;
default:
usage();
}
--argc;
}
if (argc > 2)
usage();
if (!tflag) {
if ((fileout=fopen(OUTFILE, "w")) == NULL)
error(opnerr, OUTFILE);
}
if (argc > 1) {
if ((filein=fopen(*argv, "r")) == NULL)
error(opnerr, *argv);
loutput(0, "#line 1 %s", *argv);
}
/*
* write header section of output
*/
loutput(0, "#include <stdio.h>");
loutput(0, "extern\tchar\t\tyytext[];");
loutput(0, "extern\tint\t\tyyleng;");
loutput(0, "extern\tint\t\tyyscon;");
loutput(0, "extern\tint\t\tyyline;");
loutput(0, "#define\tinput()\t\tgetchar()");
loutput(0, "#define\toutput(c)\tputchar(c)");
loutput(0, "#define\tunput(c)\tyyback(c)");
loutput(0, "#define\tECHO\t\t%s",
"{register n=0; while (n<yyleng) output(yytext[n++]);}");
loutput(0, "#define\tREJECT\t\tyyrjct()");
loutput(0, "#define\tBEGIN\t\tyyscon = ");
/*
* set up context and start condition lists
*/
ctxstart = alloc(sizeof(struct def));
ctxstart->d_next = NULL;
ctxstart->d_name = "0";
scnstart = alloc(sizeof(struct def));
scnstart->d_next = NULL;
scnstart->d_name = "0";
scnstart->d_data = 0;
/*
* parse definitions section
* definitions are nfa segments that get copied wherever
* they are used, classes used in definitions are stored once.
* definition nfa's start at 0, each ends with LX_TERM
*/
setltype();
indefs = 1;
yyparse();
indefs = 0;
/*
* set beginning of context 0 to where definitions end
*/
ctxstart->d_data = nxt;
/*
* write #defines for start conditions and contexts
*/
sdefns();
xdefns();
/*
* these two routines are used by the generated atuomata
* to access the user-provided i/o routines
*/
loutput(0, "_llic()");
loutput(0, "{");
loutput(1, "return (input());");
loutput(0, "}");
loutput(0, "_lloc(c)");
loutput(0, "{");
loutput(1, "output(c);");
loutput(0, "}");
/*
* parse rules section, each rule gets a case in yylex()
*/
loutput(0, "yylex()");
loutput(0, "{");
outlnum(1);
while (ltype == LN_LSPC)
lcopy();
loutput(0, "yyloop:");
loutput(1, "switch (_lltk()) {");
loutput(1, "case 0:");
loutput(2, "if (yywrap())");
loutput(3, "return (EOF);");
loutput(2, "break;");
yyparse();
loutput(1, "}");
loutput(1, "goto yyloop;\n");
loutput(0, "}");
nfa[nxt++][0] = LX_STOP;
/*
* don't need definitions anymore, copy nfa down to 0
*/
s = ctxstart->d_data;
i = 0;
while (s < nxt) {
nfa[i][0] = nfa[s][0];
nfa[i++][1] = nfa[s++][1];
}
nxt = i;
freedef(defstart);
outlnum(1);
/*
* copy the rest of the input spec through
*/
while (ltype != LN_EOFL)
lcopy();
/*
* class tables
* context table
* nfa
* workspace
*/
btable();
xtable();
ptable();
ltable();
if (pflag) {
printnfa();
}
if (vflag)
stats();
fclose(fileout);
}
/*
* interpret input according to type of line
*/
yyparse()
{
register s = nxt;
register struct def *nd, *pd = NULL;
register char *pc;
for (;;) switch (ltype) {
case LN_DFLT:
if (indefs) {
s = nxt;
pc = getident();
rexparse(0);
nfa[nxt++][0] = LX_TERM;
nd = alloc(sizeof(struct def));
if (pd != NULL)
pd->d_next = nd;
else
defstart = nd;
pd = nd;
pd->d_name = pc;
pd->d_data = s;
pd->d_next = NULL;
if (yylval != '\n')
dnl();
else
setltype();
} else {
if (look(0) == '<') {
next();
inscons();
if (next() != '>')
error("%s in start list", illchr);
}
if (look(0) == '^') {
next();
nfa[nxt++][0] = LX_BLIN;
}
rexparse(0);
if (yylval == '/') {
nfa[nxt++][0] = LX_LOOK;
rexparse(0);
}
switch (yylval) {
case '$':
nfa[nxt++][0] = LX_ELIN;
break;
case ' ':
case '\t':
break;
case '\n':
error(noactn);
default:
error(rulsyn);
}
nfa[nxt][0] = LX_ACPT;
nfa[nxt++][1] = ++actn;
loutput(1, "case 0%o:", actn);
outlnum(0);
eatspc();
if (look(0) == '\n')
error(noactn);
if (look(0) == '|')
dnl();
else {
output("\t\t");
getactn();
loutput(2, "break;");
}
nfalink(s);
s = nxt;
while (ltype == LN_LSPC)
lcopy();
}
break;
case LN_LSPC:
outlnum(1);
while (lcopy(), ltype==LN_LSPC);
break;
case LN_CTXT:
if (indefs)
addcontext();
else {
nfa[nxt++][0] = LX_STOP;
markcontext(nxt - ctxstart->d_data);
s = nxt;
}
dnl();
break;
case LN_SCON:
if (!indefs)
error(illstc);
addstart();
dnl();
break;
case LN_LCOM:
dnl();
outlnum(1);
while (ltype != LN_RCOM)
lcopy();
dnl();
break;
case LN_OPTN:
dnl();
break;
case LN_DLIM:
dnl();
return;
case LN_EOFL:
if (indefs)
error(eoferr);
return;
}
}
/*
* parse regular expressions into nfa segments
*/
rexparse(p)
{
register c, t, s;
s = nxt;
for (c=yylex(); c!=LX_TERM; c=nfaclose(t)) {
t = nxt;
if (c != LX_OPER) {
nfa[nxt][0] = c;
nfa[nxt++][1] = yylval;
} else switch (c=yylval) {
case '|':
nfa[t=nxt++][0] = LX_JUMP;
nfalink(s);
c = rexparse(p);
++t;
nfa[t][1] = nxt - t;
return (c);
case '"':
if (!inquotes)
return (p);
case '(':
if (rexparse(c) == c)
break;
error(unmopr, c);
case ')':
if (p)
return (p);
error(unmopr, c);
case '{':
for (c=getdefn(); nfa[c][0]!=LX_TERM; ++c) {
nfa[nxt][0] = nfa[c][0];
nfa[nxt][1] = nfa[c][1];
++nxt;
}
break;
default:
error(regsyn);
}
}
return (c);
}
/*
* look for and apply a closure operator to the
* nfa segement starting at t, ending at nxt
*/
nfaclose(t)
register t;
{
register c;
int v0, v1;
if ((c=yylex()) == LX_OPER) switch (yylval) {
case '*':
case '+':
nfa[nxt][0] = LX_LINK;
nfa[nxt][1] = t - nxt;
++nxt;
case '?':
if (yylval != '+')
nfalink(t);
c = yylex();
break;
case '{':
if (!isdigit(look(0)))
break;
v0 = v1 = 0;
do {
v0 *= 10;
v0 += next()-'0';
} while (isdigit(look(0)));
if (look(0) == ',') {
next();
while (isdigit(look(0))) {
v1 *= 10;
v1 += next()-'0';
}
v1 -= v0;
} else
v1 = 0;
if (next()!='}' || v0<0 || v1<0)
error(reperr);
if (v0) {
while (--v0)
t = nfacopy(t);
if (v1)
t = nfacopy(t);
} else if (v1 == 0)
while (--nxt > t)
nfa[nxt][0] = nfa[nxt][1] = 0;
if (v1) {
nfalink(t);
c = (nxt - t) * v1 + t;
nfa[t][1] = c - t;
while (--v1) {
t = nfacopy(t);
nfa[t][1] = c - t;
}
}
c = yylex();
}
return (c);
}
/*
* create an epsilon transition at nfa state s to nxt
*/
nfalink(s)
register s;
{
register i, j;
j = nxt++;
while ((i=j--) > s) {
nfa[i][0] = nfa[j][0];
nfa[i][1] = nfa[j][1];
}
nfa[s][0] = LX_LINK;
nfa[s][1] = nxt - s;
}
/*
* replicate the nfa segment starting at t ending at nxt
*/
nfacopy(t)
register t;
{
register s;
for (s=nxt; t<s; ++t,++nxt) {
nfa[nxt][0] = nfa[t][0];
nfa[nxt][1] = nfa[t][1];
}
return (t);
}
/*
* insert conditional epsilon transitions for
* each applicable start condition
*/
inscons()
{
register t;
nfa[nxt][0] = LX_SCON;
nfa[t=nxt++][1] = getstart();
if (look(0) == ',') {
next();
nfa[nxt++][0] = LX_JUMP;
nfalink(t++);
inscons();
++t;
nfa[t][1] = nxt - t;
}
}