gen.c

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

C
1,279
字号

	/* Error if (...)? with only one alt */
	for (u = q->down; u!=NULL; u=u->right ) {num_alts++;}
	g = first_guess_block(q->down);
	if ( num_alts==1 && g!=NULL )
	{
		warnFL("(...)? predicate in block with one alternative; will generate bad code",
			   FileStr[g->file], g->line);
	}

	t = t->down;	/* move down to first alt */
	while ( t!=NULL && t->token == ALT )
	{
		require(start_state!=NULL, "gen_block: invalid GLA for block");
		if ( t!=q->down ) {
			TAB;
			fprintf(output, "else {\n");
			need_right_curly++;
		}
		code_for_guess_block(t, &guess_block_in_prev_alt);
		TAB;
		fprintf(output, "if (");
		/* To prevent/detect infinite recursion, ensure 'visited' flag is set
		 * on node starting this alt
		 */
		start_state->visited = 1;
		start_state->lookahead = gen_prediction_expr(t, start_state->p1);
		start_state->visited = 0;
		fprintf(output, " ) {\n");
		tabs++;
		gen_alt(t);
		tabs--; TAB;
		fprintf(output, "}\n");
		t = t->right;					/* move to next alt in AST */
		start_state = start_state->p2;	/* move to next alt in GLA */
	}

	switch ( block_type ) {
	case OPT :
	case CLOSURE :
		follow = q->start_state->p2;
		break;
	case POS_CLOSURE :
		follow = q->start_state->next;
	}

	if ( block_type == OPT || block_type == CLOSURE || block_type == POS_CLOSURE )
	{
		TAB;
		fprintf(output, "else {\n");
		need_right_curly++;
		TAB;
		fprintf(output, "if (");
		/* what follows the block? */
		q->start_state->visited = 1;
		q->start_state->lookahead = gen_prediction_expr(NULL, follow);
		q->start_state->visited = 0;
		fprintf(output, " ) {\n");
		if ( block_type != OPT )
		{
			tabs++; TAB;
			fprintf(output, "_done = 1;\n");
			tabs--;
		}
		TAB;
		fprintf(output, "}\n");
	}

	/* Generate error clause */
	TAB;
	fprintf(output, "else {\n");
	/* generate the _GUESS_FAIL even if no (..)? found because calling
	 * routine may be using STreeTest()
	 */
	tabs++;
	TAB;
	if ( GenCPP ) fprintf(output, "if ( guessing ) _GUESS_FAIL;\n");
	else fprintf(output, "if ( _parser->guessing ) _GUESS_FAIL;\n");
	TAB;
	if ( GenCPP ) fprintf(output, "no_viable_alt(\"%s\", _t);\n", current_rule);
	else fprintf(output, "no_viable_alt(_parser, \"%s\", _t);\n", current_rule);
	tabs--;
	TAB;
	fprintf(output, "}\n");
	if ( transform ) { TAB; fprintf(output, " _tresult = _r;\n"); }

	for (;need_right_curly>0; need_right_curly--)
	{
		TAB;
		fprintf(output, "}\n");
	}

	switch ( block_type ) {
	case BLOCK :
		break;
	case CLOSURE :
		tabs--;
		TAB; fprintf(output, "}\n");
/* 		if ( transform ) fprintf(output, " _tresult = _r;\n"); */
		TAB; fprintf(output, "}\n");
		break;
	case POS_CLOSURE :
		tabs--;
		TAB;
		fprintf(output, "} while ( !_done );\n");
/* 		if ( transform ) { TAB; fprintf(output, " _tresult = _r;\n"); } */
		TAB;
		fprintf(output, "}\n");
		break;
	case PRED_OP :
		TAB;
		fprintf(output, "_RESTORE;\n");
/* 		if ( transform ) { TAB; fprintf(output, " _tresult = _r;\n"); } */
		TAB; fprintf(output, "}\n");
		TAB; fprintf(output, "_GUESS_DONE;\n");
		break;
	}

	test_block_consistency(q, block_type);
}

void
#ifdef __USE_PROTOS
gen_alt( AST *t )
#else
gen_alt( t )
AST *t;
#endif
{
	require(t!=NULL && t->token==ALT, "gen_alt: invalid alt");

	t = t->down;
	if ( t==NULL ) return;
	if ( t->token==Action ) t->init_action = 1;
	gen_tree_pattern(t);

	/* find last element of alternative to see if it's a simple token */
	while ( t->right!=NULL ) { t = t->right; }
	if ( t->down==NULL && (t->token == Token || t->token == WILD) )
		{ TAB; go_right(1); }
}

