|
|
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.