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