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

  1. /*
  2.  * lex.c    --    Generate all of the lexical type files: parser.dlg tokens.h
  3.  *
  4.  * $Id: lex.c,v 1.7 1993/08/24 14:44:32 pccts Exp pccts $
  5.  * $Revision: 1.7 $
  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.  
  44. #define DLGErrorString "invalid token"
  45.  
  46. #ifdef __STDC__
  47. static void dumpPredictionExpressions(FILE *);
  48. #else
  49. static void dumpPredictionExpressions();
  50. #endif
  51.   
  52. /* Generate a complete lexical description of the lexemes found in the grammar */
  53. void
  54. #ifdef __STDC__
  55. genLexDescr( void )
  56. #else
  57. genLexDescr( )
  58. #endif
  59. {
  60.     ListNode *p;
  61.     FILE *dlgFile = fopen(DlgFileName, "w");
  62.     require(dlgFile!=NULL, eMsg1("genLexFile: cannot open %s", DlgFileName) );
  63.  
  64.     fprintf(dlgFile, "<<\n");
  65.     fprintf(dlgFile, "/* %s -- DLG Description of scanner\n", DlgFileName);
  66.     fprintf(dlgFile, " *\n");
  67.     fprintf(dlgFile, " * Generated from:");
  68.     {int i; for (i=0; i<NumFiles; i++) fprintf(dlgFile, " %s", FileStr[i]);}
  69.     fprintf(dlgFile, "\n");
  70.     fprintf(dlgFile, " *\n");
  71.     fprintf(dlgFile, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-1993\n");
  72.     fprintf(dlgFile, " * Purdue University Electrical Engineering\n");
  73.     fprintf(dlgFile, " * ANTLR Version %s\n", Version);
  74.     fprintf(dlgFile, " */\n");
  75.     fprintf(dlgFile, "#include <stdio.h>\n");
  76.     fprintf(dlgFile, "#define ANTLR_VERSION    %s\n", VersionDef);
  77.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  78.         fprintf(dlgFile, "#define %s %s\n", DefaultParserName, ParserName);
  79.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  80.         fprintf(dlgFile, "#include \"%s\"\n", RemapFileName);
  81.     if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 );
  82.     if ( FoundGuessBlk )
  83.     {
  84.         fprintf(dlgFile, "#define ZZCAN_GUESS\n");
  85.         fprintf(dlgFile, "#include <setjmp.h>\n");
  86.     }
  87.     if ( OutputLL_k > 1 ) fprintf(dlgFile, "#define LL_K %d\n", OutputLL_k);
  88.     if ( DemandLookahead ) fprintf(dlgFile, "#define DEMAND_LOOK\n");
  89.     fprintf(dlgFile, "#include \"antlr.h\"\n");
  90.     if ( GenAST ) fprintf(dlgFile, "#include \"ast.h\"\n");
  91.     fprintf(dlgFile, "#include \"%s\"\n", DefFileName);
  92.     fprintf(dlgFile, "#include \"dlgdef.h\"\n");
  93.     fprintf(dlgFile, "LOOKAHEAD\n");
  94.     fprintf(dlgFile, "void zzerraction()\n");
  95.     fprintf(dlgFile, "{\n");
  96.     fprintf(dlgFile, "\t(*zzerr)(\"%s\");\n", DLGErrorString);
  97.     fprintf(dlgFile, "\tzzadvance();\n");
  98.     fprintf(dlgFile, "\tzzskip();\n");
  99.     fprintf(dlgFile, "}\n>>\n\n");
  100.     /* dump all actions */
  101.     if (LexActions != NULL)
  102.     {
  103.         for (p = LexActions->next; p!=NULL; p=p->next)
  104.         {
  105.             fprintf(dlgFile, "<<\n");
  106.             dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 );
  107.             fprintf(dlgFile, ">>\n");
  108.         }
  109.     }
  110.     /* dump all regular expression rules/actions (skip sentinel node) */
  111.     if ( ExprOrder == NULL ) {
  112.         warnNoFL("no regular expressions found in grammar");
  113.     }
  114.     else dumpLexClasses(dlgFile);
  115.     fprintf(dlgFile, "%%%%\n");
  116.     fclose( dlgFile );
  117. }
  118.  
  119. /* For each lexical class, scan ExprOrder looking for expressions
  120.  * in that lexical class.  Print out only those that match.
  121.  * Each element of the ExprOrder list has both an expr and an lclass
  122.  * field.
  123.  */
  124. void
  125. #ifdef __STDC__
  126. dumpLexClasses( FILE *dlgFile )
  127. #else
  128. dumpLexClasses( dlgFile )
  129. FILE *dlgFile;
  130. #endif
  131. {
  132.     int i;
  133.     TermEntry *t;
  134.     ListNode *p;
  135.     Expr *q;
  136.  
  137.     for (i=0; i<NumLexClasses; i++)
  138.     {
  139.         fprintf(dlgFile, "\n%%%%%s\n\n", lclass[i].classnum);
  140.         for (p=ExprOrder->next; p!=NULL; p=p->next)
  141.         {
  142.             q = (Expr *) p->elem;
  143.             if ( q->lclass != i ) continue;
  144.             lexmode(i);
  145.             t = (TermEntry *) hash_get(Texpr, q->expr);
  146.             require(t!=NULL, eMsg1("genLexDescr: rexpr %s not in hash table",q->expr) );
  147.             if ( t->token == EpToken ) continue;
  148.             fprintf(dlgFile, "%s\n\t<<\n", StripQuotes(q->expr));
  149.             /* replace " killed by StripQuotes() */
  150.             q->expr[ strlen(q->expr) ] = '"';
  151.             if ( TokenStr[t->token] != NULL )
  152.                 fprintf(dlgFile, "\t\tNLA = %s;\n", TokenStr[t->token]);
  153.             else fprintf(dlgFile, "\t\tNLA = %d;\n", t->token);
  154.             if ( t->action != NULL ) dumpAction( t->action, dlgFile, 2,-1,0,1 );
  155.             fprintf(dlgFile, "\t>>\n\n");
  156.         }
  157.     }
  158. }
  159.  
  160. /* Generate a list of #defines && list of struct definitions for
  161.  * aggregate retv's */
  162. void
  163. #ifdef __STDC__
  164. genDefFile( void )
  165. #else
  166. genDefFile( )
  167. #endif
  168. {
  169.     int i;
  170.  
  171.     DefFile = fopen(DefFileName, "w");
  172.     require(DefFile!=NULL, eMsg1("genDefFile: cannot open %s", DefFileName) );
  173.  
  174.     fprintf(DefFile, "/* %s -- List of labelled tokens and stuff\n", DefFileName);
  175.     fprintf(DefFile, " *\n");
  176.     fprintf(DefFile, " * Generated from:");
  177.     for (i=0; i<NumFiles; i++) fprintf(DefFile, " %s", FileStr[i]);
  178.     fprintf(DefFile, "\n");
  179.     fprintf(DefFile, " *\n");
  180.     fprintf(DefFile, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-1993\n");
  181.     fprintf(DefFile, " * Purdue University Electrical Engineering\n");
  182.     fprintf(DefFile, " * ANTLR Version %s\n", Version);
  183.     fprintf(DefFile, " */\n");
  184.     if ( TokenStr[EofToken]!=NULL )
  185.         fprintf(DefFile, "#define %s %d\n", TokenStr[EofToken], EofToken);
  186.     for (i=TokenStart; i<TokenNum; i++)
  187.     {
  188.         if ( TokenStr[i]!=NULL && i != EpToken )
  189.         {
  190.             TermEntry *p;
  191.  
  192.             require((p=(TermEntry *)hash_get(Tname, TokenStr[i])) != NULL,
  193.                     "token not in sym tab when it should be");
  194.             if ( !p->errclassname )
  195.             {
  196.                 fprintf(DefFile, "#define %s %d\n", TokenStr[i], i);
  197.             }
  198.         }
  199.     }
  200.  
  201.     GenRulePrototypes(DefFile, SynDiag);
  202. }
  203.  
  204. void
  205. #ifdef __STDC__
  206. GenRemapFile( void )
  207. #else
  208. GenRemapFile( )
  209. #endif
  210. {
  211.     if ( strcmp(ParserName, DefaultParserName)!=0 )
  212.     {
  213.         FILE *f;
  214.         int i;
  215.  
  216.         f = fopen(RemapFileName, "w");
  217.         require(f!=NULL, eMsg1("GenRemapFile: cannot open %s", RemapFileName) );
  218.  
  219.         fprintf(f, "/* %s -- List of symbols to remap\n", RemapFileName);
  220.         fprintf(f, " *\n");
  221.         fprintf(f, " * Generated from:");
  222.         for (i=0; i<NumFiles; i++) fprintf(f, " %s", FileStr[i]);
  223.         fprintf(f, "\n");
  224.         fprintf(f, " *\n");
  225.         fprintf(f, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-1993\n");
  226.         fprintf(f, " * Purdue University Electrical Engineering\n");
  227.         fprintf(f, " * ANTLR Version %s\n", Version);
  228.         fprintf(f, " */\n");
  229.  
  230.         GenRuleFuncRedefs(f, SynDiag);
  231.         GenPredefinedSymbolRedefs(f);
  232.         if ( GenAST ) GenASTSymbolRedefs(f);
  233.         GenSetRedefs(f);
  234.  
  235.         fclose(f);
  236.     }
  237. }
  238.  
  239. /* Generate a bunch of #defines that rename all functions to be "ParserName_func" */
  240. void
  241. #ifdef __STDC__
  242. GenRuleFuncRedefs( FILE *f, Junction *p )
  243. #else
  244. GenRuleFuncRedefs( f, p )
  245. FILE *f;
  246. Junction *p;
  247. #endif
  248. {
  249.     fprintf(f, "\n/* rename rule functions to be 'ParserName_func' */\n");
  250.     while ( p!=NULL )
  251.     {
  252.         fprintf(f, "#define %s %s_%s\n", p->rname, ParserName, p->rname);
  253.         p = (Junction *)p->p2;
  254.     }
  255. }
  256.  
  257. /* Generate a bunch of #defines that rename all standard symbols to be
  258.  * "ParserName_symbol".  The list of standard symbols to change is in
  259.  * globals.c.
  260.  */
  261. void
  262. #ifdef __STDC__
  263. GenPredefinedSymbolRedefs( FILE *f )
  264. #else
  265. GenPredefinedSymbolRedefs( f )
  266. FILE *f;
  267. #endif
  268. {
  269.     char **p;
  270.  
  271.     fprintf(f, "\n/* rename PCCTS-supplied symbols to be 'ParserName_symbol' */\n");
  272.     for (p = &StandardSymbols[0]; *p!=NULL; p++)
  273.     {
  274.         fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p);
  275.     }
  276. }
  277.  
  278. /* Generate a bunch of #defines that rename all AST symbols to be
  279.  * "ParserName_symbol".  The list of AST symbols to change is in
  280.  * globals.c.
  281.  */
  282. void
  283. #ifdef __STDC__
  284. GenASTSymbolRedefs( FILE *f )
  285. #else
  286. GenASTSymbolRedefs( f )
  287. FILE *f;
  288. #endif
  289. {
  290.     char **p;
  291.  
  292.     fprintf(f, "\n/* rename PCCTS-supplied AST symbols to be 'ParserName_symbol' */\n");
  293.     for (p = &ASTSymbols[0]; *p!=NULL; p++)
  294.     {
  295.         fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p);
  296.     }
  297. }
  298.  
  299. /* redefine all sets generated by ANTLR; WARNING:  'zzerr', 'setwd' must match
  300.  * use in bits.c (DumpSetWd() etc...)
  301.  */
  302. void
  303. #ifdef __STDC__
  304. GenSetRedefs( FILE *f )
  305. #else
  306. GenSetRedefs( f )
  307. FILE *f;
  308. #endif
  309. {
  310.     int i;
  311.  
  312.     for (i=1; i<=wordnum; i++)
  313.     {
  314.         fprintf(f, "#define setwd%d %s_setwd%d\n", i, ParserName, i);
  315.     }
  316.     for (i=1; i<=esetnum; i++)
  317.     {
  318.         fprintf(f, "#define zzerr%d %s_err%d\n", i, ParserName, i);
  319.     }
  320. }
  321.  
  322. /* Find all return types/parameters that require structs and def
  323.  * all rules with ret types.
  324.  */
  325. void
  326. #ifdef __STDC__
  327. GenRulePrototypes( FILE *f, Junction *p )
  328. #else
  329. GenRulePrototypes( f, p )
  330. FILE *f;
  331. Junction *p;
  332. #endif
  333. {
  334.     int i;
  335.  
  336.     i = 1;
  337.     while ( p!=NULL )
  338.     {
  339.         if ( p->ret != NULL )
  340.         {
  341.             if ( HasComma(p->ret) )
  342.             {
  343.                 DumpRetValStruct(f, p->ret, i);
  344.             }
  345.             fprintf(f, "\n#ifdef __STDC__\n");
  346.             if ( HasComma(p->ret) )
  347.             {
  348.                 fprintf(f, "extern struct _rv%d", i);
  349.             }
  350.             else
  351.             {
  352.                 fprintf(f, "extern ");
  353.                 DumpType(p->ret, f);
  354.             }
  355.             fprintf(f, " %s%s(", RulePrefix, p->rname);
  356.             if ( p->pdecl != NULL || GenAST )
  357.             {
  358.                 if ( GenAST ) fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":"");
  359.                 if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
  360.             }
  361.             else fprintf(f, "void");
  362.             fprintf(f, ");\n");
  363.             fprintf(f, "#else\n");
  364.             if ( HasComma(p->ret) )
  365.             {
  366.                 fprintf(f, "extern struct _rv%d", i);
  367.             }
  368.             else
  369.             {
  370.                 fprintf(f, "extern ");
  371.                 DumpType(p->ret, f);
  372.             }
  373.             fprintf(f, " %s%s();\n", RulePrefix, p->rname);
  374.             fprintf(f, "#endif\n");
  375.         }
  376.         else
  377.         {
  378.             fprintf(f, "\n#ifdef __STDC__\n");
  379.             fprintf(f, "void %s%s(", RulePrefix, p->rname);
  380.             if ( p->pdecl != NULL || GenAST )
  381.             {
  382.                 if ( GenAST ) fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":"");
  383.                 if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
  384.             }
  385.             else fprintf(f, "void");
  386.             fprintf(f, ");\n");
  387.             fprintf(f, "#else\n");
  388.             fprintf(f, "extern %s%s();\n", RulePrefix, p->rname);
  389.             fprintf(f, "#endif\n");
  390.         }
  391.         i++;
  392.         p = (Junction *)p->p2;
  393.     }
  394. }
  395.  
  396. /* Given a list of ANSI-style parameter declarations, print out a
  397.  * comma-separated list of the symbols (w/o types).
  398.  * Basically, we look for a comma, then work backwards until start of
  399.  * the symbol name.  Then print it out until 1st non-alnum char.  Now,
  400.  * move on to next parameter.
  401.  */
  402. void
  403. #ifdef __STDC__
  404. DumpListOfParmNames( char *pdecl, FILE *output )
  405. #else
  406. DumpListOfParmNames( pdecl, output )
  407. char *pdecl;
  408. FILE *output;
  409. #endif
  410. {
  411.     int firstTime = 1, done = 0;
  412.     require(output!=NULL, "DumpListOfParmNames: NULL parm");
  413.  
  414.     if ( pdecl == NULL ) return;
  415.     while ( !done )
  416.     {
  417.         if ( !firstTime ) putc(',', output);
  418.         done = DumpNextNameInDef(&pdecl, output);
  419.         firstTime = 0;
  420.     }
  421. }
  422.  
  423. /* given a list of parameters or return values, dump the next
  424.  * name to output.  Return 1 if last one just printed, 0 if more to go.
  425.  */
  426. int
  427. #ifdef __STDC__
  428. DumpNextNameInDef( char **q, FILE *output )
  429. #else
  430. DumpNextNameInDef( q, output )
  431. char **q;
  432. FILE *output;
  433. #endif
  434. {
  435.     char *p = *q;        /* where did we leave off? */
  436.     int done=0;
  437.  
  438.     while ( *p!='\0' && *p!=',' ) p++;        /* find end of decl */
  439.     if ( *p == '\0' ) done = 1;
  440.     while ( !isalnum(*p) && *p!='_' ) --p;    /* scan back until valid var character */
  441.     while ( isalnum(*p) || *p=='_' ) --p;    /* scan back until beginning of variable */
  442.     p++;                        /* move to start of variable */
  443.     while ( isalnum(*p) || *p=='_'  ) {putc(*p, output); p++;}
  444.     while ( *p!='\0' && *p!=',' ) p++;        /* find end of decl */
  445.     p++;                /* move past this parameter */
  446.  
  447.     *q = p;                /* record where we left off */
  448.     return done;
  449. }
  450.  
  451. /* Given a list of ANSI-style parameter declarations, dump K&R-style
  452.  * declarations, one per line for each parameter.  Basically, convert
  453.  * comma to semi-colon, newline.
  454.  */
  455. void
  456. #ifdef __STDC__
  457. DumpOldStyleParms( char *pdecl, FILE *output )
  458. #else
  459. DumpOldStyleParms( pdecl, output )
  460. char *pdecl;
  461. FILE *output;
  462. #endif
  463. {
  464.     require(output!=NULL, "DumpOldStyleParms: NULL parm");
  465.  
  466.     if ( pdecl == NULL ) return;
  467.     while ( *pdecl != '\0' )
  468.     {
  469.         if ( *pdecl == ',' )
  470.         {
  471.             pdecl++;
  472.             putc(';', output); putc('\n', output);
  473.             while ( *pdecl==' ' || *pdecl=='\t' || *pdecl=='\n' ) pdecl++;
  474.         }
  475.         else {putc(*pdecl, output); pdecl++;}
  476.     }
  477.     putc(';', output);
  478.     putc('\n', output);
  479. }
  480.  
  481. /* Take in a type definition (type + symbol) and print out type only */
  482. void
  483. #ifdef __STDC__
  484. DumpType( char *s, FILE *f )
  485. #else
  486. DumpType( s, f )
  487. char *s;
  488. FILE *f;
  489. #endif
  490. {
  491.     char *p, *end;
  492.     require(s!=NULL, "DumpType: invalid type string");
  493.  
  494.     p = &s[strlen(s)-1];        /* start at end of string and work back */
  495.     /* scan back until valid variable character */
  496.     while ( !isalnum(*p) && *p!='_' ) --p;
  497.     /* scan back until beginning of variable */
  498.     while ( isalnum(*p) || *p=='_' ) --p;
  499.     if ( p<=s )
  500.     {
  501.         warnNoFL(eMsg1("invalid parameter/return value: '%s'",s));
  502.         return;
  503.     }
  504.     end = p;                    /* here is where we stop printing alnum */
  505.     p = s;
  506.     while ( p!=end ) {putc(*p, f); p++;} /* dump until just before variable */
  507.     while ( *p!='\0' )                     /* dump rest w/o variable */
  508.     {
  509.         if ( !isalnum(*p) && *p!='_' ) putc(*p, f);
  510.         p++;
  511.     }
  512. }
  513.  
  514. /* check to see if string e is a word in string s */
  515. int
  516. #ifdef __STDC__
  517. strmember( char *s, char *e )
  518. #else
  519. strmember( s, e )
  520. char *s;
  521. char *e;
  522. #endif
  523. {
  524.     register char *p;
  525.     require(s!=NULL&&e!=NULL, "strmember: NULL string");
  526.     
  527.     if ( *e=='\0' ) return 1;   /* empty string is always member */
  528.     do {
  529.     while ( *s!='\0' && !isalnum(*s) && *s!='_' )
  530.     ++s;
  531.     p = e;
  532.     while ( *p!='\0' && *p==*s ) {p++; s++;}
  533.     if ( *p=='\0' ) {
  534.         if ( *s=='\0' ) return 1;
  535.         if ( !isalnum (*s) && *s != '_' ) return 1;
  536.     }
  537.     while ( isalnum(*s) || *s == '_' )
  538.     ++s;
  539.     } while ( *s!='\0' );
  540.     return 0;
  541. }
  542.  
  543. int
  544. #ifdef __STDC__
  545. HasComma( char *s )
  546. #else
  547. HasComma( s )
  548. char *s;
  549. #endif
  550. {
  551.     while (*s!='\0')
  552.         if ( *s++ == ',' ) return 1;
  553.     return 0;
  554. }
  555.  
  556. void
  557. #ifdef __STDC__
  558. DumpRetValStruct( FILE *f, char *ret, int i )
  559. #else
  560. DumpRetValStruct( f, ret, i )
  561. FILE *f;
  562. char *ret;
  563. int i;
  564. #endif
  565. {
  566.     fprintf(f, "\nstruct _rv%d {\n", i);
  567.     while ( *ret != '\0' )
  568.     {
  569.          while ( *ret==' ' || *ret=='\t' ) ret++; /* ignore white */
  570.          putc('\t', f);
  571.          while ( *ret!=',' && *ret!='\0' ) putc(*ret++, f);
  572.          if ( *ret == ',' ) {putc(';', f); putc('\n', f); ret++;}
  573.     }
  574.     fprintf(f, ";\n};\n");
  575. }
  576.  
  577. /* given "s" yield s -- DESTRUCTIVE (we modify s if starts with " else return s) */
  578. char *
  579. #ifdef __STDC__
  580. StripQuotes( char *s )
  581. #else
  582. StripQuotes( s )
  583. char *s;
  584. #endif
  585. {
  586.     if ( *s == '"' )
  587.     {
  588.         s[ strlen(s)-1 ] = '\0';    /* remove last quote */
  589.         return( s+1 );                /* return address past initial quote */
  590.     }
  591.     return( s );
  592. }
  593.  
  594.