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
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue