# /* * Copyright (c) 1978 Charles H. Forsyth */ /* * lex -- output human- and machine-readable tables */ #include #include "lexlex.h" char strdec[] = {"\n\ struct\tlextab\t%s = {\n\ \t%d,\t/* last state */\n\ \t_D%s,\t/* defaults */\n\ \t_N%s,\t/* next */\n\ \t_C%s,\t/* check */\n\ \t_B%s,\t/* base */\n\ \t%d,\t/* last in base */\n\ \t%s,\t/* byte-int move routines */\n\ \t_F%s,\t/* final state descriptions */\n\ \t_A%s,\t/* action routine */\n\ \t%s%s,\t/* look-ahead vector */\n\ "}; nfaprint(np, base) register struct nfa *np; struct nfa *base; { register i; if (np->n_flag&NPRT) return; np->n_flag |= NPRT; fprintf(lexlog, "state %d\n", np-base); switch (np->n_char) { case EPSILON: for (i = 0; i < 2; i++) if (np->n_succ[i]) fprintf(lexlog, "\tepsilon %d\n", np->n_succ[i]-base); break; case FIN: fprintf(lexlog, "\tfinal state\n"); break; case CCL: fprintf(lexlog, "\t["); cclprint(np->n_ccl); fprintf(lexlog, "] %d\n", np->n_succ[0]-base); break; default: putc('\t', lexlog); chprint(np->n_char); fprintf(lexlog, " %d\n", np->n_succ[0]-base); break; } fprintf(lexlog, "\n"); if (np->n_succ[0]) nfaprint(np->n_succ[0], base); if (np->n_succ[1]) nfaprint(np->n_succ[1], base); } cclprint(cp) register char *cp; { register i; for (i = 0; i < NCHARS; i++) if (cp[i/NBPC]&(1<<(i%NBPC))) chprint(i); } chprint(ch) { register char *s; ch &= 0377; switch (ch) { case '\t': s = "\\t"; break; case '\n': s = "\\n"; break; case '\b': s = "\\b"; break; case '\r': s = "\\r"; break; default: fprintf(lexlog, (ch<040 || ch>=0177) ? "\\%o": "%c", ch); return; } fprintf(lexlog, s); } /* * print the minimised DFA, * and at the same time, * construct the vector which * indicates final states by * associating them with * their translation index. */ dfaprint() { register struct move *dp; register struct dfa *st; register i; int fi, k, l; vstart("int _", "F", tabname); fprintf(lexlog, "\nMinimised DFA for complete syntax\n"); for (i = 0; i < ndfa; i++) { fprintf(lexlog, "\nstate %d", i); st = &dfa[i]; k = -1; if (fi = st->df_name->s_final) { k = nfa[fi].n_trans - trans; fprintf(lexlog, " (final %d[%d],)", fi, k); if (nfa[fi].n_flag&FLOOK) { k |= (nfa[fi].n_look+1)<<11; fprintf(lexlog, " restore %d", nfa[fi].n_look); } } if (l = st->df_name->s_look) fprintf(lexlog, " look-ahead %o", l); veld(k); /* k = st->df_name->s_group->s_els[0]; if (k!=i) { fprintf(lexlog, " deleted\n"); continue; } */ fprintf(lexlog, "\n"); for (dp = st->df_base; dp < st->df_max; dp = range(st, dp)) ; if (st->df_default) fprintf(lexlog, "\t.\tsame as %d\n", st->df_default-dfa); } veld(-1); /* blocking state */ vend(); } range(st, dp) register struct dfa *st; register struct move *dp; { int low, high, last; struct set *s; register a; while (dp < st->df_max && dp->m_check!=st) dp++; if (dp >= st->df_max) return(dp); low = dp - st->df_base; /* s = dp->m_next->s_group->s_els[0]; */ s = dp->m_next; for (last = low-1; dp < st->df_max && dp->m_check==st && (a = dp - st->df_base)==last+1 && /* dp->m_next->s_state->s_els[0]==s; dp++) */ dp->m_next==s; dp++) last = a; high = last; fprintf(lexlog, "\t"); if (high==low) chprint(low); else { fprintf(lexlog, "["); if (high-low > 4) { chprint(low); fprintf(lexlog, "-"); chprint(high); } else { while (low<=high) chprint(low++); } fprintf(lexlog, "]"); } if (s == NULL || s->s_state == NULL) fprintf(lexlog, "\tNULL\n"); else fprintf(lexlog, "\t%d\n", s->s_state-dfa); return(dp); } heading() { fprintf(llout, "\ \#include \n\ \#ifdef vms\n\ \#include \"c:lex.h\"\n\ \#else\n\ \#include \n\ \#endif\n"); fprintf(llout, "extern int _lmov%c();\n", (ndfa <= 255) ? 'b' : 'i'); } llactr() { fprintf(llout, "_A%s(__na__) {\n", tabname); } newcase(i) { static int putsw; if (!putsw++) fprintf(llout, "\tswitch (__na__) {\n"); fprintf(llout, "\tcase %d:\n", i); setline(); } ending() { static int ended; if (ended++) return; fprintf(llout, "\t}\n\treturn(LEXSKIP);\n}\n"); setline(); } dfawrite() { register struct move *dp; register i, a; int k, base, nr, c; struct dfa *st, *def; struct set *xp; setline(); fprintf(llout, "\n#define\tLLTYPE1\t%s\n", ndfa<=255? "char": "int"); vstart("LLTYPE1 _", "N", tabname); for (i = 0; i <= llnxtmax; i++) if (xp = move[i].m_next) veld(xp->s_state-dfa); else veld(ndfa); vend(); vstart("LLTYPE1 _", "C", tabname); for (i = 0; i <= llnxtmax; i++) if (st = move[i].m_check) veld(st-dfa); else veld(-1); vend(); vstart("LLTYPE1 _", "D", tabname); for (i = 0; i < ndfa; i++) if (def = dfa[i].df_default) veld(def-dfa); else veld(ndfa); /* refer to blocking state */ vend(); vstart("int _", "B", tabname); for (i = 0; i < ndfa; i++) if (dp = dfa[i].df_base) veld(dp-move); else veld(0); veld(0); /* for blocking state */ vend(); if (nlook) { fprintf(llout, "char *llsave[%d];\n", nlook); vstart("int _", "L", tabname); a = nlook<=NBPC? NCHARS-1: -1; for (i = 0; i < ndfa; i++) velo(dfa[i].df_name->s_look&a); velo(0); vend(); } dospccl(ignore, "LLIGN", "X"); dospccl(breakc, "LLBRK", "Y"); dospccl(illeg, "LLILL", "Z"); fprintf(llout, strdec, tabname, ndfa, tabname, tabname, tabname, tabname, llnxtmax, ndfa<=255? "_lmovb": "_lmovi", tabname, tabname, nlook? "_L": "", nlook? tabname: "NULL"); refccl(ignore, "ignore", "X"); refccl(breakc, "break", "Y"); refccl(illeg, "illegal", "Z"); fprintf(llout, "};\n"); fclose(llout); } dospccl(cp, s, tag) register char *cp; char *s, *tag; { register n; if (cp==0) return; fprintf(llout, "#define\t%s\t%s\n", s, s); vstart("char _", tag, tabname); for (n = sizeof(ccls[0]); n--;) velo(*cp++&0377); vend(); } refccl(cp, nm, tag) char *cp, *nm, *tag; { if (cp==0) fprintf(llout, "\t0,\t/* no %s class */\n", nm); else fprintf(llout, "\t_%s%s,\t/* %s class */\n", tag, tabname, nm); } int vnl; static vstart(def, tag, name) char *def, *tag, *name; { vnl = 0; fprintf(llout, "\n%s%s%s[] = {\n", def, tag, name); } vend() { fprintf(llout, "\n};\n"); } veld(e) int e; /* * Print decimal value e */ { fprintf(llout, " %d,", e); veol(); } velo(e) int e; /* * Print octal value e */ { fprintf(llout, " 0%o,", e); veol(); } veol() /* * End of line */ { if ((++vnl & 017) == 0) fprintf(llout, "\n"); } setline() { fprintf(llout, "\n#line %d \"%s\"\n", yyline, infile); }