void
#ifdef __USE_PROTOS
gen_tree_pattern( AST *t )
#else
gen_tree_pattern( t )
AST *t;
#endif
{
	while ( t != NULL )
	{
		/* could be root of a tree, check it */
		if ( t->down != NULL && (t->token==Token||t->token==WILD) ) {
			TAB;
			fprintf(output, "{_SAVE; TREE_CONSTR_PTRS;\n");
		}
		gen_element(t);
		if ( t->down != NULL ) {
			if ( t->token == Token || t->token==WILD )
			{
				gen_tree_pattern(t->down);	/* only token/wildcard can be root of tree */
				TAB;
				fprintf(output, "_RESTORE;");
				if ( transform ) fprintf(output, " _tresult = _r;");
				fprintf(output, "\n");
				TAB; fprintf(output, "}\n");
				/* link in result of #(...) */
				if ( transform && !whichRule->no_copy ) {
					TAB; fprintf(output, "_mkchild(&_r,&_s,&_e,_tresult);\n");
				}
				TAB; go_right(1);
			}
		}
		t = t->right;
	}
}

void
#ifdef __USE_PROTOS
gen_element( AST *t )
#else
gen_element( t )
AST *t;
#endif
{
	char *res;
	require(t!=NULL, "gen_element: NULL tree pointer");

	switch ( t->token )
	{
	    case Token :
			TAB;
			if ( t->upper_range!=0 )
				fprintf(output, "_MATCHRANGE(%s,%s);",
						t->text, token_dict[t->upper_range]);
			else fprintf(output, "_MATCH(%s);", t->text);
			fprintf(output, "\n");
			/* Make copy of token if transform && (copy or (labeled&&!copy)) */
			if ( transform && (t->label[0]!='\0'||!t->no_copy) ) {
				TAB;
				if ( GenCPP )
					fprintf(output, "_tresult=_t->shallowCopy();\n");
				else
					fprintf(output, "_tresult=ast_dup_node(_t);\n");
			}
			if ( transform && !t->no_copy ) {
				if ( t->is_root )
					fprintf(output, " _mkroot(&_r,&_s,&_e,_tresult);\n");
				else
					fprintf(output, " _mkchild(&_r,&_s,&_e,_tresult);\n");
			}
			/* Do Label if any */
			if ( transform  ) {		/* label is output, label_in is input */
				if ( t->label[0]!='\0' )
				{
					TAB;
					fprintf(output,
							"%s=(SORAST *)_tresult; %s_in=(SORAST *)_t;\n",
							t->label,t->label);
				}
			} else {
				if ( t->label[0]!='\0' )
					{ TAB; fprintf(output, "%s=(SORAST *)_t;\n", t->label); }
			}
			/* Move tree parser pointer */
			if ( t->down != NULL ) { TAB; go_down(1); }
			else if ( t->right != NULL ) { TAB; go_right(1); }
			break;
		case WILD :
			TAB;
			fprintf(output, "_WILDCARD;");
			/* Make copy of token or tree if transform */
			if ( transform ) {
				TAB;
				if ( GenCPP )
					fprintf(output, "_tresult=_t->deepCopy();");
				else
					fprintf(output, "_tresult=ast_dup(_t);");
				/* wildcard can't be root, must be child */
				if ( !t->no_copy ) {
					if ( t->is_root )
						fprintf(output, " _mkroot(&_r,&_s,&_e,_tresult);");
					else
						fprintf(output, " _mkchild(&_r,&_s,&_e,_tresult);");
				}
			}
			fprintf(output, "\n");
			if ( transform  ) {
				if ( t->label[0]!='\0' )
				{
					TAB;
					fprintf(output,
							"%s=(SORAST *)_tresult; %s_in=(SORAST *)_t;\n",
							t->label,t->label);
				}
			} else {
				if ( t->label[0]!='\0' )
					{ TAB; fprintf(output, "%s=(SORAST *)_t;\n", t->label); }
			}
			if ( t->down != NULL ) { TAB; go_down(1); }
			else if ( t->right != NULL ) { TAB; go_right(1); }
			break;
		case NonTerm :
			TAB;
			/* For nontransform mode, do labels first */
			if (t->label[0]!='\0')
				fprintf(output, "%s=(SORAST *)_t; ", t->label);
			if ( t->out ) {
				if ( t->in ) fprintf(output, "%s=", t->down->right->text);
				else fprintf(output, "%s=", t->down->text);
			}
			fprintf(output, "%s%s", Prefix, t->text);
			if ( transform ) res = ", &_tresult"; else res = "";
			if ( GenCPP ) {
				if ( t->in ) fprintf(output, "(&_t%s, %s);",
									 res, t->down->text);
				else fprintf(output, "(&_t%s);", res);
			}
			else {
				if ( t->in ) fprintf(output, "(_parser, &_t%s, %s);",
									 res, t->down->text);
				else fprintf(output, "(_parser, &_t%s);", res);
			}
			fprintf(output, "\n");
			if (transform && t->label[0]!='\0')
				{
					TAB;
					fprintf(output, "%s=(SORAST *)_tresult;\n", t->label);
				}
			/* Link in result of rule */
			if ( transform&&!t->no_copy ) {
				TAB;
				fprintf(output, "_mkchild(&_r,&_s,&_e,_tresult);\n");
			}
			break;
		case Action :
			if ( !t->init_action && found_guess_block ) {
				TAB;
				if ( GenCPP ) fprintf(output, "if ( !guessing ) {\n");
				else fprintf(output, "if ( !_parser->guessing ) {\n");
			}
			dumpAction(t->action, output, tabs, 0, 0, 1);
			if ( !t->init_action && found_guess_block ) {TAB; fprintf(output, "}\n");}
			break;
		case CLOSURE :
			gen_block(t->down, CLOSURE);
			break;
		case POS_CLOSURE :
			gen_block(t->down, POS_CLOSURE);
			break;
		case OPT :
			gen_block(t->down, OPT);
			break;
		case BLOCK :
			gen_block(t, BLOCK);
			break;
		case PRED_OP :
			require(t->up!=NULL, "define_labels_in_element: GLA is broken");
			if ( t->up->down==t ) {
				if ( t->down->token == BLOCK ) gen_block(t->down, PRED_OP);
			}
			else if ( t->up->down->token==Action && t->up->down->right==t ) {
				if ( t->down->token == BLOCK ) gen_block(t->down, PRED_OP);
			}
			else {
				warnFL("predicate not at beginning of alternative; ignored",
					   FileStr[t->file], t->line);
			}
			break;
		default :
			fatal(eMsgd("invalid elemental node type: %d", t->token));
	}
}

