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 >
Wrap
C/C++ Source or Header
|
1992-12-08
|
12KB
|
405 lines
/*
* lex.c -- Generate all of the lexical type files: parser.dlg tokens.h
*
* SOFTWARE RIGHTS
*
* We reserve no LEGAL rights to the Purdue Compiler Construction Tool
* Set (PCCTS) -- PCCTS is in the public domain. An individual or
* company may do whatever they wish with source code distributed with
* PCCTS or the code generated by PCCTS, including the incorporation of
* PCCTS, or its output, into commerical software.
*
* We encourage users to develop software with PCCTS. However, we do ask
* that credit is given to us for developing PCCTS. By "credit",
* we mean that if you incorporate our source code into one of your
* programs (commercial product, research project, or otherwise) that you
* acknowledge this fact somewhere in the documentation, research report,
* etc... If you like PCCTS and have developed a nice tool with the
* output, please mention that you developed it using PCCTS. In
* addition, we ask that this header remain intact in our source code.
* As long as these guidelines are kept, we expect to continue enhancing
* this system and expect to make other tools available as they are
* completed.
*
* ANTLR 1.06
* Terence Parr
* Purdue University
* 1989-1992
*/
#include <stdio.h>
#include <ctype.h>
#include "set.h"
#include "syn.h"
#include "hash.h"
#include "generic.h"
#define DLGErrorString "invalid token"
/* Generate a complete lexical description of the lexemes found in the grammar */
void
genLexDescr()
{
ListNode *p;
FILE *dlgFile = fopen(DlgFileName, "w");
require(dlgFile!=NULL, eMsg1("genLexFile: cannot open %s", DlgFileName) );
fprintf(dlgFile, "<<\n");
fprintf(dlgFile, "/* %s -- DLG Description of scanner\n", DlgFileName);
fprintf(dlgFile, " *\n");
fprintf(dlgFile, " * Generated from:");
{int i; for (i=0; i<NumFiles; i++) fprintf(dlgFile, " %s", FileStr[i]);}
fprintf(dlgFile, "\n");
fprintf(dlgFile, " *\n");
fprintf(dlgFile, " * Terence Parr, Hank Dietz and Will Cohen: 1989-1992\n");
fprintf(dlgFile, " * Purdue University Electrical Engineering\n");
fprintf(dlgFile, " * ANTLR Version %s\n", Version);
fprintf(dlgFile, " */\n");
fprintf(dlgFile, "#include <stdio.h>\n");
if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 );
if ( LL_k > 1 ) fprintf(dlgFile, "#define LL_K %d\n", OutputLL_k);
if ( DemandLookahead ) fprintf(dlgFile, "#define DEMAND_LOOK\n");
fprintf(dlgFile, "#include \"antlr.h\"\n");
if ( GenAST ) fprintf(dlgFile, "#include \"ast.h\"\n");
fprintf(dlgFile, "#include \"%s\"\n", DefFileName);
fprintf(dlgFile, "#include \"dlgdef.h\"\n");
fprintf(dlgFile, "LOOKAHEAD\n");
fprintf(dlgFile, "void zzerraction()\n");
fprintf(dlgFile, "{\n");
fprintf(dlgFile, "\t(*zzerr)(\"%s\");\n", DLGErrorString);
fprintf(dlgFile, "\tzzadvance();\n");
fprintf(dlgFile, "\tzzskip();\n");
fprintf(dlgFile, "}\n>>\n\n");
/* dump all actions */
if (LexActions != NULL)
{
for (p = LexActions->next; p!=NULL; p=p->next)
{
fprintf(dlgFile, "<<\n");
dumpAction( p->elem, dlgFile, 0, -1, 0, 1 );
fprintf(dlgFile, ">>\n");
}
}
/* dump all regular expression rules/actions (skip sentinel node) */
if ( ExprOrder == NULL ) {
warnNoFL("no regular expressions found in grammar");
}
else dumpLexClasses(dlgFile);
fprintf(dlgFile, "%%%%\n");
fclose( dlgFile );
}
/* For each lexical class, scan ExprOrder looking for expressions
* in that lexical class. Print out only those that match.
* Each element of the ExprOrder list has both an expr and an lclass
* field.
*/
dumpLexClasses(dlgFile)
FILE *dlgFile;
{
int i;
TermEntry *t;
ListNode *p;
Expr *q;
for (i=0; i<NumLexClasses; i++)
{
fprintf(dlgFile, "\n%%%%%s\n\n", lclass[i].class);
for (p=ExprOrder->next; p!=NULL; p=p->next)
{
q = (Expr *) p->elem;
if ( q->lclass != i ) continue;
lexmode(i);
t = (TermEntry *) hash_get(Texpr, q->expr);
require(t!=NULL, eMsg1("genLexDescr: rexpr %s not in hash table",q->expr) );
if ( t->token == EpToken ) continue;
fprintf(dlgFile, "%s\n\t<<\n", StripQuotes(q->expr));
/* replace " killed by StripQuotes() */
q->expr[ strlen(q->expr) ] = '"';
if ( TokenStr[t->token] != NULL )
fprintf(dlgFile, "\t\tNLA = %s;\n", TokenStr[t->token]);
else fprintf(dlgFile, "\t\tNLA = %d;\n", t->token);
/*
if ( TokenStr[t->token] != NULL )
fprintf(dlgFile, "\t\tLA(1) = %s;\n", TokenStr[t->token]);
else fprintf(dlgFile, "\t\tLA(1) = %d;\n", t->token);
*/
if ( t->action != NULL ) dumpAction( t->action, dlgFile, 2,-1,0,1 );
fprintf(dlgFile, "\t>>\n\n");
}
}
}
/* Generate a list of #defines && list of struct definitions for
* aggregate retv's */
void
genDefFile()
{
Junction *p = SynDiag;
int i;
DefFile = fopen(DefFileName, "w");
require(DefFile!=NULL, eMsg1("genDefFile: cannot open %s", DefFileName) );
fprintf(DefFile, "/* %s -- List of labelled tokens\n", DefFileName);
fprintf(DefFile, " *\n");
fprintf(DefFile, " * Generated from:");
for (i=0; i<NumFiles; i++) fprintf(DefFile, " %s", FileStr[i]);
fprintf(DefFile, "\n");
fprintf(DefFile, " *\n");
fprintf(DefFile, " * Terence Parr, Hank Dietz and Will Cohen: 1989-1992\n");
fprintf(DefFile, " * Purdue University Electrical Engineering\n");
fprintf(DefFile, " * ANTLR Version %s\n", Version);
fprintf(DefFile, " */\n");
if ( TokenStr[EofToken]!=NULL )
fprintf(DefFile, "#define %s %d\n", TokenStr[EofToken], EofToken);
for (i=TokenStart; i<TokenNum; i++)
{
if ( TokenStr[i]!=NULL && i != EpToken )
{
TermEntry *p;
require((p=(TermEntry *)hash_get(Tname, TokenStr[i])) != NULL,
"token not in sym tab when it should be");
if ( !p->errclassname )
{
fprintf(DefFile, "#define %s %d\n", TokenStr[i], i);
}
}
}
GenRulePrototypes(DefFile, p);
}
/* Find all return types/parameters that require structs and def
* all rules with ret types.
*/
void
GenRulePrototypes(f, p)
FILE *f;
Junction *p;
{
int i;
i = 1;
while ( p!=NULL )
{
if ( p->ret != NULL )
{
if ( HasComma(p->ret) )
{
DumpRetValStruct(f, p->ret, i);
}
fprintf(f, "\n#ifdef __STDC__\n");
if ( HasComma(p->ret) )
{
fprintf(f, "extern struct _rv%d", i);
}
else
{
fprintf(f, "extern ");
DumpType(p->ret, f);
}
fprintf(f, " %s%s(", RulePrefix, p->rname);
if ( p->pdecl != NULL || GenAST )
{
if ( GenAST ) fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":"");
if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
}
fprintf(f, ");\n");
fprintf(f, "#else\n");
if ( HasComma(p->ret) )
{
fprintf(f, "extern struct _rv%d", i);
}
else
{
fprintf(f, "extern ");
DumpType(p->ret, f);
}
fprintf(f, " %s%s();\n", RulePrefix, p->rname);
fprintf(f, "#endif\n");
}
else
{
fprintf(f, "\n#ifdef __STDC__\n");
fprintf(f, "void %s%s(", RulePrefix, p->rname);
if ( p->pdecl != NULL || GenAST )
{
if ( GenAST ) fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":"");
if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
}
fprintf(f, ");\n");
fprintf(f, "#else\n");
fprintf(f, "extern %s%s();\n", RulePrefix, p->rname);
fprintf(f, "#endif\n");
}
i++;
p = (Junction *)p->p2;
}
}
/* Given a list of ANSI-style parameter declarations, print out a
* comma-separated list of the symbols (w/o types).
* Basically, we look for a comma, then work backwards until start of
* the symbol name. Then print it out until 1st non-alnum char. Now,
* move on to next parameter.
*/
void
DumpListOfParmNames( pdecl, output )
char *pdecl;
FILE *output;
{
char *end;
int firstTime = 1, done = 0;
require(output!=NULL, "DumpListOfParmNames: NULL parm");
if ( pdecl == NULL ) return;
while ( !done )
{
if ( !firstTime ) putc(',', output);
done = DumpNextNameInDef(&pdecl, output);
firstTime = 0;
}
}
/* given a list of parameters or return values, dump the next
* name to output. Return 1 if last one just printed, 0 if more to go.
*/
DumpNextNameInDef(q, output)
char **q; /* pointer to ptr into definition string */
FILE *output;
{
char *p = *q; /* where did we leave off? */
int done=0;
while ( *p!='\0' && *p!=',' ) p++; /* find end of decl */
if ( *p == '\0' ) done = 1;
while ( !isalnum(*p) && *p!='_' ) --p; /* scan back until valid var character */
while ( isalnum(*p) || *p=='_' ) --p; /* scan back until beginning of variable */
p++; /* move to start of variable */
while ( isalnum(*p) || *p=='_' ) {putc(*p, output); p++;}
while ( *p!='\0' && *p!=',' ) p++; /* find end of decl */
p++; /* move past this parameter */
*q = p; /* record where we left off */
return done;
}
/* Given a list of ANSI-style parameter declarations, dump K&R-style
* declarations, one per line for each parameter. Basically, convert
* comma to semi-colon, newline.
*/
void
DumpOldStyleParms( pdecl, output )
char *pdecl;
FILE *output;
{
require(output!=NULL, "DumpOldStyleParms: NULL parm");
if ( pdecl == NULL ) return;
while ( *pdecl != '\0' )
{
if ( *pdecl == ',' )
{
pdecl++;
putc(';', output); putc('\n', output);
while ( *pdecl==' ' || *pdecl=='\t' || *pdecl=='\n' ) pdecl++;
}
else {putc(*pdecl, output); pdecl++;}
}
putc(';', output);
putc('\n', output);
}
/* Take in a type definition (type + symbol) and print out type only */
void
DumpType(s, f)
char *s;
FILE *f;
{
char *p, *end;
require(s!=NULL, "DumpType: invalid type string");
p = &s[strlen(s)-1]; /* start at end of string and work back */
/* scan back until valid variable character */
while ( !isalnum(*p) && *p!='_' ) --p;
/* scan back until beginning of variable */
while ( isalnum(*p) || *p=='_' ) --p;
if ( p<=s )
{
warnNoFL(eMsg1("invalid parameter/return value: '%s'",s));
return;
}
end = p; /* here is where we stop printing alnum */
p = s;
while ( p!=end ) {putc(*p, f); p++;} /* dump until just before variable */
while ( *p!='\0' ) /* dump rest w/o variable */
{
if ( !isalnum(*p) && *p!='_' ) putc(*p, f);
p++;
}
}
/* check to see if string e is a word in string s */
int
strmember(s, e)
char *s, *e;
{
register char *p;
require(s!=NULL&&e!=NULL, "strmember: NULL string");
if ( *e=='\0' ) return 1; /* empty string is always member */
do {
while ( *s!='\0' && !isalnum(*s) && *s!='_' )
++s;
p = e;
while ( *p!='\0' && *p==*s ) {p++; s++;}
if ( *p=='\0' ) {
if ( *s=='\0' ) return 1;
if ( !isalnum (*s) && *s != '_' ) return 1;
}
while ( isalnum(*s) || *s == '_' )
++s;
} while ( *s!='\0' );
return 0;
}
int
HasComma(s)
char *s;
{
while (*s!='\0')
if ( *s++ == ',' ) return 1;
return 0;
}
void
DumpRetValStruct(f,ret,i)
FILE *f;
char *ret;
int i;
{
fprintf(f, "\nstruct _rv%d {\n", i);
while ( *ret != '\0' )
{
while ( *ret==' ' || *ret=='\t' ) ret++; /* ignore white */
putc('\t', f);
while ( *ret!=',' && *ret!='\0' ) putc(*ret++, f);
if ( *ret == ',' ) {putc(';', f); putc('\n', f); ret++;}
}
fprintf(f, ";\n};\n");
}
/* given "s" yield s -- DESTRUCTIVE (we modify s if starts with " else return s) */
char *
StripQuotes(s)
char *s;
{
if ( *s == '"' )
{
s[ strlen(s)-1 ] = '\0'; /* remove last quote */
return( s+1 ); /* return address past initial quote */
}
return( s );
}