gen.c

来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 1,279 行 · 第 1/3 页

C
1,279
字号
		case PRED_OP :
			if ( t->down->token != Action )
			{
				define_labels_in_block(t->down);
			}
			break;
		case OPT :
			define_labels_in_block(t->down);
			break;
		case BLOCK :
			define_labels_in_block(t);
			break;
	}
}

/* dump action 's' to file 'output' starting at "local" tab 'tabs'
   Dump line information in front of action if GenLineInfo is set
   If file == -1 then GenLineInfo is ignored.
   The user may redefine the LineInfoFormatStr to his/her liking
   most compilers will like the default, however.

   June '93; changed so that empty lines are left alone so that
   line information is correct for the compiler/debuggers.
*/
void
#ifdef __USE_PROTOS
dumpAction( char *s, FILE *output, int tabs, int file, int line, int final_newline )
#else
dumpAction( s, output, tabs, file, line, final_newline )
char *s;
FILE *output;
int tabs;
int file;
int line;
int final_newline;
#endif
{
    int inDQuote, inSQuote;
    require(s!=NULL, 		"dumpAction: NULL action");
    require(output!=NULL,	eMsg1("dumpAction: output FILE is NULL for %s",s));

/*	if ( GenLineInfo && file != -1 )
	{
		fprintf(output, LineInfoFormatStr, line, FileStr[file]);
	}*/
    PastWhiteSpace( s );
	/* don't print a tab if first non-white char is a # (preprocessor command) */
	if ( *s!='#' ) {TAB;}
    inDQuote = inSQuote = 0;
    while ( *s != '\0' )
    {
        if ( *s == '\\' )
        {
            putc( *s++, output ); /* Avoid '"' Case */
            if ( *s == '\0' ) return;
            if ( *s == '\'' ) putc( *s++, output );
            if ( *s == '\"' ) putc( *s++, output );
        }
        if ( *s == '\'' )
        {
            if ( !inDQuote ) inSQuote = !inSQuote;
        }
        if ( *s == '"' )
        {
            if ( !inSQuote ) inDQuote = !inDQuote;
        }
        if ( *s == '\n' )
        {
            putc('\n', output);
			s++;
            while (*s == '\n') {
               putc('\n', output);
               s++;
            }
            PastWhiteSpace( s );
            if ( *s == '}' )
            {
                --tabs;
				TAB;
                putc( *s++, output );
                continue;
            }
            if ( *s == '\0' ) return;
			if ( *s != '#' )	/* #define, #endif etc.. start at col 1 */
            {
				TAB;
			}
        }
        if ( *s == '}' && !(inSQuote || inDQuote) )
        {
            --tabs;            /* Indent one fewer */
        }
        if ( *s == '{' && !(inSQuote || inDQuote) )
        {
            tabs++;            /* Indent one more */
        }
        putc( *s, output );
        s++;
    }
    if ( final_newline ) putc('\n', output);
}

char *
#ifdef __USE_PROTOS
find_predicate( AST *t )
#else
find_predicate( t )
AST *t;
#endif
{
	if ( t==NULL ) return NULL;
	if ( t->token == Action )
	{
		if ( t->right!=NULL && t->right->token==PRED_OP && t->right->down->token!=BLOCK )
		{
			return t->right->down->action;
		}
	}
	else if ( t->token == PRED_OP && t->down->token!=BLOCK )
	{
		return t->down->action;
	}
	return NULL;
}

/* Given a pointer to a tree pattern element (Token, BLOCK, etc...),
 * generate an expression that predicts when that path would match.
 */
