home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pccts1.zip / ANTLR / BITS.C < prev    next >
C/C++ Source or Header  |  1993-09-02  |  11KB  |  455 lines

  1. /*
  2.  * bits.c -- manage creation and output of bit sets used by the parser.
  3.  *
  4.  * $Id: bits.c,v 1.8 1993/08/24 14:44:32 pccts Exp pccts $
  5.  * $Revision: 1.8 $
  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.10
  28.  * Terence Parr
  29.  * Purdue University
  30.  * 1989-1993
  31.  */
  32. #include <stdio.h>
  33. #include <ctype.h>
  34. #ifdef __cplusplus
  35. #ifndef __STDC__
  36. #define __STDC__
  37. #endif
  38. #endif
  39. #include "set.h"
  40. #include "syn.h"
  41. #include "hash.h"
  42. #include "generic.h"
  43. #include "dlgdef.h"
  44.  
  45. #define BitsPerByte        8
  46.  
  47. /* #define BitsPerWord        BitsPerByte*sizeof(unsigned)
  48.  */
  49. /* char is only thing that is pretty much always known == 8 bits
  50.  * This allows output of antlr (set stuff, anyway) to be androgynous (portable)
  51.  */
  52. typedef unsigned char SetWordType;
  53. #define BitsPerWord        BitsPerByte*sizeof(SetWordType)
  54.  
  55. static SetWordType *setwd = NULL;
  56. int setnum = -1;
  57. int wordnum = 0;
  58.  
  59. int esetnum = 0;
  60.  
  61. /* Used to convert native wordsize, which ANTLR uses (via set.c) to manipulate sets,
  62.    to bytes that are most portable size-wise.
  63.    */
  64. void
  65. #ifdef __STDC__
  66. DumpIntAsChars( FILE *f, char *format, unsigned wd )
  67. #else
  68. DumpIntAsChars( f, format, wd )
  69. FILE *f;
  70. char *format;
  71. unsigned wd;
  72. #endif
  73. {
  74.     int i;
  75.     /* uses max of 32 bit unsigned integer for the moment */
  76.     static unsigned long byte_mask[sizeof(unsigned long)] =
  77.                 { 0xFF, 0xFF00, 0xFF0000, 0xFF000000 };
  78. /*                  0xFF00000000, 0xFF0000000000, 0xFF000000000000, 0xFF00000000000000 };*/
  79.  
  80.     /* for each byte in the word */
  81.     for (i=0; i<sizeof(unsigned); i++)
  82.     {
  83.         /* mask out the ith byte and shift down to the first 8 bits */
  84.         fprintf(f, format, (wd&byte_mask[i])>>(i*BitsPerByte));
  85.         if ( i<sizeof(unsigned)-1) fprintf(f, ",");
  86.     }
  87. }
  88.  
  89. /* Create a new setwd (ignoring [Ep] token on end) */
  90. void
  91. #ifdef __STDC__
  92. NewSetWd( void )
  93. #else
  94. NewSetWd( )
  95. #endif
  96. {
  97.     SetWordType *p;
  98.  
  99.     if ( setwd == NULL )
  100.     {
  101.         setwd = (SetWordType *) calloc(TokenNum, sizeof(SetWordType));
  102.         require(setwd!=NULL, "NewSetWd: cannot alloc set wd\n");
  103.     }
  104.     for (p = setwd; p<&(setwd[TokenNum]); p++)  {*p=0;}
  105.     wordnum++;
  106. }
  107.  
  108. /* Dump the current setwd to ErrFile. 0..MaxTokenVal */
  109. void
  110. #ifdef __STDC__
  111. DumpSetWd( void )
  112. #else
  113. DumpSetWd( )
  114. #endif
  115. {
  116.     int i,c=1;
  117.  
  118.     if ( setwd==NULL ) return;
  119.     fprintf(DefFile, "extern SetWordType setwd%d[];\n", wordnum);
  120.     fprintf(ErrFile,
  121.             "SetWordType setwd%d[%d] = {", wordnum, TokenNum-1);
  122.     for (i=0; i<TokenNum-1; i++)
  123.     {
  124.         if ( i!=0 ) fprintf(ErrFile, ",");
  125.         if ( c == 8 ) {fprintf(ErrFile, "\n\t"); c=1;} else c++;
  126.         fprintf(ErrFile, "0x%x", setwd[i]);
  127.     }
  128.     fprintf(ErrFile, "};\n");
  129. }
  130.  
  131. /* Make a new set.  Dump old setwd and create new setwd if current setwd is full */
  132. void
  133. #ifdef __STDC__
  134. NewSet( void )
  135. #else
  136. NewSet( )
  137. #endif
  138. {
  139.     setnum++;
  140.     if ( setnum==BitsPerWord )        /* is current setwd full? */
  141.     {
  142.         DumpSetWd(); NewSetWd(); setnum = 0;
  143.     }
  144. }
  145.  
  146. /* s is a set of tokens.  Turn on bit at each token position in set 'setnum' */
  147. void
  148. #ifdef __STDC__
  149. FillSet( set s )
  150. #else
  151. FillSet( s )
  152. set s;
  153. #endif
  154. {
  155.     SetWordType mask=(((unsigned)1)<<setnum);
  156.     unsigned int e;
  157.  
  158.     while ( !set_nil(s) )
  159.     {
  160.         e = set_int(s);
  161.         set_rm(e, s);
  162.         setwd[e] |= mask;
  163.     }
  164. }
  165.  
  166.                     /* E r r o r  C l a s s  S t u f f */
  167.  
  168. /* compute the FIRST of a rule for the error class stuff */
  169. static set
  170. #ifdef __STDC__
  171. Efirst( char *rule, ECnode *eclass )
  172. #else
  173. Efirst( rule, eclass )
  174. char *rule;
  175. ECnode *eclass;
  176. #endif
  177. {
  178.     set rk, a;
  179.     Junction *r;
  180.     RuleEntry *q = (RuleEntry *) hash_get(Rname, rule);
  181.  
  182.     if ( q == NULL )
  183.     {
  184.         warnNoFL(eMsg2("undefined rule '%s' referenced in errclass '%s'; ignored",
  185.                         rule, TokenStr[eclass->tok]));
  186.         return empty;
  187.     }
  188.     r = RulePtr[q->rulenum];
  189.     r->end->halt = TRUE;        /* don't let reach fall off end of rule here */
  190.     rk = empty;
  191.     REACH(r, 1, &rk, a);
  192.     r->end->halt = FALSE;
  193.     return a;
  194. }
  195.  
  196. /*
  197.  * scan the list of tokens/eclasses/nonterminals filling the new eclass
  198.  * with the set described by the list.  Note that an eclass can be
  199.  * quoted to allow spaces etc... However, an eclass must not conflict
  200.  * with a reg expr found elsewhere.  The reg expr will be taken over
  201.  * the eclass name.
  202.  */
  203. static void
  204. #ifdef __STDC__
  205. doEclass( char *eclass )
  206. #else
  207. doEclass( eclass )
  208. char *eclass;
  209. #endif
  210. {
  211.     TermEntry *q;
  212.     ECnode *p;
  213.     ListNode *e;
  214.     unsigned int t;
  215.     unsigned deg=0;
  216.     set a;
  217.     require(eclass!=NULL, "doEclass: NULL eset");
  218.     
  219.     p = (ECnode *) eclass;
  220.     lexmode(p->lexclass);    /* switch to lexclass where errclass is defined */
  221.     p->eset = empty;
  222.     for (e = (p->elist)->next; e!=NULL; e=e->next)
  223.     {
  224.         if ( islower( *((char *)e->elem) ) )    /* is it a rule ref? (alias FIRST request) */
  225.         {
  226.             a = Efirst((char *)e->elem, p);
  227.             set_orin(&p->eset, a);
  228.             deg += set_deg(a);
  229.             set_free( a );
  230.             continue;
  231.         }
  232.         else if ( *((char *)e->elem)=='"' )
  233.         {
  234.             t = 0;
  235.             q = (TermEntry *) hash_get(Texpr, (char *) e->elem);
  236.             if ( q == NULL )
  237.             {
  238.                 /* if quoted and not an expr look for eclass name */
  239.                 q = (TermEntry *) hash_get(Tname, *((char **)&(e->elem))=StripQuotes((char *)e->elem));
  240.                 if ( q != NULL ) t = q->token;
  241.             }
  242.             else t = q->token;
  243.         }
  244.         else    /* labelled token/eclass */
  245.         {
  246.             q = (TermEntry *) hash_get(Tname, (char *)e->elem);
  247.             if ( q != NULL ) t = q->token; else t=0;
  248.         }
  249.         if ( t!=0 )
  250.         {
  251.             set_orel(t, &p->eset);
  252.             deg++;
  253.         }
  254.         else warnNoFL(eMsg2("undefined token '%s' referenced in errclass '%s'; ignored",
  255.                             (char *)e->elem, TokenStr[p->tok]));
  256.     }
  257.     p->setdeg = deg;
  258. }
  259.  
  260. void
  261. #ifdef __STDC__
  262. ComputeErrorSets( void )
  263. #else
  264. ComputeErrorSets( )
  265. #endif
  266. {
  267. #ifdef __cplusplus
  268.     list_apply(eclasses, (void (*)(void *)) doEclass);
  269. #else
  270. #ifdef __STDC__
  271.     list_apply(eclasses, (void (*)(void *)) doEclass);
  272. #else
  273.     list_apply(eclasses, doEclass);
  274. #endif
  275. #endif
  276. }
  277.  
  278. /* replace a subset of an error set with an error class name if a subset is found
  279.  * repeat process until no replacements made
  280.  */
  281. void
  282. #ifdef __STDC__
  283. SubstErrorClass( set *f )
  284. #else
  285. SubstErrorClass( f )
  286. set *f;
  287. #endif
  288. {
  289.     int max, done = 0;
  290.     ListNode *p;
  291.     ECnode *ec, *maxclass = NULL;
  292.     set a;
  293.     require(f!=NULL, "SubstErrorClass: NULL eset");
  294.  
  295.     if ( eclasses == NULL ) return;
  296.     while ( !done )
  297.     {
  298.         max = 0;
  299.         maxclass = NULL;
  300.         for (p=eclasses->next; p!=NULL; p=p->next)    /* chk all error classes */
  301.         {
  302.             ec = (ECnode *) p->elem;
  303.             if ( ec->setdeg > max )
  304.             {
  305.                 if ( set_sub(ec->eset, *f) || set_equ(ec->eset, *f) )
  306.                     {maxclass = ec; max=ec->setdeg;}
  307.             }
  308.         }
  309.         if ( maxclass != NULL )    /* if subset found, replace with token */
  310.         {
  311.             a = set_dif(*f, maxclass->eset);
  312.             set_orel((unsigned)maxclass->tok, &a);
  313.             set_free(*f);
  314.             *f = a;
  315.         }
  316.         else done = 1;
  317.     }
  318. }
  319.  
  320. /* Define a new error set.  WARNING...set-implementation dependent */
  321. int
  322. #ifdef __STDC__
  323. DefErrSet( set *f )
  324. #else
  325. DefErrSet( f )
  326. set *f;
  327. #endif
  328. {
  329.     unsigned *p, *endp;
  330.     int e=1;
  331.     require(!set_nil(*f), "DefErrSet: nil set to dump?");
  332.  
  333.     SubstErrorClass(f);
  334.     p = f->setword;
  335.     endp = &(f->setword[NumWords(TokenNum-1)]);
  336.     esetnum++;
  337.     fprintf(DefFile, "extern SetWordType zzerr%d[];\n", esetnum);
  338.     fprintf(ErrFile, "SetWordType zzerr%d[%d] = {", esetnum, NumWords(TokenNum-1)*sizeof(unsigned));
  339.     while ( p < endp )
  340.     {
  341.         if ( e > 1 ) fprintf(ErrFile, ", ");
  342.         DumpIntAsChars(ErrFile, "0x%x", *p++);
  343.         if ( e == 3 )
  344.         {
  345.             if ( p < endp ) fprintf(ErrFile, ",");
  346.             fprintf(ErrFile, "\n\t");
  347.             e=1;
  348.         }
  349.         else e++;
  350.     }
  351.     fprintf(ErrFile, "};\n");
  352.  
  353.     return esetnum;
  354. }
  355.  
  356. void
  357. #ifdef __STDC__
  358. GenErrHdr( void )
  359. #else
  360. GenErrHdr( )
  361. #endif
  362. {
  363.     int i, j;
  364.  
  365.     fprintf(ErrFile, "/*\n");
  366.     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");
  367.     fprintf(ErrFile, " *\n");
  368.     fprintf(ErrFile, " * Generated from:");
  369.     for (i=0; i<NumFiles; i++) fprintf(ErrFile, " %s", FileStr[i]);
  370.     fprintf(ErrFile, "\n");
  371.     fprintf(ErrFile, " *\n");
  372.     fprintf(ErrFile, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-1993\n");
  373.     fprintf(ErrFile, " * Purdue University Electrical Engineering\n");
  374.     fprintf(ErrFile, " * ANTLR Version %s\n", Version);
  375.     fprintf(ErrFile, " */\n\n");
  376.     fprintf(ErrFile, "#include <stdio.h>\n");
  377.     fprintf(ErrFile, "#define ANTLR_VERSION    %s\n", VersionDef);
  378.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  379.         fprintf(ErrFile, "#define %s %s\n", DefaultParserName, ParserName);
  380.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  381.         fprintf(ErrFile, "#include \"%s\"\n", RemapFileName);
  382.     if ( HdrAction != NULL ) dumpAction( HdrAction, ErrFile, 0, -1, 0, 1 );
  383.     if ( FoundGuessBlk )
  384.     {
  385.         fprintf(ErrFile, "#define ZZCAN_GUESS\n");
  386.         fprintf(ErrFile, "#include <setjmp.h>\n");
  387.     }
  388.  
  389.     if ( OutputLL_k > 1 ) fprintf(ErrFile, "#define LL_K %d\n", OutputLL_k);
  390.     fprintf(ErrFile, "#define zzEOF_TOKEN %d\n", EofToken);
  391.     fprintf(ErrFile, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
  392.     if ( DemandLookahead ) fprintf(ErrFile, "#define DEMAND_LOOK\n");
  393.     fprintf(ErrFile, "#include \"antlr.h\"\n");
  394.     if ( GenAST ) fprintf(ErrFile, "#include \"ast.h\"\n");
  395.     fprintf(ErrFile, "#include \"%s\"\n", DefFileName);
  396.     fprintf(ErrFile, "#include \"dlgdef.h\"\n");
  397.     fprintf(ErrFile, "#include \"err.h\"\n\n");
  398.  
  399.     /* Dump a zztokens for each automaton */
  400.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  401.     {
  402.         fprintf(ErrFile, "char *%s_zztokens[%d]={\n", ParserName, TokenNum-1);
  403.     }
  404.     else
  405.     {
  406.         fprintf(ErrFile, "char *zztokens[%d]={\n", TokenNum-1);
  407.     }
  408.     fprintf(ErrFile, "\t/* 00 */\t\"Invalid\",\n");
  409.     if ( TokenStr[EofToken] != NULL )
  410.         fprintf(ErrFile, "\t/* %02d */\t\"%s\"", EofToken, TokenStr[i]);
  411.     else
  412.         fprintf(ErrFile, "\t/* %02d */\t\"EOF\"", EofToken);
  413.     for (i=TokenStart; i<TokenNum-1; i++)
  414.     {
  415.         if ( i == EpToken ) continue;
  416.         if ( TokenStr[i] != NULL )
  417.             fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, TokenStr[i]);
  418.         else
  419.         {
  420.             /* look in all lexclasses for the reg expr */
  421.             for (j=0; j<NumLexClasses; j++)
  422.             {
  423.                 lexmode(j);
  424.                 if ( ExprStr[i] != NULL )
  425.                 {
  426.                     fprintf(ErrFile, ",\n\t/* %02d */\t", i);
  427.                     dumpExpr(ExprStr[i]);
  428.                     break;
  429.                 }
  430.             }
  431.             require(j<NumLexClasses, eMsgd("No label or expr for token %d",i));
  432.         }
  433.     }
  434.     fprintf(ErrFile, "\n};\n");
  435. }
  436.  
  437. void
  438. #ifdef __STDC__
  439. dumpExpr( char *e )
  440. #else
  441. dumpExpr( e )
  442. char *e;
  443. #endif
  444. {
  445.     while ( *e!='\0' )
  446.     {
  447.         if ( *e=='\\' && *(e+1)=='\\' )
  448.             {putc('\\', ErrFile); putc('\\', ErrFile); e+=2;}
  449.         else if ( *e=='\\' && *(e+1)=='"' )
  450.             {putc('\\', ErrFile); putc('"', ErrFile); e+=2;}
  451.         else if ( *e=='\\' ) {putc('\\', ErrFile); putc('\\', ErrFile); e++;}
  452.         else {putc(*e, ErrFile); e++;}
  453.     }
  454. }
  455.