From e37302c4b99f147f1fd85ca27a2dbd2aa7a4eb41 Mon Sep 17 00:00:00 2001 From: wkj Date: Wed, 21 Apr 2004 01:22:09 +0000 Subject: Plan 9 lex (to be installed as lex.9, if at all). --- src/cmd/lex/sub2.c | 856 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 856 insertions(+) create mode 100644 src/cmd/lex/sub2.c (limited to 'src/cmd/lex/sub2.c') diff --git a/src/cmd/lex/sub2.c b/src/cmd/lex/sub2.c new file mode 100644 index 00000000..f9950a8d --- /dev/null +++ b/src/cmd/lex/sub2.c @@ -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= 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= 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= 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 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 LINESIZE){ + charc = 0; + print("\n\t"); + } + } + print("\n"); + } +# endif + /* for each char, calculate next state */ + n = 0; + for(i = 1; i= 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=0;i--){ /* for each state */ + j = state[i]; + if(count == *j++){ + for(k=0;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 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 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= 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= 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 LINESIZE){ + print("\n\t"); + charc = 0; + } + } + print("\n"); + } + charc = 0; + print("match:\n"); + for(i=0;i LINESIZE){ + print("\n"); + charc = 0; + } + } + print("\n"); + return; +} +# endif + +void +mkmatch(void) +{ + int i; + uchar tab[NCH]; + + for(i=0; i 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=0;i--){ + j = array[i]; + if(j && *j++ == count){ + for(k=0;k= count){ + array[n] = array[i]; + return; + } + } + } + add(array,n); +} +# endif -- cgit v1.2.3