set
#ifdef __USE_PROTOS
gen_prediction_expr( AST *alt, GLA *t )
#else
gen_prediction_expr( alt, t )
AST *alt;
GLA *t;
#endif
{
	char *sempred;
	set a, rs;
	int tok, first=1, num_on_line=0;
	require(alt==NULL||alt->token==ALT,
			"gen_prediction_expr: AST node is invalid");

	a = Lookahead(t);
	rs = set_dup(a);

	/* if this production is a guess block, then test return value of setjmp() */

    /* MR21 Problem reported by Peter Keller
       THM: Sor doesn't see predicate because of intervening action.
       
    */

    if (alt != NULL) {
        AST* cursor;
        for (cursor = alt->down;
             cursor != NULL && Action == cursor->token;
             cursor = cursor->right) {
			/* nothing */ 
        }
        if (cursor != NULL &&
            cursor->token == PRED_OP &&
            cursor->down->token == BLOCK) {
            fprintf(output," !_gv &&");
        }
    }

#if 0
                /* The old code which was replaced */

	if ( alt!=NULL && alt->down!=NULL && alt->down->token==PRED_OP &&
		 alt->down->down->token==BLOCK ) fprintf(output, " !_gv &&");

#endif

	/* handle end of input first */
	if ( set_el(end_of_input, a) )
	{
		fprintf(output, " _t==NULL");
		set_rm(end_of_input, a);
		if ( !set_nil(a) ) fprintf(output, " ||");
	}
	else if ( set_el(wild_card, a) )
	{
		fprintf(output, " _t!=NULL");
		if ( alt!=NULL ) {
			sempred = find_predicate(alt->down);
			if ( sempred!=NULL ) fprintf(output, " && (%s)", sempred);
		}
		set_free(a);
		return rs;
	}
	else
	{
		fprintf(output, " _t!=NULL");
		if ( !set_nil(a) ) fprintf(output, " &&");
	}

	if ( set_nil(a) ) { set_free(a); return rs; }

	fprintf(output, " (");
	while ( !set_nil(a) )
	{
		tok = set_int(a);
		set_rm(tok, a);
		if ( first ) first = 0;
		else fprintf(output, "||");
		if ( num_on_line>=2 ) {num_on_line=0; fprintf(output,"\n"); TAB;}
		else num_on_line++;
		if ( tok==wild_card ) fprintf(output, "_t!=NULL");
		else if ( token_dict[tok]==0 )
		{
			if ( GenCPP )
				fprintf(output, "_t->type()==UNDEFINED_TOKEN");
			else
				fprintf(output, "_t->token==UNDEFINED_TOKEN");
		}
		else
		{
			if ( GenCPP )
				fprintf(output, "_t->type()==%s", token_dict[tok]);
			else
				fprintf(output, "_t->token==%s", token_dict[tok]);
		}
	}
	fprintf(output, ")");

	if ( alt!=NULL ) {
		sempred = find_predicate(alt->down);
		if ( sempred!=NULL ) fprintf(output, " && (%s)", sempred);
	}
	set_free(a);
	return rs;
}

/* Find all return types/parameters that require structs and def
 * all rules with ret types.
 */
void
#ifdef __USE_PROTOS
GenRulePrototypes( FILE *f, int tabs )
#else
GenRulePrototypes( f, tabs )
FILE *f;
int tabs;
#endif
{
	AST *p;
	SymEntry *s;

	for (p=rules; p!=NULL; p=p->right)
	{
		int i;
		s = (SymEntry *) hash_get(symbols, p->text);
		require(s!=NULL, "GenRulePrototypes: sym tab broken");

		for (i=1; i<=tabs; i++) fprintf(f, "\t");
		GenRulePrototype(f, p, s, 1);
	}
}

