|
|
1.1 root 1: %term ERROR
2: %{
3: #include "common.h"
4: #include "code.h"
5: #include "sym.h"
6: #define UNDEFINED -1
7: #define GIVENUP -2
8:
9: int debug_flag = 0;
10: int Dflag = 0;
11: int tflag = 0;
12: int line_xref_flag = 0;
13: int ntrees = 0;
14: int nerrors = 0;
15: int fatalerrors = 0;
16: int tree_lineno;
17: FILE *outfile;
18: FILE *symfile;
19: Code *epilogue;
20:
21: SymbolEntry ErrorSymbol;
22: %}
23: %union {
24: Node *y_nodep;
25: SymbolEntry *y_symp;
26: Code *y_code;
27: int y_int;
28: }
29: %start pattern_spec
30: %term K_NODE K_LABEL K_PROLOGUE K_CONST K_INSERT
31: %term K_COST K_ACTION
32: %token <y_symp> ID
33: %token <y_int> NUMBER
34: %token <y_code> CBLOCK
35: %type <y_nodep> tree tree_list
36: %type <y_symp> id_list label assoc_list assoc assoc_list2 assoc2
37: %type <y_symp> const_list const_def
38: %type <y_int> arity_spec constant
39: %type <y_symp> action cost
40: %%
41:
42: pattern_spec: declarations patternsOrInserts =
43: { if (nerrors==0) machine_build(); };
44:
45: declarations: declarations decl
46: | decl;
47:
48: decl: K_NODE assoc_list ';' = { SymbolEnterList ($2, A_NODE); }
49:
50: | K_NODE assoc_list2 ';'
51: = {
52: SymbolEnterList($2, A_NODE);
53: SymbolCheckNodeValues();
54: }
55:
56: | K_CONST const_list ';' = { SymbolEnterList ($2, A_CONST); }
57:
58: | K_LABEL id_list ';' = { SymbolEnterList ($2, A_LABEL); }
59:
60: | K_PROLOGUE CBLOCK ';' = { CodeWrite(outfile, $2); CodeFreeBlock($2); }
61:
62: | K_COST ID CBLOCK ';'
63: = { $2->sd.ca.code = $3; $2->sd.ca.assoc = NULL;
64: SymbolEnter ($2, A_COST); }
65:
66: | K_ACTION ID CBLOCK ';'
67: = { $2->sd.ca.code = $3; $2->sd.ca.assoc = NULL;
68: SymbolEnter ($2, A_ACTION); }
69:
70: | K_PROLOGUE error ';'
71: | K_ACTION error ';'
72: | K_COST error ';'
73: ;
74:
75: /*
76: * The rule id_list, assoc_list, and const_list build lists of identifiers.
77: * The field "next" is used as a link. This field is also used by the symbol
78: * table manager and thus the next field may not be used unless the identifiers
79: * have not already been defined.
80: */
81:
82: id_list:
83: id_list ID = {
84: if(CheckIsUndefined($2)) {
85: $2->next = $1;
86: $$ = $2;
87: } else $$ = $1;
88: }
89: | ID { if(CheckIsUndefined($1)) $$ = $1; else $$ = NULL; }
90: | id_list error;
91:
92: /*
93: * Assoc_list2 allows user assignment of node values
94: */
95: assoc_list2:
96: assoc_list2 assoc2
97: = {
98: if($2->attr==A_ERROR)
99: $$ = $1;
100: else { $2->next = $1; $$ = $2; }
101: }
102: | assoc2 { $$ = $1->attr==A_ERROR ? NULL : $1; }
103: | assoc_list2 error;
104:
105: assoc_list:
106: assoc_list assoc = {
107: if($2->attr==A_ERROR) $$ = $1;
108: else { $2->next = $1; $$ = $2; }
109: }
110: | assoc { $$ = $1->attr==A_ERROR ? NULL : $1; }
111: | assoc_list error;
112:
113: assoc: ID arity_spec
114: = {
115: if (CheckIsUndefined($1)) {
116: $1->sd.arity = $2; $$ = $1;
117: } else $$ = &ErrorSymbol;
118: };
119:
120: assoc2:
121: ID arity_spec '=' constant {
122: if(CheckIsUndefined($1)) {
123: $1->unique = $4; $1->sd.arity = $2;
124: $$ = $1;
125: } else $$ = &ErrorSymbol;
126: };
127:
128: arity_spec:
129: '(' constant ')' = { $$ = $2; };
130: | '(' '*' ')' = { $$=GIVENUP; };
131: | = { $$ = UNDEFINED; };
132:
133: const_list:
134: const_list const_def = {
135: if ($2->attr==A_ERROR) $$ = $1;
136: else { $2->next = $1; $$ = $2; }
137: }
138: | const_def { $$ = $1->attr==A_ERROR ? NULL : $1; }
139: | const_list error;
140:
141: const_def:
142: ID '=' constant = {
143: if(CheckIsUndefined($1)) {
144: $1->sd.cvalue = $3; $$ = $1;
145: } else $$ = &ErrorSymbol;
146: };
147:
148: constant:
149: NUMBER
150: | ID = {
151: if(!CheckIsDefined($1)) $$ = UNDEFINED;
152: else if($1->attr!=A_CONST) {
153: sem_error("non-constant id used");
154: $$ = -1;
155: } else $$ = $1->sd.cvalue;
156: };
157:
158: patternsOrInserts: patternsOrInserts pattern
159: | patternsOrInserts insert
160: | insert
161: | pattern
162: ;
163:
164: insert: K_INSERT CBLOCK ';' = { epilogue = CodeAppend(epilogue, $2); }
165: | K_INSERT error ';'
166: ;
167:
168: pattern:
169: label ':' tree cost action ';' = {
170: if ($1->attr==A_ERROR) {
171: error(0, "\"label: tree\" pair ignored");
172: TreeFree($3);
173: } else {
174: if(nerrors==0)
175: cgotofn(SymbolEnterTreeIntoLabel($1,
176: $3, $4, $5, tree_lineno));
177: if(debug_flag&DB_TREE)
178: TreePrint($3, 1);
179: }
180: }
181: | error ';' ;
182:
183: action: '=' CBLOCK { SymbolEntry *sp = SymbolAllocate (SymbolGenUnique());
184: sp->sd.ca.code = $2; sp->sd.ca.assoc = NULL;
185: SymbolEnter(sp, A_ACTION); $$ = sp; }
186: | '=' ID { if(CheckIsDefined($2)) {
187: if ($2->attr!=A_ACTION) {
188: sem_error ("non action id: %s", $2->name);
189: $$ = &ErrorSymbol;
190: } else $$ = $2;
191: } else $$ = &ErrorSymbol; }
192: | { $$ = NULL;};
193:
194: cost: CBLOCK { SymbolEntry *sp = SymbolAllocate (SymbolGenUnique());
195: sp->sd.ca.code = $1; sp->sd.ca.assoc = NULL;
196: SymbolEnter (sp, A_COST); $$ = sp;
197: }
198: | ID { if (CheckIsDefined($1)) {
199: if ($1->attr!=A_COST) {
200: sem_error ("non cost id: %s", $1->name);
201: $$ = &ErrorSymbol;
202: } else $$ = $1;
203: } else $$ = &ErrorSymbol; }
204: | { $$ = NULL; };
205:
206: /* labels play the same role that non-terminals do in YACC */
207: label: ID = {
208: tree_lineno = yyline; /* record line no */
209: if(!CheckIsDefined($1))
210: $1->attr = A_ERROR;
211: else if(!is_label($1)) {
212: sem_error("non label id: %s", $1->name);
213: $1->attr = A_ERROR;
214: }
215: $$ = $1;
216: };
217:
218: tree: ID {CheckIsNodeOrPred($1);} '(' tree_list ')'
219: = {
220: int count;
221: Node *ap;
222: /* check the arity of the node */
223: for(count=0, ap = $4; ap!=NULL; ap=ap->siblings) count++;
224: switch($1->attr) {
225: case A_NODE:
226: set_arity($1, &$1->sd.arity, count);
227: break;
228: }
229:
230: $$ = TreeBuild ($1, $4);
231: }
232: | ID
233: = {
234: CheckIsDefined($1);
235: switch ($1->attr) {
236: case A_NODE:
237: set_arity($1, &$1->sd.arity, 0);
238: break;
239: }
240: $$ = TreeBuild ($1, NULL);
241: };
242:
243: tree_list: tree_list ',' tree = {
244: /*
245: * build sibling list in reverse order TreeBuild will
246: * put it right later.
247: */
248: $3->siblings = $1;
249: $$ = $3;
250: }
251: | tree = { $1->siblings = NULL; $$ = $1; }
252: | error { $$ = NULL; };
253: | tree_list error;
254:
255: %%
256:
257: extern char *process_suffix();
258:
259: set_arity(symp, arityp, count)
260: SymbolEntry *symp;
261: int *arityp;
262: int count;
263: {
264: if(*arityp!=GIVENUP) {
265: if (*arityp==UNDEFINED)
266: *arityp = count;
267: else if (*arityp!=count) {
268: sem_error("inconsistent arity for %s", symp->name);
269: *arityp = GIVENUP;
270: }
271: }
272: }
273:
274: is_node(symp)
275: SymbolEntry *symp;
276: { return(symp->attr==A_NODE); }
277:
278: is_label(symp)
279: SymbolEntry *symp;
280: { return(symp->attr==A_LABEL); }
281:
282: CheckIsNodeOrPred (symp)
283: SymbolEntry *symp;
284: {
285: if (symp->attr==A_ERROR)
286: return;
287: if (symp->attr!=A_NODE)
288: sem_error ("non-node identifier %s", symp->name);
289: }
290:
291: CheckIsUndefined(symp)
292: SymbolEntry *symp;
293: {
294: if (symp->attr==A_ERROR)
295: return(0);
296: if (symp->attr!=A_UNDEFINED) {
297: sem_error ("multiple declaration: %s", symp->name);
298: return(0);
299: } else return(1);
300: }
301:
302: CheckIsDefined(symp)
303: SymbolEntry *symp;
304: {
305: if (symp->attr==A_ERROR)
306: return(0);
307: if (symp->attr==A_UNDEFINED) {
308: sem_error ("undefined identifier: %s", symp->name);
309: symp->attr=A_ERROR;
310: return(0);
311: } else return(1);
312: }
313:
314:
315:
316: /*VARARGS*/
317: yyerror(fmt, s1, s2, s3)
318: char *fmt, *s1, *s2, *s3;
319: {
320: fprintf(stderr, "line %d: ", yyline);
321: fprintf(stderr, fmt, s1, s2, s3);
322: if (token_buffer[0]!=0)
323: fprintf(stderr, " at \"%s\"\n", token_buffer);
324: }
325:
326: /*VARARGS*/
327: yyerror2 (fmt, s1, s2, s3)
328: char *fmt, *s1, *s2, *s3;
329: {
330: fprintf(stderr, "line %d: ", yyline);
331: fprintf(stderr, fmt, s1, s2, s3);
332: putchar('\n');
333: }
334:
335: char *cmdnam;
336: char *inFileName;
337: char *outFileName;
338: char prefixFile[100];
339: static char usage[] = "usage: mt [-d] file";
340: #define USAGE error(1, usage)
341: char *prefix_base = PREFIX_BASE;
342: char *suffix = "c1";
343:
344: main(argc, argv)
345: int argc;
346: char **argv;
347: {
348: int i;
349: char *cp;
350:
351: #ifndef PREFIX_BASE
352: error(1,"PREFIX_BASE has not been defined; recompile twig");
353: #endif
354:
355: cmdnam = argv[0];
356: argv++;
357: inFileName = NULL;
358:
359: while(--argc > 0) {
360: if (*argv[0]=='-')
361: switch(argv[0][1]) {
362: /* to see what each of these flags mean...
363: * see common.h */
364: case 'd': {
365: char *cp;
366: for(cp = &argv[0][2]; *cp!='\0'; cp++)
367: switch(*cp) {
368: case 'l': debug_flag |= DB_LEX; break;
369: case 'm': debug_flag |= DB_MACH; break;
370: case 's': debug_flag |= DB_SYM; break;
371: case 't': debug_flag |= DB_TREE; break;
372: case 'M': debug_flag |= DB_MEM; break;
373: }
374: }
375: break;
376: case 'D': Dflag++; break;
377: case 't': tflag++; break;
378: case 'w': suffix = process_suffix(&argv[0][2]); break;
379: case 'l': prefix_base = &argv[0][2]; break;
380: case 'x': line_xref_flag++; break;
381: default:
382: USAGE;
383: }
384: else inFileName = argv[0];
385: argv++;
386: }
387: if(inFileName==NULL)
388: USAGE;
389:
390: if(freopen(inFileName, "r", stdin)==NULL)
391: error(1, "can't open %s", inFileName);
392: if((cp=strrchr(inFileName, '.'))!=NULL && strcmp(cp,".mt")==0) {
393: if ((outfile = fopen("walker.c" , "w"))==NULL)
394: error(1, "can't write %s", outFileName);
395: if ((symfile = fopen("symbols.h", "w"))==NULL)
396: error(1, "can't write %s", outFileName);
397: } else error(1, "input file must have suffix .mt");
398:
399: ErrorSymbol.attr = A_LABEL;
400: TreeInit();
401: SymbolInit();
402: LexInit();
403: yyparse();
404:
405: SymbolDump();
406: if(nerrors == 0) {
407: if(!tflag) {
408: FILE *prefix;
409: char c;
410: sprintf(prefixFile, "%s.%s", prefix_base, suffix);
411: prefix = fopen(prefixFile, "r");
412: assert(prefix!=NULL);
413: if(Dflag)
414: fputs("#define DEBUG 1\n", outfile);
415: if(line_xref_flag)
416: fputs("#define LINE_XREF 1\n", outfile);
417: fprintf(outfile,"# line 1 \"%s\"\n", prefixFile);
418: while((c=getc(prefix))!=EOF) putc(c, outfile);
419: }
420: MachineGen();
421: SymbolGenerateWalkerCode();
422: CodeWrite(outfile, epilogue);
423: CodeFreeBlock(epilogue);
424: }
425:
426: /* cleanup */
427: cleanup(0);
428: }
429:
430: cleanup(retcode)
431: int retcode;
432: {
433: lexCleanup();
434: if(retcode==0) {
435: SymbolFinish();
436: }
437: exit(retcode);
438: }
439:
440: /*VARARGS*/
441: error(rc, fmt, a1, a2, a3)
442: int rc;
443: char *fmt, *a1, *a2, *a3;
444: {
445: fprintf(stderr, "%s: ", cmdnam);
446: fprintf(stderr, fmt, a1, a2, a3);
447: putc ('\n', stderr);
448: if(rc)
449: exit (rc);
450: }
451:
452: /*VARARGS*/
453: sem_error (fmt, a1, a2, a3)
454: char *fmt, *a1, *a2, *a3;
455: {
456: fprintf (stderr, "line %d: ", yyline);
457: sem_error2(fmt, a1, a2, a3);
458: nerrors++;
459: fatalerrors++;
460: }
461:
462: /*VARARGS*/
463: sem_error2(fmt, a1, a2, a3)
464: char *fmt, *a1, *a2, *a3;
465: {
466: fprintf (stderr, fmt, a1, a2, a3);
467: putc('\n', stderr);
468: nerrors++;
469: }
470:
471: char *
472: process_suffix(suf)
473: char *suf;
474: {
475: extern int gen_table2;
476: if(strcmp(suf,"exper")==0) {
477: /* experimental walker */
478: /* expect this to change alot */
479: gen_table2++;
480: }
481: return(suf);
482: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.