home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / p / pccts.zip / antlr / lex.c < prev    next >
C/C++ Source or Header  |  1992-12-08  |  12KB  |  405 lines

  1. /*
  2.  * lex.c    --    Generate all of the lexical type files: parser.dlg tokens.h
  3.  *
  4.  * SOFTWARE RIGHTS
  5.  *
  6.  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
  7.  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
  8.  * company may do whatever they wish with source code distributed with
  9.  * PCCTS or the code generated by PCCTS, including the incorporation of
  10.  * PCCTS, or its output, into commerical software.
  11.  * 
  12.  * We encourage users to develop software with PCCTS.  However, we do ask
  13.  * that credit is given to us for developing PCCTS.  By "credit",
  14.  * we mean that if you incorporate our source code into one of your
  15.  * programs (commercial product, research project, or otherwise) that you
  16.  * acknowledge this fact somewhere in the documentation, research report,
  17.  * etc...  If you like PCCTS and have developed a nice tool with the
  18.  * output, please mention that you developed it using PCCTS.  In
  19.  * addition, we ask that this header remain intact in our source code.
  20.  * As long as these guidelines are kept, we expect to continue enhancing
  21.  * this system and expect to make other tools available as they are
  22.  * completed.
  23.  *
  24.  * ANTLR 1.06
  25.  * Terence Parr
  26.  * Purdue University
  27.  * 1989-1992
  28.  */
  29. #include <stdio.h>
  30. #include <ctype.h>
  31. #include "set.h"
  32. #include "syn.h"
  33. #include "hash.h"
  34. #include "generic.h"
  35.  
  36. #define DLGErrorString "invalid token"
  37.  
  38. /* Generate a complete lexical description of the lexemes found in the grammar */
  39. void
  40. genLexDescr()
  41. {
  42.     ListNode *p;
  43.     FILE *dlgFile = fopen(DlgFileName, "w");
  44.     require(dlgFile!=NULL, eMsg1("genLexFile: cannot open %s", DlgFileName) );
  45.  
  46.     fprintf(dlgFile, "<<\n");
  47.     fprintf(dlgFile, "/* %s -- DLG Description of scanner\n", DlgFileName);
  48.     fprintf(dlgFile, " *\n");
  49.     fprintf(dlgFile, " * Generated from:");
  50.     {int i; for (i=0; i<NumFiles; i++) fprintf(dlgFile, " %s", FileStr[i]);}
  51.     fprintf(dlgFile, "\n");
  52.     fprintf(dlgFile, " *\n");
  53.     fprintf(dlgFile, " * Terence Parr, Hank Dietz and Will Cohen: 1989-1992\n");
  54.     fprintf(dlgFile, " * Purdue University Electrical Engineering\n");
  55.     fprintf(dlgFile, " * ANTLR Version %s\n", Version);
  56.     fprintf(dlgFile, " */\n");
  57.     fprintf(dlgFile, "#include <stdio.h>\n");
  58.     if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 );
  59.     if ( LL_k > 1 ) fprintf(dlgFile, "#define LL_K %d\n", OutputLL_k);
  60.     if ( DemandLookahead ) fprintf(dlgFile, "#define DEMAND_LOOK\n");
  61.     fprintf(dlgFile, "#include \"antlr.h\"\n");
  62.     if ( GenAST ) fprintf(dlgFile, "#include \"ast.h\"\n");
  63.     fprintf(dlgFile, "#include \"%s\"\n", DefFileName);
  64.     fprintf(dlgFile, "#include \"dlgdef.h\"\n");
  65.     fprintf(dlgFile, "LOOKAHEAD\n");
  66.     fprintf(dlgFile, "void zzerraction()\n");
  67.     fprintf(dlgFile, "{\n");
  68.     fprintf(dlgFile, "\t(*zzerr)(\"%s\");\n", DLGErrorString);
  69.     fprintf(dlgFile, "\tzzadvance();\n");
  70.     fprintf(dlgFile, "\tzzskip();\n");
  71.     fprintf(dlgFile, "}\n>>\n\n");
  72.     /* dump all actions */
  73.     if (LexActions != NULL)
  74.     {
  75.         for (p = LexActions->next; p!=NULL; p=p->next)
  76.         {
  77.             fprintf(dlgFile, "<<\n");
  78.             dumpAction( p->elem, dlgFile, 0, -1, 0, 1 );
  79.             fprintf(dlgFile, ">>\n");
  80.         }
  81.     }
  82.     /* dump all regular expression rules/actions (skip sentinel node) */
  83.     if ( ExprOrder == NULL ) {
  84.         warnNoFL("no regular expressions found in grammar");
  85.     }
  86.     else dumpLexClasses(dlgFile);
  87.     fprintf(dlgFile, "%%%%\n");
  88.     fclose( dlgFile );
  89. }
  90.  
  91. /* For each lexical class, scan ExprOrder looking for expressions
  92.  * in that lexical class.  Print out only those that match.
  93.  * Each element of the ExprOrder list has both an expr and an lclass
  94.  * field.
  95.  */
  96. dumpLexClasses(dlgFile)
  97. FILE *dlgFile;
  98. {
  99.     int i;
  100.     TermEntry *t;
  101.     ListNode *p;
  102.     Expr *q;
  103.  
  104.     for (i=0; i<NumLexClasses; i++)
  105.     {
  106.         fprintf(dlgFile, "\n%%%%%s\n\n", lclass[i].class);
  107.         for (p=ExprOrder->next; p!=NULL; p=p->next)
  108.         {
  109.             q = (Expr *) p->elem;
  110.             if ( q->lclass != i ) continue;
  111.             lexmode(i);
  112.             t = (TermEntry *) hash_get(Texpr, q->expr);
  113.             require(t!=NULL, eMsg1("genLexDescr: rexpr %s not in hash table",q->expr) );
  114.             if ( t->token == EpToken ) continue;
  115.             fprintf(dlgFile, "%s\n\t<<\n", StripQuotes(q->expr));
  116.             /* replace " killed by StripQuotes() */
  117.             q->expr[ strlen(q->expr) ] = '"';
  118.             if ( TokenStr[t->token] != NULL )
  119.                 fprintf(dlgFile, "\t\tNLA = %s;\n", TokenStr[t->token]);
  120.             else fprintf(dlgFile, "\t\tNLA = %d;\n", t->token);
  121. /*
  122.             if ( TokenStr[t->token] != NULL )
  123.                 fprintf(dlgFile, "\t\tLA(1) = %s;\n", TokenStr[t->token]);
  124.             else fprintf(dlgFile, "\t\tLA(1) = %d;\n", t->token);
  125. */
  126.             if ( t->action != NULL ) dumpAction( t->action, dlgFile, 2,-1,0,1 );
  127.             fprintf(dlgFile, "\t>>\n\n");
  128.         }
  129.     }
  130. }
  131.  
  132. /* Generate a list of #defines && list of struct definitions for
  133.  * aggregate retv's */
  134. void
  135. genDefFile()
  136. {
  137.     Junction *p  = SynDiag;
  138.     int i;
  139.  
  140.     DefFile = fopen(DefFileName, "w");
  141.     require(DefFile!=NULL, eMsg1("genDefFile: cannot open %s", DefFileName) );
  142.     fprintf(DefFile, "/* %s -- List of labelled tokens\n", DefFileName);
  143.     fprintf(DefFile, " *\n");
  144.     fprintf(DefFile, " * Generated from:");
  145.     for (i=0; i<NumFiles; i++) fprintf(DefFile, " %s", FileStr[i]);
  146.     fprintf(DefFile, "\n");
  147.     fprintf(DefFile, " *\n");
  148.     fprintf(DefFile, " * Terence Parr, Hank Dietz and Will Cohen: 1989-1992\n");
  149.     fprintf(DefFile, " * Purdue University Electrical Engineering\n");
  150.     fprintf(DefFile, " * ANTLR Version %s\n", Version);
  151.     fprintf(DefFile, " */\n");
  152.     if ( TokenStr[EofToken]!=NULL )
  153.         fprintf(DefFile, "#define %s %d\n", TokenStr[EofToken], EofToken);
  154.     for (i=TokenStart; i<TokenNum; i++)
  155.     {
  156.         if ( TokenStr[i]!=NULL && i != EpToken )
  157.         {
  158.             TermEntry *p;
  159.  
  160.             require((p=(TermEntry *)hash_get(Tname, TokenStr[i])) != NULL,
  161.                     "token not in sym tab when it should be");
  162.             if ( !p->errclassname )
  163.             {
  164.                 fprintf(DefFile, "#define %s %d\n", TokenStr[i], i);
  165.             }
  166.         }
  167.     }
  168.  
  169.     GenRulePrototypes(DefFile, p);
  170. }
  171.  
  172. /* Find all return types/parameters that require structs and def
  173.  * all rules with ret types.
  174.  */
  175. void
  176. GenRulePrototypes(f, p)
  177. FILE *f;
  178. Junction *p;
  179. {
  180.     int i;
  181.  
  182.     i = 1;
  183.     while ( p!=NULL )
  184.     {
  185.         if ( p->ret != NULL )
  186.         {
  187.             if ( HasComma(p->ret) )
  188.             {
  189.                 DumpRetValStruct(f, p->ret, i);
  190.             }
  191.             fprintf(f, "\n#ifdef __STDC__\n");
  192.             if ( HasComma(p->ret) )
  193.             {
  194.                 fprintf(f, "extern struct _rv%d", i);
  195.             }
  196.             else
  197.             {
  198.                 fprintf(f, "extern ");
  199.                 DumpType(p->ret, f);
  200.             }
  201.             fprintf(f, " %s%s(", RulePrefix, p->rname);
  202.             if ( p->pdecl != NULL || GenAST )
  203.             {
  204.                 if ( GenAST ) fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":"");
  205.                 if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
  206.             }
  207.             fprintf(f, ");\n");
  208.             fprintf(f, "#else\n");
  209.             if ( HasComma(p->ret) )
  210.             {
  211.                 fprintf(f, "extern struct _rv%d", i);
  212.             }
  213.             else
  214.             {
  215.                 fprintf(f, "extern ");
  216.                 DumpType(p->ret, f);
  217.             }
  218.             fprintf(f, " %s%s();\n", RulePrefix, p->rname);
  219.             fprintf(f, "#endif\n");
  220.         }
  221.         else
  222.         {
  223.             fprintf(f, "\n#ifdef __STDC__\n");
  224.             fprintf(f, "void %s%s(", RulePrefix, p->rname);
  225.             if ( p->pdecl != NULL || GenAST )
  226.             {
  227.                 if ( GenAST ) fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":"");
  228.                 if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
  229.             }
  230.             fprintf(f, ");\n");
  231.             fprintf(f, "#else\n");
  232.             fprintf(f, "extern %s%s();\n", RulePrefix, p->rname);
  233.             fprintf(f, "#endif\n");
  234.         }
  235.         i++;
  236.         p = (Junction *)p->p2;
  237.     }
  238. }
  239.  
  240. /* Given a list of ANSI-style parameter declarations, print out a
  241.  * comma-separated list of the symbols (w/o types).
  242.  * Basically, we look for a comma, then work backwards until start of
  243.  * the symbol name.  Then print it out until 1st non-alnum char.  Now,
  244.  * move on to next parameter.
  245.  */
  246. void
  247. DumpListOfParmNames( pdecl, output )
  248. char *pdecl;
  249. FILE *output;
  250. {
  251.     char *end;
  252.     int firstTime = 1, done = 0;
  253.     require(output!=NULL, "DumpListOfParmNames: NULL parm");
  254.  
  255.     if ( pdecl == NULL ) return;
  256.     while ( !done )
  257.     {
  258.         if ( !firstTime ) putc(',', output);
  259.         done = DumpNextNameInDef(&pdecl, output);
  260.         firstTime = 0;
  261.     }
  262. }
  263.  
  264. /* given a list of parameters or return values, dump the next
  265.  * name to output.  Return 1 if last one just printed, 0 if more to go.
  266.  */
  267. DumpNextNameInDef(q, output)
  268. char **q;                /* pointer to ptr into definition string */
  269. FILE *output;
  270. {
  271.     char *p = *q;        /* where did we leave off? */
  272.     int done=0;
  273.  
  274.     while ( *p!='\0' && *p!=',' ) p++;        /* find end of decl */
  275.     if ( *p == '\0' ) done = 1;
  276.     while ( !isalnum(*p) && *p!='_' ) --p;    /* scan back until valid var character */
  277.     while ( isalnum(*p) || *p=='_' ) --p;    /* scan back until beginning of variable */
  278.     p++;                        /* move to start of variable */
  279.     while ( isalnum(*p) || *p=='_'  ) {putc(*p, output); p++;}
  280.     while ( *p!='\0' && *p!=',' ) p++;        /* find end of decl */
  281.     p++;                /* move past this parameter */
  282.  
  283.     *q = p;                /* record where we left off */
  284.     return done;
  285. }
  286.  
  287. /* Given a list of ANSI-style parameter declarations, dump K&R-style
  288.  * declarations, one per line for each parameter.  Basically, convert
  289.  * comma to semi-colon, newline.
  290.  */
  291. void
  292. DumpOldStyleParms( pdecl, output )
  293. char *pdecl;
  294. FILE *output;
  295. {
  296.     require(output!=NULL, "DumpOldStyleParms: NULL parm");
  297.  
  298.     if ( pdecl == NULL ) return;
  299.     while ( *pdecl != '\0' )
  300.     {
  301.         if ( *pdecl == ',' )
  302.         {
  303.             pdecl++;
  304.             putc(';', output); putc('\n', output);
  305.             while ( *pdecl==' ' || *pdecl=='\t' || *pdecl=='\n' ) pdecl++;
  306.         }
  307.         else {putc(*pdecl, output); pdecl++;}
  308.     }
  309.     putc(';', output);
  310.     putc('\n', output);
  311. }
  312.  
  313. /* Take in a type definition (type + symbol) and print out type only */
  314. void
  315. DumpType(s, f)
  316. char *s;
  317. FILE *f;
  318. {
  319.     char *p, *end;
  320.     require(s!=NULL, "DumpType: invalid type string");
  321.  
  322.     p = &s[strlen(s)-1];        /* start at end of string and work back */
  323.     /* scan back until valid variable character */
  324.     while ( !isalnum(*p) && *p!='_' ) --p;
  325.     /* scan back until beginning of variable */
  326.     while ( isalnum(*p) || *p=='_' ) --p;
  327.     if ( p<=s )
  328.     {
  329.         warnNoFL(eMsg1("invalid parameter/return value: '%s'",s));
  330.         return;
  331.     }
  332.     end = p;                    /* here is where we stop printing alnum */
  333.     p = s;
  334.     while ( p!=end ) {putc(*p, f); p++;} /* dump until just before variable */
  335.     while ( *p!='\0' )                     /* dump rest w/o variable */
  336.     {
  337.         if ( !isalnum(*p) && *p!='_' ) putc(*p, f);
  338.         p++;
  339.     }
  340. }
  341.  
  342. /* check to see if string e is a word in string s */
  343. int
  344. strmember(s, e)
  345.   char *s, *e;
  346. {
  347.     register char *p;
  348.     require(s!=NULL&&e!=NULL, "strmember: NULL string");
  349.     
  350.     if ( *e=='\0' ) return 1;   /* empty string is always member */
  351.     do {
  352.     while ( *s!='\0' && !isalnum(*s) && *s!='_' )
  353.     ++s;
  354.     p = e;
  355.     while ( *p!='\0' && *p==*s ) {p++; s++;}
  356.     if ( *p=='\0' ) {
  357.         if ( *s=='\0' ) return 1;
  358.         if ( !isalnum (*s) && *s != '_' ) return 1;
  359.     }
  360.     while ( isalnum(*s) || *s == '_' )
  361.     ++s;
  362.     } while ( *s!='\0' );
  363.     return 0;
  364. }
  365.  
  366. int
  367. HasComma(s)
  368. char *s;
  369. {
  370.     while (*s!='\0')
  371.         if ( *s++ == ',' ) return 1;
  372.     return 0;
  373. }
  374.  
  375. void
  376. DumpRetValStruct(f,ret,i)
  377. FILE *f;
  378. char *ret;
  379. int i;
  380. {
  381.     fprintf(f, "\nstruct _rv%d {\n", i);
  382.     while ( *ret != '\0' )
  383.     {
  384.          while ( *ret==' ' || *ret=='\t' ) ret++; /* ignore white */
  385.          putc('\t', f);
  386.          while ( *ret!=',' && *ret!='\0' ) putc(*ret++, f);
  387.          if ( *ret == ',' ) {putc(';', f); putc('\n', f); ret++;}
  388.     }
  389.     fprintf(f, ";\n};\n");
  390. }
  391.  
  392. /* given "s" yield s -- DESTRUCTIVE (we modify s if starts with " else return s) */
  393. char *
  394. StripQuotes(s)
  395. char *s;
  396. {
  397.     if ( *s == '"' )
  398.     {
  399.         s[ strlen(s)-1 ] = '\0';    /* remove last quote */
  400.         return( s+1 );                /* return address past initial quote */
  401.     }
  402.     return( s );
  403. }
  404.  
  405.