void
#ifdef __USE_PROTOS
GenRulePrototype(FILE *f, AST *p, SymEntry *s, int decl_not_def)
#else
GenRulePrototype(f, p, s, decl_not_def)
FILE *f;
SymEntry *s;
AST *p;
int decl_not_def;
#endif
{
	require(s!=NULL&&s->definition!=NULL, "GenRulePrototype: no def for rule");

	if ( GenCPP )
	{
		if ( s->rt != NULL )
			DumpType(s->rt, f, FileStr[s->definition->file], s->definition->line);
		else fprintf(f, "void");
		if ( decl_not_def )
			fprintf(f, " %s(SORASTBase **_root%s",
					p->text,
					transform?", SORASTBase **_result":"");
		else
			fprintf(f, " %s::%s(SORASTBase **_root%s",
					CurClassName,
					p->text,
					transform?", SORASTBase **_result":"");
		if ( s->args != NULL ) fprintf(f, ",%s", s->args);
		fprintf(f, ")");
		if ( decl_not_def ) fprintf(f, ";");
		fprintf(f, "\n");
		return;
	}

	if ( decl_not_def ) fprintf(f, "extern ");
	if ( GenAnsiProtos && GenKRProtos ) fprintf(f, "\n#ifdef __USE_PROTOS\n");
	if ( GenAnsiProtos )
	{
		if ( s->rt != NULL )
			DumpType(s->rt, f, FileStr[s->definition->file], s->definition->line);
		else fprintf(f, "void");
		fprintf(f, " %s%s(STreeParser *_parser, SORAST **_root%s",
				Prefix,
				p->text,
				transform?", SORAST **_result":"");
		if ( s->args != NULL ) fprintf(f, ",%s", s->args);
		fprintf(f, ")");
		if ( decl_not_def ) fprintf(f, ";");
		fprintf(f, "\n");
	}
	if ( GenAnsiProtos && GenKRProtos ) fprintf(f, "#else\n");
	if ( GenKRProtos )
	{
		if ( s->rt != NULL )
			DumpType(s->rt, f, FileStr[s->definition->file], s->definition->line);
		else fprintf(f, "void");
		if ( decl_not_def) fprintf(f, " %s%s();\n", Prefix, p->text);
		else
		{
			fprintf(f, " %s%s(_parser, _root%s",
					Prefix, p->text,transform?", _result":"");
			if ( s->args!=NULL ) fprintf(f, ",");
			DumpListOfParmNames(s->args, f);
			fprintf(f, ")\n");
			fprintf(f, "STreeParser *_parser;\n");
			fprintf(f, "SORAST **_root%s;\n", transform?", **_result":"");
			DumpOldStyleParms(s->args, f);
		}
	}
	if ( GenAnsiProtos && GenKRProtos ) fprintf(f, "#endif\n");
}

/*
 * For each referenced token, generate a #define in a file defined in
 * 'def_token_file'.
 */
void
#ifdef __USE_PROTOS
gen_tokens_file( void )
#else
gen_tokens_file( )
#endif
{
	FILE *f;
	ListNode *p;

	if ( def_token_file==NULL ) return;

	f = fopen(def_token_file, "w");
	if ( f==NULL )
	{
		errNoFL(eMsg1("cannot write token definition file %s", def_token_file));
		return;
	}
#ifdef SPECIAL_FOPEN
       special_fopen_actions(def_token_file);
#endif

	gen_info_hdr(f);
	fprintf(f, "\n");
	for (p = token_list->next; p!=NULL; p=p->next)
	{
		SymEntry *t = (SymEntry *) p->elem;
		fprintf(f, "#define %s %d\n", t->str, t->token_type);
	}
	fclose(f);
}

AST *
#ifdef __USE_PROTOS
first_guess_block(AST *q)
#else
first_guess_block(q)
AST *q;
#endif
{
	require(q!=NULL&&q->token==ALT, "first_guess_block: non-ALT ptr");

	if ( q->down!=NULL )
	{
		if ( (q->down->token==PRED_OP && q->down->down!=NULL &&
			  q->down->down->token==BLOCK) )
		{
			return q->down;
		}
		else if (q->down->token==Action && q->down->right!=NULL &&
			  q->down->right->token==PRED_OP && q->down->right->down!=NULL &&
			  q->down->right->down->token==BLOCK)
		{
			return q->down->right;
		}
		else return NULL;
	}
	return NULL;
}

void
#ifdef __USE_PROTOS
code_for_guess_block( AST *t, int *guess_block_in_prev_alt )
#else
code_for_guess_block( t, guess_block_in_prev_alt )
AST *t;
int *guess_block_in_prev_alt;
#endif
{
	if ( found_guess_block )
	{
		/* if previous alt had a guess block, check to turn it off */
		if ( *guess_block_in_prev_alt )
		{
			TAB;
			if ( GenCPP ) fprintf(output, "if ( guessing ) _GUESS_DONE;\n");
			else fprintf(output, "if ( _parser->guessing ) _GUESS_DONE;\n");
		}
		/* if current alt has a guess block... */
		if ( first_guess_block(t)!=NULL )
		{
			TAB;
			fprintf(output, "_GUESS;\n");
			*guess_block_in_prev_alt = 1;
		}
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?