1 /* bits.c -- manage creation and output of bit sets used by the parser. 2 * 3 * SOFTWARE RIGHTS 4 * 5 * We reserve no LEGAL rights to the Purdue Compiler Construction Tool 6 * Set (PCCTS) -- PCCTS is in the public domain. An individual or 7 * company may do whatever they wish with source code distributed with 8 * PCCTS or the code generated by PCCTS, including the incorporation of 9 * PCCTS, or its output, into commerical software. 10 * 11 * We encourage users to develop software with PCCTS. However, we do ask 12 * that credit is given to us for developing PCCTS. By "credit", 13 * we mean that if you incorporate our source code into one of your 14 * programs (commercial product, research project, or otherwise) that you 15 * acknowledge this fact somewhere in the documentation, research report, 16 * etc... If you like PCCTS and have developed a nice tool with the 17 * output, please mention that you developed it using PCCTS. In 18 * addition, we ask that this header remain intact in our source code. 19 * As long as these guidelines are kept, we expect to continue enhancing 20 * this system and expect to make other tools available as they are 21 * completed. 22 * 23 * ANTLR 1.33 24 * Terence Parr 25 * Parr Research Corporation 26 * with Purdue University and AHPCRC, University of Minnesota 27 * 1989-2001 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <ctype.h> 33 #include <assert.h> 34 #include "pcctscfg.h" 35 #include "set.h" 36 #include "syn.h" 37 #include "hash.h" 38 #include "generic.h" 39 #include "dlgdef.h" 40 41 /* char is only thing that is pretty much always known == 8 bits 42 * This allows output of antlr (set stuff, anyway) to be androgynous (portable) 43 */ 44 typedef unsigned char SetWordType; 45 #define BitsPerByte 8 46 #define BitsPerWord BitsPerByte*sizeof(SetWordType) 47 48 static SetWordType *setwd = NULL; 49 int setnum = -1; 50 int wordnum = 0; 51 52 int esetnum = 0; 53 54 /* Used to convert native wordsize, which ANTLR uses (via set.c) to manipulate sets, 55 to bytes that are most portable size-wise. 56 */ 57 void 58 #ifdef __USE_PROTOS 59 DumpIntAsChars( FILE *f, char *format, unsigned wd ) 60 #else 61 DumpIntAsChars( f, format, wd ) 62 FILE *f; 63 char *format; 64 unsigned wd; 65 #endif 66 { 67 int i; 68 /* uses max of 32 bit unsigned integer for the moment */ 69 static unsigned long byte_mask[sizeof(unsigned long)] = 70 { 0xFF, 0xFF00UL, 0xFF0000UL, 0xFF000000UL }; /* MR20 G. Hobbelt */ 71 /* 0xFF00000000, 0xFF0000000000, 0xFF000000000000, 0xFF00000000000000 };*/ 72 73 /* for each byte in the word */ 74 assert(sizeof(unsigned) <= 4); /* M20 G. Hobbelt Sanity check */ 75 for (i=0; i<sizeof(unsigned); i++) 76 { 77 /* mask out the ith byte and shift down to the first 8 bits */ 78 fprintf(f, format, (wd&byte_mask[i])>>(i*BitsPerByte)); 79 if ( i<sizeof(unsigned)-1) fprintf(f, ","); 80 } 81 } 82 83 /* Create a new setwd (ignoring [Ep] token on end) */ 84 void 85 #ifdef __USE_PROTOS 86 NewSetWd( void ) 87 #else 88 NewSetWd( ) 89 #endif 90 { 91 SetWordType *p; 92 93 if ( setwd == NULL ) 94 { 95 setwd = (SetWordType *) calloc(TokenNum, sizeof(SetWordType)); 96 require(setwd!=NULL, "NewSetWd: cannot alloc set wd\n"); 97 } 98 for (p = setwd; p<&(setwd[TokenNum]); p++) {*p=0;} 99 wordnum++; 100 } 101 102 void 103 #ifdef __USE_PROTOS 104 DumpSetWd( void ) 105 #else 106 DumpSetWd( ) 107 #endif 108 { 109 if ( GenCC ) DumpSetWdForCC(); 110 else DumpSetWdForC(); 111 } 112 113 /* Dump the current setwd to ErrFile. 0..MaxTokenVal */ 114 void 115 #ifdef __USE_PROTOS 116 DumpSetWdForC( void ) 117 #else 118 DumpSetWdForC( ) 119 #endif 120 { 121 int i,c=1; 122 123 if ( setwd==NULL ) return; 124 fprintf(DefFile, "extern SetWordType setwd%d[];\n", wordnum); 125 fprintf(ErrFile, 126 "SetWordType setwd%d[%d] = {", wordnum, TokenNum-1); 127 for (i=0; i<TokenNum-1; i++) 128 { 129 DAWDLE; 130 if ( i!=0 ) fprintf(ErrFile, ","); 131 if ( c == 8 ) {fprintf(ErrFile, "\n\t"); c=1;} else c++; 132 fprintf(ErrFile, "0x%x", setwd[i]); 133 } 134 fprintf(ErrFile, "};\n"); 135 } 136 137 /* Dump the current setwd to Parser.C file. 0..MaxTokenVal; 138 * Only used if -CC on. 139 */ 140 void 141 #ifdef __USE_PROTOS 142 DumpSetWdForCC( void ) 143 #else 144 DumpSetWdForCC( ) 145 #endif 146 { 147 int i,c=1; 148 149 if ( setwd==NULL ) return; 150 fprintf(Parser_h, "\tstatic SetWordType setwd%d[%d];\n", wordnum, TokenNum-1); 151 fprintf(Parser_c, 152 "SetWordType %s::setwd%d[%d] = {", CurrentClassName, wordnum, 153 TokenNum-1); 154 for (i=0; i<TokenNum-1; i++) 155 { 156 DAWDLE; 157 if ( i!=0 ) fprintf(Parser_c, ","); 158 if ( c == 8 ) {fprintf(Parser_c, "\n\t"); c=1;} else c++; 159 fprintf(Parser_c, "0x%x", setwd[i]); 160 } 161 fprintf(Parser_c, "};\n"); 162 } 163 164 /* Make a new set. Dump old setwd and create new setwd if current setwd is full */ 165 void 166 #ifdef __USE_PROTOS 167 NewSet( void ) 168 #else 169 NewSet( ) 170 #endif 171 { 172 setnum++; 173 if ( setnum==BitsPerWord ) /* is current setwd full? */ 174 { 175 DumpSetWd(); NewSetWd(); setnum = 0; 176 } 177 } 178 179 /* s is a set of tokens. Turn on bit at each token position in set 'setnum' */ 180 void 181 #ifdef __USE_PROTOS 182 FillSet( set s ) 183 #else 184 FillSet( s ) 185 set s; 186 #endif 187 { 188 SetWordType mask=(((unsigned)1)<<setnum); 189 unsigned int e; 190 191 while ( !set_nil(s) ) 192 { 193 e = set_int(s); 194 set_rm(e, s); 195 setwd[e] |= mask; 196 } 197 } 198 199 /* E r r o r C l a s s S t u f f */ 200 201 /* compute the FIRST of a rule for the error class stuff */ 202 static set 203 #ifdef __USE_PROTOS 204 Efirst( char *rule, ECnode *eclass ) 205 #else 206 Efirst( rule, eclass ) 207 char *rule; 208 ECnode *eclass; 209 #endif 210 { 211 set rk, a; 212 Junction *r; 213 RuleEntry *q = (RuleEntry *) hash_get(Rname, rule); 214 215 if ( q == NULL ) 216 { 217 warnNoFL(eMsg2("undefined rule '%s' referenced in errclass '%s'; ignored", 218 rule, TokenString(eclass->tok))); 219 return empty; 220 } 221 r = RulePtr[q->rulenum]; 222 r->end->halt = TRUE; /* don't let reach fall off end of rule here */ 223 rk = empty; 224 REACH(r, 1, &rk, a); 225 r->end->halt = FALSE; 226 return a; 227 } 228 229 /* 230 * scan the list of tokens/eclasses/nonterminals filling the new eclass 231 * with the set described by the list. Note that an eclass can be 232 * quoted to allow spaces etc... However, an eclass must not conflict 233 * with a reg expr found elsewhere. The reg expr will be taken over 234 * the eclass name. 235 */ 236 static void 237 #ifdef __USE_PROTOS 238 doEclass( char *eclass ) 239 #else 240 doEclass( eclass ) 241 char *eclass; 242 #endif 243 { 244 TermEntry *q; 245 ECnode *p; 246 TCnode *tcnode; 247 ListNode *e; 248 unsigned int t; 249 unsigned deg=0; 250 set a; 251 require(eclass!=NULL, "doEclass: NULL eset"); 252 253 p = (ECnode *) eclass; 254 lexmode(p->lexclass); /* switch to lexclass where errclass is defined */ 255 p->eset = empty; 256 for (e = (p->elist)->next; e!=NULL; e=e->next) 257 { 258 q = NULL; /* MR23 */ 259 260 if ( islower( *((char *)e->elem) ) ) /* is it a rule ref? (alias FIRST request) */ 261 { 262 a = Efirst((char *)e->elem, p); 263 set_orin(&p->eset, a); 264 deg += set_deg(a); 265 set_free( a ); 266 continue; 267 } 268 else if ( *((char *)e->elem)=='"' ) 269 { 270 t = 0; 271 q = (TermEntry *) hash_get(Texpr, (char *) e->elem); 272 if ( q == NULL ) 273 { 274 /* if quoted and not an expr look for eclass name */ 275 q = (TermEntry *) hash_get(Tname, *((char **)&(e->elem))=StripQuotes((char *)e->elem)); 276 if ( q != NULL ) t = q->token; 277 } 278 else t = q->token; 279 } 280 else /* labelled token/eclass/tokclass */ 281 { 282 q = (TermEntry *) hash_get(Tname, (char *)e->elem); 283 if ( q != NULL ) 284 { 285 if ( strcmp((char *)e->elem, TokenString(p->tok))==0 ) 286 { 287 warnNoFL(eMsg1("self-referential error class '%s'; ignored", 288 (char *)e->elem)); 289 continue; 290 } 291 else 292 t = q->token; 293 } 294 else t=0; 295 } 296 if ( t!=0 ) 297 { 298 if (isTermEntryTokClass(q)) { /* MR23 */ 299 tcnode = q->tclass; /* MR23 */ 300 set_orin(&p->eset, tcnode->tset); /* MR23 */ 301 deg = set_deg(p->eset); /* MR23 */ 302 } /* MR23 */ 303 else { 304 set_orel(t, &p->eset); 305 deg++; 306 } 307 } 308 else warnNoFL(eMsg2("undefined token '%s' referenced in errclass '%s'; ignored", 309 (char *)e->elem, TokenString(p->tok))); 310 } 311 p->setdeg = deg; 312 } 313 314 void 315 #ifdef __USE_PROTOS 316 ComputeErrorSets( void ) 317 #else 318 ComputeErrorSets( ) 319 #endif 320 { 321 #ifdef __cplusplus 322 list_apply(eclasses, (void (*)(void *)) doEclass); 323 #else 324 #ifdef __USE_PROTOS 325 list_apply(eclasses, (void (*)(void *)) doEclass); 326 #else 327 list_apply(eclasses, doEclass); 328 #endif 329 #endif 330 } 331 332 void 333 #ifdef __USE_PROTOS 334 ComputeTokSets( void ) 335 #else 336 ComputeTokSets( ) 337 #endif 338 { 339 ListNode *t, *e = NULL, *e1, *e2; 340 int something_changed; 341 int i; 342 TCnode *p; 343 TermEntry *q, *q1, *q2; 344 345 if ( tclasses == NULL ) return; 346 347 /* turn lists of token/tokclass references into sets */ 348 for (t = tclasses->next; t!=NULL; t=t->next) 349 { 350 p = (TCnode *) t->elem; 351 352 /* if wild card, then won't have entries in tclass, assume all_tokens */ 353 if ( p->tok == WildCardToken ) 354 { 355 p->tset = set_dup(all_tokens); 356 continue; 357 } 358 359 lexmode(p->lexclass); /* switch to lexclass where tokclass is defined */ 360 p->tset = empty; 361 362 /* instantiate all tokens/token_classes into the tset */ 363 for (e = (p->tlist)->next; e!=NULL; e=e->next) 364 { 365 char *tokstr; 366 tokstr = (char *)e->elem; 367 if ( *tokstr == '"' ) { 368 q = (TermEntry *) hash_get(Texpr, tokstr); 369 require(q!=NULL, "ComputeTokSets: no token def"); 370 set_orel(q->token, &p->tset); 371 } else if (tokstr[0] == '.') { 372 e1=e->next; 373 e2=e1->next; 374 e=e2; 375 q1= (TermEntry *) hash_get(Tname, (char *)e1->elem); 376 require(q1!=NULL, "ComputeTokSets: no token def"); 377 q2= (TermEntry *) hash_get(Tname, (char *)e2->elem); 378 require(q2!=NULL, "ComputeTokSets: no token def"); 379 380 if (set_el(q1->token,imag_tokens)) { 381 errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s", 382 TokenString(p->tok),(char *)e1->elem) ); 383 } 384 if (set_el(q2->token,imag_tokens)) { 385 errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s", 386 TokenString(p->tok),(char *)e2->elem) ); 387 } 388 if (q1->token > q2->token) { 389 errNoFL(eMsg3("for #tokclass %s %s..%s - first token number > second token number", 390 TokenString(p->tok),(char *)e1->elem,(char *)e2->elem) ); 391 for (i=q2->token; i<=q1->token; i++) { set_orel(i, &p->tset); } 392 } else { 393 for (i=q1->token; i<=q2->token; i++) { set_orel(i, &p->tset); } 394 } 395 } else { 396 q = (TermEntry *) hash_get(Tname, tokstr); 397 require(q!=NULL, "ComputeTokSets: no token def"); 398 set_orel(q->token, &p->tset); 399 } 400 } 401 } 402 403 /* Go thru list of tokclasses again looking for tokclasses in sets */ 404 again: 405 something_changed = 0; 406 for (t = tclasses->next; t!=NULL; t=t->next) 407 { 408 set tcl; 409 p = (TCnode *) t->elem; 410 tcl = set_and(p->tset, tokclasses); 411 if ( !set_nil(tcl) ) 412 { 413 int tk; 414 /* replace refs to tokclasses with the associated set of tokens */ 415 something_changed = 1; 416 while ( !set_nil(tcl) ) 417 { 418 tk = set_int(tcl); /* grab one of the tok class refs */ 419 set_rm(tk, tcl); 420 if ( p->tok != tk ) /* tokclass ref to yourself? */ 421 { 422 q = (TermEntry *) hash_get(Tname, TokenString(tk)); 423 require(q!=NULL, "#tokclass not in hash table"); 424 set_orin(&p->tset, q->tclass->tset); 425 } 426 set_rm(tk, p->tset); /* remove ref that we replaced */ 427 } 428 } 429 set_free(tcl); 430 } 431 if ( something_changed ) goto again; 432 } 433 434 void 435 #ifdef __USE_PROTOS 436 DumpRemainingTokSets(void) 437 #else 438 DumpRemainingTokSets() 439 #endif 440 { 441 TCnode *p; 442 ListNode *t; 443 444 /* Go thru tclasses (for the last time) and dump the sets not dumped 445 * during code gen; yes, this is a bogus way to do this, but ComputeTokSets() 446 * can't dump the defs as the error file and tok file has not been created 447 * yet etc... 448 */ 449 if ( tclasses==NULL ) return; 450 for (t = tclasses->next; t!=NULL; t=t->next) 451 { 452 unsigned e; 453 p = (TCnode *) t->elem; 454 if ( p->dumped ) continue; 455 e = DefErrSet(&(p->tset), 0, TokenString(p->tok)); 456 p->dumped = 1; 457 p->setnum = e; 458 } 459 } 460 461 462 /* replace a subset of an error set with an error class name if a subset is found 463 * repeat process until no replacements made 464 */ 465 void 466 #ifdef __USE_PROTOS 467 SubstErrorClass( set *f ) 468 #else 469 SubstErrorClass( f ) 470 set *f; 471 #endif 472 { 473 int max, done = 0; 474 ListNode *p; 475 ECnode *ec, *maxclass = NULL; 476 set a; 477 require(f!=NULL, "SubstErrorClass: NULL eset"); 478 479 if ( eclasses == NULL ) return; 480 while ( !done ) 481 { 482 max = 0; 483 maxclass = NULL; 484 for (p=eclasses->next; p!=NULL; p=p->next) /* chk all error classes */ 485 { 486 ec = (ECnode *) p->elem; 487 if ( ec->setdeg > max ) 488 { 489 if ( set_sub(ec->eset, *f) || set_equ(ec->eset, *f) ) 490 {maxclass = ec; max=ec->setdeg;} 491 } 492 } 493 if ( maxclass != NULL ) /* if subset found, replace with token */ 494 { 495 a = set_dif(*f, maxclass->eset); 496 set_orel((unsigned)maxclass->tok, &a); 497 set_free(*f); 498 *f = a; 499 } 500 else done = 1; 501 } 502 } 503 504 int 505 #ifdef __USE_PROTOS 506 DefErrSet1(int nilOK, set *f, int subst, char *name ) 507 #else 508 DefErrSet1(nilOK, f, subst, name ) 509 int nilOK; 510 set *f; 511 int subst; /* should be substitute error classes? */ 512 char *name; 513 #endif 514 { 515 if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, "_set"); 516 else return DefErrSetForC1(nilOK, f, subst, name, "_set"); 517 } 518 519 int 520 #ifdef __USE_PROTOS 521 DefErrSet( set *f, int subst, char *name ) 522 #else 523 DefErrSet( f, subst, name ) 524 set *f; 525 int subst; /* should be substitute error classes? */ 526 char *name; 527 #endif 528 { 529 return DefErrSet1(0,f,subst,name); 530 } 531 532 int 533 #ifdef __USE_PROTOS 534 DefErrSetWithSuffix(int nilOK, set *f, int subst, char *name, const char* suffix) 535 #else 536 DefErrSetWithSuffix(nilOK, f, subst, name, suffix ) 537 int nilOK; 538 set *f; 539 int subst; /* should be substitute error classes? */ 540 char *name; 541 char *suffix; 542 #endif 543 { 544 if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, suffix ); 545 else return DefErrSetForC1(nilOK, f, subst, name, suffix); 546 } 547 548 /* Define a new error set. WARNING...set-implementation dependent. 549 */ 550 int 551 #ifdef __USE_PROTOS 552 DefErrSetForC1(int nilOK, set *f, int subst, char * name, const char * suffix) 553 #else 554 DefErrSetForC1(nilOK, f, subst, name, suffix) 555 int nilOK; /* MR13 */ 556 set *f; 557 int subst; /* should be substitute error classes? */ 558 char *name; 559 const char *suffix; 560 #endif 561 { 562 unsigned *p, *endp; 563 int e=1; 564 565 if (!nilOK) require(!set_nil(*f), "DefErrSetForC1: nil set to dump?"); 566 567 if ( subst ) SubstErrorClass(f); 568 p = f->setword; 569 endp = &(f->setword[f->n]); 570 esetnum++; 571 if ( name!=NULL ) 572 fprintf(DefFile, "extern SetWordType %s%s[];\n", name, suffix); 573 else 574 fprintf(DefFile, "extern SetWordType zzerr%d[];\n", esetnum); 575 if ( name!=NULL ) { 576 fprintf(ErrFile, "SetWordType %s%s[%d] = {", 577 name, 578 suffix, 579 NumWords(TokenNum-1)*sizeof(unsigned)); 580 } 581 else { 582 fprintf(ErrFile, "SetWordType zzerr%d[%d] = {", 583 esetnum, 584 NumWords(TokenNum-1)*sizeof(unsigned)); 585 } 586 while ( p < endp ) 587 { 588 if ( e > 1 ) fprintf(ErrFile, ", "); 589 DumpIntAsChars(ErrFile, "0x%x", *p++); 590 if ( e == 3 ) 591 { 592 DAWDLE; 593 if ( p < endp ) fprintf(ErrFile, ","); 594 fprintf(ErrFile, "\n\t"); 595 e=1; 596 } 597 else e++; 598 } 599 fprintf(ErrFile, "};\n"); 600 601 return esetnum; 602 } 603 604 int 605 #ifdef __USE_PROTOS 606 DefErrSetForC( set *f, int subst, char *name ) 607 #else 608 DefErrSetForC( f, subst, name ) 609 set *f; 610 int subst; /* should be substitute error classes? */ 611 char *name; 612 #endif 613 { 614 return DefErrSetForC1(0,f,subst,name, "_set"); 615 } 616 617 /* Define a new error set. WARNING...set-implementation dependent; 618 * Only used when -CC on. 619 */ 620 621 int 622 #ifdef __USE_PROTOS 623 DefErrSetForCC1(int nilOK, set *f, int subst, char *name, const char *suffix ) 624 #else 625 DefErrSetForCC1(nilOK, f, subst, name, suffix ) 626 int nilOK; /* MR13 */ 627 set *f; 628 int subst; /* should be substitute error classes? */ 629 char *name; 630 const char *suffix; 631 #endif 632 { 633 unsigned *p, *endp; 634 int e=1; 635 636 if (!nilOK) require(!set_nil(*f), "DefErrSetForCC1: nil set to dump?"); 637 638 if ( subst ) SubstErrorClass(f); 639 p = f->setword; 640 endp = &(f->setword[f->n]); 641 esetnum++; 642 643 if ( name!=NULL ) { 644 fprintf(Parser_h, "\tstatic SetWordType %s%s[%d];\n", name, suffix, 645 NumWords(TokenNum-1)*sizeof(unsigned)); 646 fprintf(Parser_c, "SetWordType %s::%s%s[%d] = {", 647 CurrentClassName, 648 name, 649 suffix, 650 NumWords(TokenNum-1)*sizeof(unsigned)); 651 } 652 else { 653 fprintf(Parser_c, "SetWordType %s::err%d[%d] = {", 654 CurrentClassName, 655 esetnum, 656 NumWords(TokenNum-1)*sizeof(unsigned)); 657 fprintf(Parser_h, "\tstatic SetWordType err%d[%d];\n", esetnum, 658 NumWords(TokenNum-1)*sizeof(unsigned)); 659 } 660 661 while ( p < endp ) 662 { 663 if ( e > 1 ) fprintf(Parser_c, ", "); 664 DumpIntAsChars(Parser_c, "0x%x", *p++); 665 if ( e == 3 ) 666 { 667 if ( p < endp ) fprintf(Parser_c, ","); 668 fprintf(Parser_c, "\n\t"); 669 e=1; 670 } 671 else e++; 672 } 673 fprintf(Parser_c, "};\n"); 674 675 return esetnum; 676 } 677 678 int 679 #ifdef __USE_PROTOS 680 DefErrSetForCC( set *f, int subst, char *name ) 681 #else 682 DefErrSetForCC( f, subst, name ) 683 set *f; 684 int subst; /* should be substitute error classes? */ 685 char *name; 686 #endif 687 { 688 return DefErrSetForCC1(0,f,subst,name, "_set"); 689 } 690 691 void 692 #ifdef __USE_PROTOS 693 GenParser_c_Hdr(void) 694 #else 695 GenParser_c_Hdr() 696 #endif 697 { 698 int i,j; 699 TermEntry *te; 700 char * hasAkaName = NULL; /* MR23 */ 701 702 hasAkaName = (char *) malloc(TokenNum+1); /* MR23 */ 703 require(hasAkaName!=NULL, "Cannot alloc hasAkaName\n"); /* MR23 */ 704 for (i = 0; i < TokenNum; i++) hasAkaName[i]='0'; /* MR23 */ 705 hasAkaName[TokenNum] = 0; /* MR23 */ 706 707 fprintf(Parser_c, "/*\n"); 708 fprintf(Parser_c, " * %s: P a r s e r S u p p o r t\n", CurrentClassName); 709 fprintf(Parser_c, " *\n"); 710 fprintf(Parser_c, " * Generated from:"); 711 for (i=0; i<NumFiles; i++) fprintf(Parser_c, " %s", FileStr[i]); 712 fprintf(Parser_c, "\n"); 713 fprintf(Parser_c, " *\n"); 714 fprintf(Parser_c, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n"); 715 fprintf(Parser_c, " * Parr Research Corporation\n"); 716 fprintf(Parser_c, " * with Purdue University Electrical Engineering\n"); 717 fprintf(Parser_c, " * with AHPCRC, University of Minnesota\n"); 718 fprintf(Parser_c, " * ANTLR Version %s\n", Version); 719 fprintf(Parser_c, " */\n\n"); 720 721 if ( FirstAction != NULL ) dumpAction(FirstAction,Parser_c, 0, -1, 0, 1); /* MR11 MR15b */ 722 723 fprintf(Parser_c, "#define ANTLR_VERSION %s\n", VersionDef); 724 725 fprintf(Parser_c, "#include \"pcctscfg.h\"\n"); 726 fprintf(Parser_c, "#include \"pccts_stdio.h\"\n"); 727 fprintf(Parser_c, "#define ANTLR_SUPPORT_CODE\n"); 728 if ( UserTokenDefsFile != NULL ) 729 fprintf(Parser_c, "#include %s\n", UserTokenDefsFile); 730 else 731 fprintf(Parser_c, "#include \"%s\"\n", DefFileName); 732 733 fprintf(Parser_c, "#include \"%s.h\"\n\n", CurrentClassName); 734 735 fprintf(Parser_c, "const ANTLRChar *%s::tokenName(int tok) ", /* MR1 */ 736 CurrentClassName); /* MR1 */ 737 fprintf(Parser_c, " { return _token_tbl[tok]; }\n"); /* MR1 */ /* MR10 */ 738 /* Dump a Parser::tokens for each automaton */ 739 fprintf(Parser_c, "\nconst ANTLRChar *%s::_token_tbl[]={\n", 740 CurrentClassName); /* MR20 */ 741 fprintf(Parser_c, "\t/* 00 */\t\"Invalid\""); 742 743 for (i=1; i<TokenNum-1; i++) 744 { 745 DAWDLE; 746 if ( i == EpToken ) continue; 747 /* remapped to invalid token? */ 748 if ( TokenInd!=NULL && TokenInd[i]>=LastTokenCounted ) 749 { 750 fprintf(Parser_c, ",\n\t/* %02d */\t\"invalid\"", i); 751 continue; 752 } 753 if ( TokenString(i) != NULL ) { 754 te=(TermEntry *) hash_get(Tname,TokenString(i)); /* MR11 */ 755 if (te == NULL || te->akaString == NULL) { /* MR11 */ 756 fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i)); 757 } else { 758 hasAkaName[i] = '1'; /* MR23 */ 759 fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, te->akaString); /* MR11 */ 760 } 761 } 762 else 763 { 764 /* look in all lexclasses for the reg expr */ 765 for (j=0; j<NumLexClasses; j++) 766 { 767 lexmode(j); 768 if ( ExprString(i) != NULL ) 769 { 770 fprintf(Parser_c, ",\n\t/* %02d */\t", i); 771 dumpExpr(Parser_c, ExprString(i)); 772 break; 773 } 774 } 775 if ( j>=NumLexClasses ) 776 { 777 if ( UserDefdTokens ) 778 { 779 fprintf(Parser_c, ",\n\t/* %02d */\t\"\"", i); 780 } 781 else 782 fatal_internal(eMsgd("No label or expr for token %d",i)); 783 } 784 } 785 } 786 fprintf(Parser_c, "\n};\n"); 787 788 /* Build constructors */ 789 fprintf(Parser_c, "\n%s::", CurrentClassName); 790 fprintf(Parser_c, "%s(ANTLRTokenBuffer *input) : %s(input,%d,%d,%d,%d)\n", 791 CurrentClassName, 792 (BaseClassName == NULL ? "ANTLRParser" : BaseClassName), 793 OutputLL_k, 794 FoundGuessBlk, 795 DemandLookahead, 796 NumWords(TokenNum-1)*sizeof(unsigned)); 797 fprintf(Parser_c, "{\n"); 798 fprintf(Parser_c, "\ttoken_tbl = _token_tbl;\n"); 799 if (TraceGen) { 800 fprintf(Parser_c, "\ttraceOptionValueDefault=1;\t\t// MR10 turn trace ON\n"); 801 } else { 802 fprintf(Parser_c, "\ttraceOptionValueDefault=0;\t\t// MR10 turn trace OFF\n"); 803 }; 804 fprintf(Parser_c, "}\n\n"); 805 free ( (void *) hasAkaName); 806 } 807 808 void 809 #ifdef __USE_PROTOS 810 GenParser_h_Hdr(void) 811 #else 812 GenParser_h_Hdr() 813 #endif 814 { 815 int i; 816 817 fprintf(Parser_h, "/*\n"); 818 fprintf(Parser_h, " * %s: P a r s e r H e a d e r \n", CurrentClassName); 819 fprintf(Parser_h, " *\n"); 820 fprintf(Parser_h, " * Generated from:"); 821 for (i=0; i<NumFiles; i++) fprintf(Parser_h, " %s", FileStr[i]); 822 fprintf(Parser_h, "\n"); 823 fprintf(Parser_h, " *\n"); 824 fprintf(Parser_h, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n"); 825 fprintf(Parser_h, " * Parr Research Corporation\n"); 826 fprintf(Parser_h, " * with Purdue University Electrical Engineering\n"); 827 fprintf(Parser_h, " * with AHPCRC, University of Minnesota\n"); 828 fprintf(Parser_h, " * ANTLR Version %s\n", Version); 829 fprintf(Parser_h, " */\n\n"); 830 831 if ( FirstAction != NULL ) dumpAction( FirstAction, Parser_h, 0, -1, 0, 1); /* MR11 MR15b */ 832 833 fprintf(Parser_h, "#ifndef %s_h\n", CurrentClassName); 834 fprintf(Parser_h, "#define %s_h\n\n", CurrentClassName); 835 836 fprintf(Parser_h, "#ifndef ANTLR_VERSION\n"); 837 fprintf(Parser_h, "#define ANTLR_VERSION %s\n",VersionDef); 838 fprintf(Parser_h, "#endif\n\n"); 839 840 if ( GenAST ) fprintf(Parser_h, "class ASTBase;\n"); 841 if (TraceGen) { 842 fprintf(Parser_h,"#ifndef zzTRACE_RULES\n"); /* MR20 */ 843 fprintf(Parser_h,"#define zzTRACE_RULES\n"); /* MR20 */ 844 fprintf(Parser_h,"#endif\n"); /* MR22 */ 845 }; 846 fprintf(Parser_h, "#include \"%s\"\n\n", APARSER_H); 847 848 if ( HdrAction != NULL ) dumpAction( HdrAction, Parser_h, 0, -1, 0, 1); 849 850 /* MR10 */ if (ClassDeclStuff == NULL) { 851 /* MR10 */ fprintf(Parser_h, "class %s : public ANTLRParser {\n", CurrentClassName); 852 /* MR10 */ } else { 853 /* MR10 */ fprintf(Parser_h, "class %s %s {\n",CurrentClassName,ClassDeclStuff); 854 /* MR10 */ }; 855 856 fprintf(Parser_h, "public:\n"); /* MR1 */ 857 fprintf(Parser_h, "\tstatic const ANTLRChar *tokenName(int tk);\n");/* MR1 */ 858 fprintf(Parser_h, "\tenum { SET_SIZE = %i };\n",TokenNum-1); /* MR21 */ 859 fprintf(Parser_h, "protected:\n"); 860 fprintf(Parser_h, "\tstatic const ANTLRChar *_token_tbl[];\n"); /* MR20 */ 861 fprintf(Parser_h, "private:\n"); 862 } 863 864 /* Currently, this is only used in !GenCC mode */ 865 void 866 #ifdef __USE_PROTOS 867 GenErrHdr( void ) 868 #else 869 GenErrHdr( ) 870 #endif 871 { 872 int i, j; 873 TermEntry *te; 874 875 fprintf(ErrFile, "/*\n"); 876 fprintf(ErrFile, " * A n t l r S e t s / E r r o r F i l e H e a d e r\n"); 877 fprintf(ErrFile, " *\n"); 878 fprintf(ErrFile, " * Generated from:"); 879 for (i=0; i<NumFiles; i++) fprintf(ErrFile, " %s", FileStr[i]); 880 fprintf(ErrFile, "\n"); 881 fprintf(ErrFile, " *\n"); 882 fprintf(ErrFile, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n"); 883 fprintf(ErrFile, " * Parr Research Corporation\n"); 884 fprintf(ErrFile, " * with Purdue University Electrical Engineering\n"); 885 fprintf(ErrFile, " * With AHPCRC, University of Minnesota\n"); 886 fprintf(ErrFile, " * ANTLR Version %s\n", Version); 887 fprintf(ErrFile, " */\n\n"); 888 889 if ( FirstAction != NULL ) dumpAction( FirstAction, ErrFile, 0, -1, 0, 1); /* MR11 MR15b */ 890 891 fprintf(ErrFile, "#define ANTLR_VERSION %s\n", VersionDef); 892 893 fprintf(ErrFile, "#include \"pcctscfg.h\"\n"); 894 fprintf(ErrFile, "#include \"pccts_stdio.h\"\n"); 895 if ( strcmp(ParserName, DefaultParserName)!=0 ) 896 fprintf(ErrFile, "#define %s %s\n", DefaultParserName, ParserName); 897 if ( strcmp(ParserName, DefaultParserName)!=0 ) 898 fprintf(ErrFile, "#include \"%s\"\n", RemapFileName); 899 if ( HdrAction != NULL ) dumpAction( HdrAction, ErrFile, 0, -1, 0, 1 ); 900 if ( FoundGuessBlk ) 901 { 902 fprintf(ErrFile, "#define ZZCAN_GUESS\n"); 903 fprintf(ErrFile, "#include \"pccts_setjmp.h\"\n"); 904 } 905 if (TraceGen) { 906 fprintf(ErrFile,"#ifndef zzTRACE_RULES\n"); /* MR20 */ 907 fprintf(ErrFile,"#define zzTRACE_RULES\n"); /* MR20 */ 908 fprintf(ErrFile,"#endif\n"); /* MR22 */ 909 }; 910 911 if ( OutputLL_k > 1 ) fprintf(ErrFile, "#define LL_K %d\n", OutputLL_k); 912 #ifdef DUM 913 if ( LexGen ) fprintf(ErrFile, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken)); 914 #endif 915 fprintf(ErrFile, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned)); 916 if ( DemandLookahead ) fprintf(ErrFile, "#define DEMAND_LOOK\n"); 917 fprintf(ErrFile, "#include \"antlr.h\"\n"); 918 if ( GenAST ) fprintf(ErrFile, "#include \"ast.h\"\n"); 919 920 if ( UserDefdTokens ) fprintf(ErrFile, "#include %s\n", UserTokenDefsFile); 921 /* still need this one as it has the func prototypes */ 922 fprintf(ErrFile, "#include \"%s\"\n", DefFileName); 923 fprintf(ErrFile, "#include \"dlgdef.h\"\n"); 924 fprintf(ErrFile, "#include \"err.h\"\n\n"); 925 926 /* Dump a zztokens for each automaton */ 927 if ( strcmp(ParserName, DefaultParserName)!=0 ) 928 { 929 fprintf(ErrFile, "ANTLRChar *%s_zztokens[%d]={\n", ParserName, TokenNum-1); 930 } 931 else 932 { 933 fprintf(ErrFile, "ANTLRChar *zztokens[%d]={\n", TokenNum-1); 934 } 935 fprintf(ErrFile, "\t/* 00 */\t\"Invalid\""); 936 for (i=1; i<TokenNum-1; i++) 937 { 938 DAWDLE; 939 if ( i == EpToken ) continue; 940 /* remapped to invalid token? */ 941 if ( TokenInd!=NULL && TokenInd[i]>=LastTokenCounted ) 942 { 943 fprintf(ErrFile, ",\n\t/* %02d */\t\"invalid\"", i); 944 continue; 945 } 946 if ( TokenString(i) != NULL ) { 947 te=(TermEntry *) hash_get(Tname,TokenString(i)); /* MR11 */ 948 if (te == NULL || te->akaString == NULL) { /* MR11 */ 949 fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i)); 950 } else { 951 fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, te->akaString); /* MR11 */ 952 } 953 } 954 else 955 { 956 /* look in all lexclasses for the reg expr */ 957 for (j=0; j<NumLexClasses; j++) 958 { 959 lexmode(j); 960 if ( ExprString(i) != NULL ) 961 { 962 fprintf(ErrFile, ",\n\t/* %02d */\t", i); 963 dumpExpr(ErrFile, ExprString(i)); 964 break; 965 } 966 } 967 if ( j>=NumLexClasses ) 968 { 969 if ( UserDefdTokens ) 970 { 971 fprintf(ErrFile, ",\n\t/* %02d */\t\"\"", i); 972 } 973 else 974 fatal_internal(eMsgd("No label or expr for token %d",i)); 975 } 976 } 977 } 978 fprintf(ErrFile, "\n};\n"); 979 } 980 981 void 982 #ifdef __USE_PROTOS 983 dumpExpr( FILE *f, char *e ) 984 #else 985 dumpExpr( f, e ) 986 FILE *f; 987 char *e; 988 #endif 989 { 990 while ( *e!='\0' ) 991 { 992 if ( *e=='\\' && *(e+1)=='\\' ) 993 {putc('\\', f); putc('\\', f); e+=2;} 994 else if ( *e=='\\' && *(e+1)=='"' ) 995 {putc('\\', f); putc('"', f); e+=2;} 996 else if ( *e=='\\' ) {putc('\\', f); putc('\\', f); e++;} 997 else {putc(*e, f); e++;} 998 } 999 } 1000 1001 int 1002 #ifdef __USE_PROTOS 1003 isTermEntryTokClass(TermEntry *te) 1004 #else 1005 isTermEntryTokClass(te) 1006 TermEntry *te; 1007 #endif 1008 { 1009 ListNode *t; 1010 TCnode *p; 1011 TermEntry *q; 1012 char *tokstr; 1013 1014 if (tclasses == NULL) return 0; 1015 1016 for (t = tclasses->next; t!=NULL; t=t->next) 1017 { 1018 p = (TCnode *) t->elem; 1019 tokstr = TokenString(p->tok); 1020 lexmode(p->lexclass); /* switch to lexclass where tokclass is defined */ 1021 q = (TermEntry *) hash_get(Tname, tokstr); 1022 if (q == te) return 1; 1023 } 1024 return 0; 1025 } 1026