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