gen.c
来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 1,279 行 · 第 1/3 页
C
1,279 行
/* Code generator for SORCERER
*
* Translate sorcerer rules (in intermediate trees) to C / C++
*
* SOFTWARE RIGHTS
*
* We reserve no LEGAL rights to SORCERER -- SORCERER is in the public
* domain. An individual or company may do whatever they wish with
* source code distributed with SORCERER or the code generated by
* SORCERER, including the incorporation of SORCERER, or its output, into
* commerical software.
*
* We encourage users to develop software with SORCERER. However, we do
* ask that credit is given to us for developing SORCERER. 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 SORCERER and have developed a nice tool with the
* output, please mention that you developed it using SORCERER. 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.
*
* SORCERER 1.00B
* Terence Parr
* AHPCRC, University of Minnesota
* 1992-2001
*
* The latest (October 1994) transformation mode works as follows:
*
* o All elements set _tresult, a function-scoped var
* o All rules are passed the address of a SORAST ptr
* called '_result' that is set at the end of each
* alternative. The return tree is guaranteed to
* be complete only at this point.
* o Each alt AND #(...) tree have their own root (_r),
* sibling (_s) and tail/end pointers (_e). #(...) trees
* set _tresult just before exiting their scope. Hence,
* #(...) are just like elements--they set _tresult.
* o At the end of a rule, *_result is set to _tresult.
* o After each root node ref, a _mkroot(&_r,&_s,&_e,_tresult)
* is generated to set the pointers.
* o After each child node ref, a _mkchild(&_r,&_s,&_e,_tresult)
* is generated to set the pointers.
* o After each rule ref, a _mkroot(&_r,&_s,&_e,_tresult)
* is generated to set the pointers.
* o After each #(...) ref, a _mkroot(&_r,&_s,&_e,_tresult)
* is generated to set the pointers.
* o token references: gen a _tresult=ast_dup(_t);
* (only if labeled, however).
* o rules or alts with nocopy set don't construct trees.
*/
#include "pcctscfg.h"
#include "stdpccts.h"
#include "sym.h"
#include "proto.h"
static outfile = -1;
static char *current_rule;
static ListNode *labels_for_func = NULL;
static AST *whichRule;
static int tabs=0;
#define TAB {int i=1; for (;i<=tabs;i++) {putc('\t', output);}}
#define PastWhiteSpace(s) while (*(s) == ' ' || *(s) == '\t') {s++;}
static void
#ifdef __USE_PROTOS
go_down(int nl)
#else
go_down(nl)
int nl;
#endif
{
fprintf(output, "_DOWN;");
if ( nl ) fprintf(output, "\n");
}
static void
#ifdef __USE_PROTOS
go_right(int nl)
#else
go_right(nl)
int nl;
#endif
{
fprintf(output, "_RIGHT;");
if ( nl ) fprintf(output, "\n");
}
void
#ifdef __USE_PROTOS
gen_info_hdr( FILE *f )
#else
gen_info_hdr( f )
FILE *f;
#endif
{
fprintf(f, "/*\n");
fprintf(f, " * S O R C E R E R T r a n s l a t i o n H e a d e r\n");
fprintf(f, " *\n");
fprintf(f, " * SORCERER Developed by Terence Parr, Aaron Sawdey, & Gary Funck\n");
fprintf(f, " * Parr Research Corporation, Intrepid Technology, University of Minnesota\n");
fprintf(f, " * 1992-1994\n");
fprintf(f, " * SORCERER Version %s\n", VersionText);
fprintf(f, " */\n");
}
void
#ifdef __USE_PROTOS
gen_hdr_CPP( void )
#else
gen_hdr_CPP( )
#endif
{
char CPPParser_h_Name[MaxFileName+1];
gen_info_hdr(output);
fprintf(output, "#define SORCERER_VERSION\t%s\n", VersionNumber);
if ( transform ) fprintf(output, "#define SORCERER_TRANSFORM\n");
else fprintf(output, "#define SORCERER_NONTRANSFORM\n");
/* Don't gen header action here as it's in the ClassName.h
if ( header_action!=NULL )
dumpAction(header_action, output, 0, -1, 0, 1); */
fprintf(output, "#include \"%s\"\n", STPARSER_H);
if ( UserDefdTokens ) fprintf(output, "#include \"%s\"\n", tokdefs_file);
strcpy(CPPParser_h_Name, CurClassName);
strcat(CPPParser_h_Name, ".h");
fprintf(output, "#include \"%s\"\n", CPPParser_h_Name);
}
void
#ifdef __USE_PROTOS
gen_hdr_C( void )
#else
gen_hdr_C( )
#endif
{
if ( Inline ) return;
gen_info_hdr(output);
fprintf(output, "#define SORCERER_VERSION\t%s\n", VersionNumber);
if ( transform ) fprintf(output, "#define SORCERER_TRANSFORM\n");
else fprintf(output, "#define SORCERER_NONTRANSFORM\n");
fprintf(output, "#include \"pcctscfg.h\"\n");
fprintf(output, "#include <stdio.h>\n");
fprintf(output, "#include <setjmp.h>\n");
if ( Prefix[0]!='\0' )
{
fprintf(output, "/* rename error routines; used in macros, must use /lib/cpp */\n");
fprintf(output, "#define mismatched_token %smismatched_token\n", Prefix);
fprintf(output, "#define mismatched_range %smismatched_range\n", Prefix);
fprintf(output, "#define missing_wildcard %smissing_wildcard\n", Prefix);
fprintf(output, "#define no_viable_alt %sno_viable_alt\n", Prefix);
fprintf(output, "#define sorcerer_panic %ssorcerer_panic\n", Prefix);
}
if ( header_action!=NULL )
dumpAction(header_action, output, 0, -1, 0, 1);
/* make a #define for the STreeParser containing the ref vars */
if ( AllRefVars!=NULL )
{
ListNode *p;
fprintf(output, "#define _REFVARS \\\n");
for (p = AllRefVars->next; p!=NULL; p=p->next)
{
RefVarRec *r = (RefVarRec *)p->elem;
fprintf(output, "\t%s; \\\n", r->decl);
}
fprintf(output, "\n\n");
}
fprintf(output, "#include \"sorcerer.h\"\n");
if ( UserDefdTokens ) fprintf(output, "#include \"%s\"\n", tokdefs_file);
if ( GenProtoFile!=NULL ) fprintf(output, "#include \"%s\"\n", GenProtoFile);
else GenRulePrototypes( output, 0 );
if ( transform ) fprintf(output, "#include \"sorcerer.c\"\n");
}
void
#ifdef __USE_PROTOS
gen_hdr( void )
#else
gen_hdr( )
#endif
{
if ( GenCPP ) gen_hdr_CPP();
else gen_hdr_C();
}
void
#ifdef __USE_PROTOS
gen_hdr1( void )
#else
gen_hdr1( )
#endif
{
if ( !Inline )
{
gen_hdr();
}
if ( GenCPP )
{
/* fprintf(output, "#include \"%s\"\n", STREESUPPORT_C); */
}
else {
/* make a func to init the ref vars with inits */
fprintf(output, "\nvoid\n");
fprintf(output, "#ifdef __USE_PROTOS\n");
fprintf(output, "_refvar_inits(STreeParser *p)\n");
fprintf(output, "#else\n");
fprintf(output, "_refvar_inits(p)\n");
fprintf(output, "STreeParser *p;\n");
fprintf(output, "#endif\n");
fprintf(output, "{\n");
if ( AllRefVars!=NULL )
{
ListNode *p;
for (p = AllRefVars->next; p!=NULL; p=p->next)
{
RefVarRec *r = (RefVarRec *)p->elem;
if ( r->init[0]!='\0' )
fprintf(output, "\tp->%s=%s;\n", r->var, r->init);
}
}
fprintf(output, "}\n\n");
}
if ( before_actions != NULL )
{
ListNode *p;
for (p = before_actions->next; p!=NULL; p=p->next)
dumpAction( (char *)p->elem, output, 0, -1, 0, 1);
}
}
void
#ifdef __USE_PROTOS
gen( AST *t )
#else
gen( t )
AST *t;
#endif
{
if ( t==NULL ) return;
while ( t!=NULL && t->token == NonTerm )
{
if ( labels_for_func != NULL )
{
/* reset 'defined' flag for previously defined labels and free list */
ListNode *p, *q;
for (p = labels_for_func->next; p!=NULL; p=q)
{
SymEntry *s = (SymEntry *)p->elem;
s->defined = 0;
q = p->next;
free(p);
}
free(labels_for_func);
labels_for_func = NULL;
}
gen_rule(t);
t = t->right;
}
if ( after_actions != NULL )
{
ListNode *p;
for (p = after_actions->next; p!=NULL; p=p->next)
dumpAction( (char *)p->elem, output, 0, -1, 0, 1);
}
fclose(output);
}
void
#ifdef __USE_PROTOS
gen_rule( AST *t )
#else
gen_rule( t )
AST *t;
#endif
{
SymEntry *s;
if ( t==NULL ) return;
whichRule=t;
s = (SymEntry *) hash_get(symbols, t->text);
require(s!=NULL, "gen_rule: sym tab broken");
if ( t->file != outfile ) /* open new output file if need to */
{
if (strcmp(FileStr[t->file], "stdin")==0) output = stdout;
else {
if ( output != NULL ) fclose( output );
output = fopen(OutMetaName(outname(FileStr[t->file])), "w");
require(output != NULL, "gen_rule: can't open output file");
#ifdef SPECIAL_FOPEN
special_fopen_actions(OutMetaName(outname(FileStr[t->file])));
#endif
}
if ( outfile == -1 ) gen_hdr1();
else gen_hdr();
outfile = t->file;
}
fprintf(output, "\n");
current_rule = t->text;
GenRulePrototype(output, t, s, 0);
/* What locals do we need? */
tabs=1;
if ( GenCPP ) fprintf(output, "{\n\tSORASTBase *_t = *_root;\n");
else fprintf(output, "{\n\tSORAST *_t = *_root;\n");
if ( s->rt!=NULL ) fprintf(output, "\t%s;\n", s->rt);
if ( transform )
{
if ( GenCPP ) fprintf(output, "\tSORASTBase *_tresult=NULL;\n");
else fprintf(output, "\tSORAST *_tresult=NULL;\n");
fprintf(output, "\tTREE_CONSTR_PTRS;\n");
}
if ( t->refvars!=NULL )
{
ListNode *p;
for (p = t->refvars->next; p!=NULL; p=p->next)
{
RefVarRec *r = (RefVarRec *)p->elem;
if ( !r->global ) {
TAB;
dump_prefixed_decl("_save_", r->decl, output);
if ( GenCPP ) fprintf(output, "=%s;\n", r->var);
else fprintf(output, "=_parser->%s;\n", r->var);
}
}
}
define_labels_in_block(t->down);
if ( found_guess_block ) fprintf(output, "\t_GUESS_BLOCK;\n");
if ( transform ) fprintf(output, " *_result = NULL;\n");
gen_block(t->down, BLOCK);
TAB;
fprintf(output, "*_root = _t;\n");
/* reset any ref vars defined in this routine */
if ( t->refvars!=NULL )
{
ListNode *p;
for (p = t->refvars->next; p!=NULL; p=p->next)
{
RefVarRec *r = (RefVarRec *)p->elem;
if ( !r->global )
{
if ( GenCPP ) fprintf(output, "\t%s = _save_%s;\n", r->var, r->var);
else fprintf(output, "\t_parser->%s = _save_%s;\n", r->var, r->var);
}
}
}
/* set result of tree copying efforts if no ! on rule */
if ( transform&&!t->no_copy ) {
TAB;
/* The 'if' check in front of the *_result assignment ensures
* that if someone sets the result before here, don't mess with
* it. This assignment is the default.
*/
fprintf(output, "if ( (*_result) == NULL ) *_result = _r;\n");
}
/* send back and return value */
if ( s->rt!=NULL )
{
char *str = s->rt;
TAB;
fprintf(output, "return ");
DumpNextNameInDef(&str, output);
fprintf(output, ";\n");
}
tabs=0;
fprintf(output, "}\n");
}
/*
* The lookahead is stored in the 1st node of each alt of the block.
* The Lookahead of what follows (for CLOSURE and OPT) blocks, is stored
* in the node which branches over the enclosed, optional block.
*/
void
#ifdef __USE_PROTOS
gen_block( AST *q, int block_type )
#else
gen_block( q, block_type )
AST *q;
int block_type;
#endif
{
AST *t = q, *u, *g;
GLA *start_state, *follow=NULL;
int need_right_curly=0, guess_block_in_prev_alt=0, num_alts=0;
require(q!=NULL, "gen_block: NULL block");
require(q->start_state!=NULL, "gen_block: NULL start state");
start_state = t->start_state->p1;
require(start_state!=NULL, "gen_block: no GLA start state for AST block");
switch ( block_type ) {
case PRED_OP :
TAB;
fprintf(output, "{_SAVE; TREE_CONSTR_PTRS;\n");
break;
case CLOSURE :
TAB;
fprintf(output, "{int _done=0;\n");
TAB;
fprintf(output, "while ( !_done ) {\n");
tabs++;
break;
case POS_CLOSURE :
TAB;
fprintf(output, "{int _done=0;\n");
TAB;
fprintf(output, "do {\n");
tabs++;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?