/* walk the block of a rule and define all labels to be "SORAST *label_i" */
void
#ifdef __USE_PROTOS
define_labels_in_block( AST *t )
#else
define_labels_in_block( t )
AST *t;
#endif
{
	require(t!=NULL, "define_labels_in_block: NULL tree pointer");
	require(t->token==BLOCK, "define_labels_in_block: invalid block");
	t = t->down;
	while ( t!=NULL )
	{
		define_labels_in_alt(t);
		t = t->right;
	}
}

void
#ifdef __USE_PROTOS
define_labels_in_alt( AST *t )
#else
define_labels_in_alt( t )
AST *t;
#endif
{
	require(t!=NULL, "define_labels_in_alt: NULL tree pointer");
	require(t->token==ALT, "gen_alt: invalid alt");

	define_labels_in_tree(t->down);
}

void
#ifdef __USE_PROTOS
define_labels_in_tree( AST *t )
#else
define_labels_in_tree( t )
AST *t;
#endif
{
	while ( t != NULL )
	{
		define_labels_in_element(t);
		/* could be root of a tree, check it */
		if ( t->down != NULL ) {
			if ( t->token == Token || t->token==WILD )
			{
				define_labels_in_tree(t->down);
			}
		}
		t = t->right;
	}
}

void
#ifdef __USE_PROTOS
define_labels_in_element( AST *t )
#else
define_labels_in_element( t )
AST *t;
#endif
{
	require(t!=NULL, "define_labels_in_element: NULL tree pointer");
	switch ( t->token )
	{
	    case Token :
		case WILD :
		case NonTerm :
			if ( t->label[0]!='\0' ) {
				SymEntry *s;
				s = (SymEntry *) hash_get(symbols, t->label);
				require(s!=NULL, "define_labels_in_element: sym tab broken");
				if ( s->token==LABEL && !s->defined ) {
					s->defined = 1;
					TAB;
					fprintf(output, "SORAST *%s=NULL", t->label);
					if ( transform ) fprintf(output, ",*%s_in=NULL", t->label);
					fprintf(output, ";\n");
					/* track which ones we define so that we can undefine
					 * them for the next rule
					 */
					list_add(&labels_for_func, (void *)s);
				}
			}
			break;
		case Action :
			break;
		case CLOSURE :
		case POS_CLOSURE :
			define_labels_in_block(t->down);
			break;

⌨️ 快捷键说明

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