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