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 + -
显示快捷键?