|
|
1.1 ! root 1: /* ! 2: * lex1.c ! 3: * main and parsing routines ! 4: */ ! 5: #include "lex.h" ! 6: ! 7: main(argc, argv) ! 8: char **argv; ! 9: { ! 10: register i, s; ! 11: int pflag = 0, tflag = 0, vflag = 0; ! 12: ! 13: while (argc>1 && **++argv=='-') { ! 14: while (*++*argv) switch (**argv) { ! 15: case 'p': ! 16: ++pflag; ! 17: break; ! 18: case 't': ! 19: ++tflag; ! 20: break; ! 21: case 'v': ! 22: ++vflag; ! 23: break; ! 24: default: ! 25: usage(); ! 26: } ! 27: --argc; ! 28: } ! 29: if (argc > 2) ! 30: usage(); ! 31: if (!tflag) { ! 32: if ((fileout=fopen(OUTFILE, "w")) == NULL) ! 33: error(opnerr, OUTFILE); ! 34: } ! 35: if (argc > 1) { ! 36: if ((filein=fopen(*argv, "r")) == NULL) ! 37: error(opnerr, *argv); ! 38: loutput(0, "#line 1 %s", *argv); ! 39: } ! 40: /* ! 41: * write header section of output ! 42: */ ! 43: loutput(0, "#include <stdio.h>"); ! 44: loutput(0, "extern\tchar\t\tyytext[];"); ! 45: loutput(0, "extern\tint\t\tyyleng;"); ! 46: loutput(0, "extern\tint\t\tyyscon;"); ! 47: loutput(0, "extern\tint\t\tyyline;"); ! 48: loutput(0, "#define\tinput()\t\tgetchar()"); ! 49: loutput(0, "#define\toutput(c)\tputchar(c)"); ! 50: loutput(0, "#define\tunput(c)\tyyback(c)"); ! 51: loutput(0, "#define\tECHO\t\t%s", ! 52: "{register n=0; while (n<yyleng) output(yytext[n++]);}"); ! 53: loutput(0, "#define\tREJECT\t\tyyrjct()"); ! 54: loutput(0, "#define\tBEGIN\t\tyyscon = "); ! 55: /* ! 56: * set up context and start condition lists ! 57: */ ! 58: ctxstart = alloc(sizeof(struct def)); ! 59: ctxstart->d_next = NULL; ! 60: ctxstart->d_name = "0"; ! 61: scnstart = alloc(sizeof(struct def)); ! 62: scnstart->d_next = NULL; ! 63: scnstart->d_name = "0"; ! 64: scnstart->d_data = 0; ! 65: /* ! 66: * parse definitions section ! 67: * definitions are nfa segments that get copied wherever ! 68: * they are used, classes used in definitions are stored once. ! 69: * definition nfa's start at 0, each ends with LX_TERM ! 70: */ ! 71: setltype(); ! 72: indefs = 1; ! 73: yyparse(); ! 74: indefs = 0; ! 75: /* ! 76: * set beginning of context 0 to where definitions end ! 77: */ ! 78: ctxstart->d_data = nxt; ! 79: /* ! 80: * write #defines for start conditions and contexts ! 81: */ ! 82: sdefns(); ! 83: xdefns(); ! 84: /* ! 85: * these two routines are used by the generated atuomata ! 86: * to access the user-provided i/o routines ! 87: */ ! 88: loutput(0, "_llic()"); ! 89: loutput(0, "{"); ! 90: loutput(1, "return (input());"); ! 91: loutput(0, "}"); ! 92: loutput(0, "_lloc(c)"); ! 93: loutput(0, "{"); ! 94: loutput(1, "output(c);"); ! 95: loutput(0, "}"); ! 96: /* ! 97: * parse rules section, each rule gets a case in yylex() ! 98: */ ! 99: loutput(0, "yylex()"); ! 100: loutput(0, "{"); ! 101: outlnum(1); ! 102: while (ltype == LN_LSPC) ! 103: lcopy(); ! 104: loutput(0, "yyloop:"); ! 105: loutput(1, "switch (_lltk()) {"); ! 106: loutput(1, "case 0:"); ! 107: loutput(2, "if (yywrap())"); ! 108: loutput(3, "return (EOF);"); ! 109: loutput(2, "break;"); ! 110: yyparse(); ! 111: loutput(1, "}"); ! 112: loutput(1, "goto yyloop;\n"); ! 113: loutput(0, "}"); ! 114: nfa[nxt++][0] = LX_STOP; ! 115: /* ! 116: * don't need definitions anymore, copy nfa down to 0 ! 117: */ ! 118: s = ctxstart->d_data; ! 119: i = 0; ! 120: while (s < nxt) { ! 121: nfa[i][0] = nfa[s][0]; ! 122: nfa[i++][1] = nfa[s++][1]; ! 123: } ! 124: nxt = i; ! 125: freedef(defstart); ! 126: outlnum(1); ! 127: /* ! 128: * copy the rest of the input spec through ! 129: */ ! 130: while (ltype != LN_EOFL) ! 131: lcopy(); ! 132: /* ! 133: * class tables ! 134: * context table ! 135: * nfa ! 136: * workspace ! 137: */ ! 138: btable(); ! 139: xtable(); ! 140: ptable(); ! 141: ltable(); ! 142: if (pflag) { ! 143: printnfa(); ! 144: } ! 145: if (vflag) ! 146: stats(); ! 147: fclose(fileout); ! 148: } ! 149: ! 150: /* ! 151: * interpret input according to type of line ! 152: */ ! 153: yyparse() ! 154: { ! 155: register s = nxt; ! 156: register struct def *nd, *pd = NULL; ! 157: register char *pc; ! 158: ! 159: for (;;) switch (ltype) { ! 160: case LN_DFLT: ! 161: if (indefs) { ! 162: s = nxt; ! 163: pc = getident(); ! 164: rexparse(0); ! 165: nfa[nxt++][0] = LX_TERM; ! 166: nd = alloc(sizeof(struct def)); ! 167: if (pd != NULL) ! 168: pd->d_next = nd; ! 169: else ! 170: defstart = nd; ! 171: pd = nd; ! 172: pd->d_name = pc; ! 173: pd->d_data = s; ! 174: pd->d_next = NULL; ! 175: if (yylval != '\n') ! 176: dnl(); ! 177: else ! 178: setltype(); ! 179: } else { ! 180: if (look(0) == '<') { ! 181: next(); ! 182: inscons(); ! 183: if (next() != '>') ! 184: error("%s in start list", illchr); ! 185: } ! 186: if (look(0) == '^') { ! 187: next(); ! 188: nfa[nxt++][0] = LX_BLIN; ! 189: } ! 190: rexparse(0); ! 191: if (yylval == '/') { ! 192: nfa[nxt++][0] = LX_LOOK; ! 193: rexparse(0); ! 194: } ! 195: switch (yylval) { ! 196: case '$': ! 197: nfa[nxt++][0] = LX_ELIN; ! 198: break; ! 199: case ' ': ! 200: case '\t': ! 201: break; ! 202: case '\n': ! 203: error(noactn); ! 204: default: ! 205: error(rulsyn); ! 206: } ! 207: nfa[nxt][0] = LX_ACPT; ! 208: nfa[nxt++][1] = ++actn; ! 209: loutput(1, "case 0%o:", actn); ! 210: outlnum(0); ! 211: eatspc(); ! 212: if (look(0) == '\n') ! 213: error(noactn); ! 214: if (look(0) == '|') ! 215: dnl(); ! 216: else { ! 217: output("\t\t"); ! 218: getactn(); ! 219: loutput(2, "break;"); ! 220: } ! 221: nfalink(s); ! 222: s = nxt; ! 223: while (ltype == LN_LSPC) ! 224: lcopy(); ! 225: } ! 226: break; ! 227: case LN_LSPC: ! 228: outlnum(1); ! 229: while (lcopy(), ltype==LN_LSPC); ! 230: break; ! 231: case LN_CTXT: ! 232: if (indefs) ! 233: addcontext(); ! 234: else { ! 235: nfa[nxt++][0] = LX_STOP; ! 236: markcontext(nxt - ctxstart->d_data); ! 237: s = nxt; ! 238: } ! 239: dnl(); ! 240: break; ! 241: case LN_SCON: ! 242: if (!indefs) ! 243: error(illstc); ! 244: addstart(); ! 245: dnl(); ! 246: break; ! 247: case LN_LCOM: ! 248: dnl(); ! 249: outlnum(1); ! 250: while (ltype != LN_RCOM) ! 251: lcopy(); ! 252: dnl(); ! 253: break; ! 254: case LN_OPTN: ! 255: dnl(); ! 256: break; ! 257: case LN_DLIM: ! 258: dnl(); ! 259: return; ! 260: case LN_EOFL: ! 261: if (indefs) ! 262: error(eoferr); ! 263: return; ! 264: } ! 265: } ! 266: ! 267: /* ! 268: * parse regular expressions into nfa segments ! 269: */ ! 270: rexparse(p) ! 271: { ! 272: register c, t, s; ! 273: ! 274: s = nxt; ! 275: for (c=yylex(); c!=LX_TERM; c=nfaclose(t)) { ! 276: t = nxt; ! 277: if (c != LX_OPER) { ! 278: nfa[nxt][0] = c; ! 279: nfa[nxt++][1] = yylval; ! 280: } else switch (c=yylval) { ! 281: case '|': ! 282: nfa[t=nxt++][0] = LX_JUMP; ! 283: nfalink(s); ! 284: c = rexparse(p); ! 285: ++t; ! 286: nfa[t][1] = nxt - t; ! 287: return (c); ! 288: case '"': ! 289: if (!inquotes) ! 290: return (p); ! 291: case '(': ! 292: if (rexparse(c) == c) ! 293: break; ! 294: error(unmopr, c); ! 295: case ')': ! 296: if (p) ! 297: return (p); ! 298: error(unmopr, c); ! 299: case '{': ! 300: for (c=getdefn(); nfa[c][0]!=LX_TERM; ++c) { ! 301: nfa[nxt][0] = nfa[c][0]; ! 302: nfa[nxt][1] = nfa[c][1]; ! 303: ++nxt; ! 304: } ! 305: break; ! 306: default: ! 307: error(regsyn); ! 308: } ! 309: } ! 310: return (c); ! 311: } ! 312: ! 313: /* ! 314: * look for and apply a closure operator to the ! 315: * nfa segement starting at t, ending at nxt ! 316: */ ! 317: nfaclose(t) ! 318: register t; ! 319: { ! 320: register c; ! 321: int v0, v1; ! 322: ! 323: if ((c=yylex()) == LX_OPER) switch (yylval) { ! 324: case '*': ! 325: case '+': ! 326: nfa[nxt][0] = LX_LINK; ! 327: nfa[nxt][1] = t - nxt; ! 328: ++nxt; ! 329: case '?': ! 330: if (yylval != '+') ! 331: nfalink(t); ! 332: c = yylex(); ! 333: break; ! 334: case '{': ! 335: if (!isdigit(look(0))) ! 336: break; ! 337: v0 = v1 = 0; ! 338: do { ! 339: v0 *= 10; ! 340: v0 += next()-'0'; ! 341: } while (isdigit(look(0))); ! 342: if (look(0) == ',') { ! 343: next(); ! 344: while (isdigit(look(0))) { ! 345: v1 *= 10; ! 346: v1 += next()-'0'; ! 347: } ! 348: v1 -= v0; ! 349: } else ! 350: v1 = 0; ! 351: if (next()!='}' || v0<0 || v1<0) ! 352: error(reperr); ! 353: if (v0) { ! 354: while (--v0) ! 355: t = nfacopy(t); ! 356: if (v1) ! 357: t = nfacopy(t); ! 358: } else if (v1 == 0) ! 359: while (--nxt > t) ! 360: nfa[nxt][0] = nfa[nxt][1] = 0; ! 361: if (v1) { ! 362: nfalink(t); ! 363: c = (nxt - t) * v1 + t; ! 364: nfa[t][1] = c - t; ! 365: while (--v1) { ! 366: t = nfacopy(t); ! 367: nfa[t][1] = c - t; ! 368: } ! 369: } ! 370: c = yylex(); ! 371: } ! 372: return (c); ! 373: } ! 374: ! 375: /* ! 376: * create an epsilon transition at nfa state s to nxt ! 377: */ ! 378: nfalink(s) ! 379: register s; ! 380: { ! 381: register i, j; ! 382: ! 383: j = nxt++; ! 384: while ((i=j--) > s) { ! 385: nfa[i][0] = nfa[j][0]; ! 386: nfa[i][1] = nfa[j][1]; ! 387: } ! 388: nfa[s][0] = LX_LINK; ! 389: nfa[s][1] = nxt - s; ! 390: } ! 391: ! 392: /* ! 393: * replicate the nfa segment starting at t ending at nxt ! 394: */ ! 395: nfacopy(t) ! 396: register t; ! 397: { ! 398: register s; ! 399: ! 400: for (s=nxt; t<s; ++t,++nxt) { ! 401: nfa[nxt][0] = nfa[t][0]; ! 402: nfa[nxt][1] = nfa[t][1]; ! 403: } ! 404: return (t); ! 405: } ! 406: ! 407: /* ! 408: * insert conditional epsilon transitions for ! 409: * each applicable start condition ! 410: */ ! 411: inscons() ! 412: { ! 413: register t; ! 414: ! 415: nfa[nxt][0] = LX_SCON; ! 416: nfa[t=nxt++][1] = getstart(); ! 417: if (look(0) == ',') { ! 418: next(); ! 419: nfa[nxt++][0] = LX_JUMP; ! 420: nfalink(t++); ! 421: inscons(); ! 422: ++t; ! 423: nfa[t][1] = nxt - t; ! 424: } ! 425: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.