misc.c

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

C
1,865
字号
	}
	/* kill Cycle list */
	for (q = Cycles[k]->next; q != NULL; q=p)
	{
		p = q->next;
		set_free( ((Cycle *)q->elem)->cyclicDep );
		free((char *)q);
	}
	free( (char *)Cycles[k] );
	Cycles[k] = NULL;
}


			/* P r i n t i n g  S y n t a x  D i a g r a m s */

static void
#ifdef __USE_PROTOS
pBlk( Junction *q, int btype )
#else
pBlk( q, btype )
Junction *q;
int btype;
#endif
{
	int k,a;
	Junction *alt, *p;

	q->end->pvisited = TRUE;
	if ( btype == aLoopBegin )
	{
		require(q->p2!=NULL, "pBlk: invalid ()* block");
		PRINT(q->p1);
		alt = (Junction *)q->p2;
		PRINT(alt->p1);
		if ( PrintAnnotate )
		{
			printf(" /* Opt ");
			k = 1;
			while ( !set_nil(alt->fset[k]) )
			{
				s_fprT(stdout, alt->fset[k]);
				if ( k++ == CLL_k ) break;
				if ( !set_nil(alt->fset[k]) ) printf(", ");
			}
			printf(" */\n");
		}
		return;
	}
	for (a=1,alt=q; alt != NULL; alt= (Junction *) alt->p2, a++)
	{
		if ( alt->p1 != NULL ) PRINT(alt->p1);
		if ( PrintAnnotate )
		{
			printf( " /* [%d] ", alt->altnum);
			k = 1;
			while ( !set_nil(alt->fset[k]) )
			{
				s_fprT(stdout, alt->fset[k]);
				if ( k++ == CLL_k ) break;
				if ( !set_nil(alt->fset[k]) ) printf(", ");
			}
			if ( alt->p2 == NULL && btype == aOptBlk )
				printf( " (optional branch) */\n");
			else printf( " */\n");
		}

		/* ignore implied empty alt of Plus blocks */
		if ( alt->p2 != NULL && ((Junction *)alt->p2)->ignore ) break;

		if ( alt->p2 != NULL && !(((Junction *)alt->p2)->p2==NULL && btype == aOptBlk) )
		{
			if ( pLevel == 1 )
			{
				printf("\n");
				if ( a+1==pAlt1 || a+1==pAlt2 ) printf("=>");
				printf("\t");
			}
			else printf(" ");
			printf("|");
			if ( pLevel == 1 )
			{
				p = (Junction *) ((Junction *)alt->p2)->p1;
				while ( p!=NULL )
				{
					if ( p->ntype==nAction )
					{
						p=(Junction *)((ActionNode *)p)->next;
						continue;
					}
					if ( p->ntype!=nJunction )
					{
						break;
					}
					if ( p->jtype==EndBlk || p->jtype==EndRule )
					{
						p = NULL;
						break;
					}
					p = (Junction *)p->p1;
				}
				if ( p==NULL ) printf("\n\t");	/* Empty alt? */
			}
		}
	}
	q->end->pvisited = FALSE;
}

/* How to print out a junction */
void
#ifdef __USE_PROTOS
pJunc( Junction *q )
#else
pJunc( q )
Junction *q;
#endif
{
	int dum_k;
	int doing_rule;
	require(q!=NULL, "pJunc: NULL node");
	require(q->ntype==nJunction, "pJunc: not junction");
	
	if ( q->pvisited == TRUE ) return;
	q->pvisited = TRUE;
	switch ( q->jtype )
	{
		case aSubBlk :
			if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
			if ( q->end->p1 != NULL && ((Junction *)q->end->p1)->ntype==nJunction &&
				 ((Junction *)q->end->p1)->jtype == EndRule ) doing_rule = 1;
			else doing_rule = 0;
			pLevel++;
			if ( pLevel==1 )
			{
				if ( pAlt1==1 ) printf("=>");
				printf("\t");
			}
			else printf(" ");
			if ( doing_rule )
			{
				if ( pLevel==1 ) printf(" ");
				pBlk(q,q->jtype);
			}
			else {
				printf("(");
				if ( pLevel==1 ) printf(" ");
				pBlk(q,q->jtype);
				if ( pLevel>1 ) printf(" ");
				printf(")");
			}
			if ( q->guess ) printf("?");
			pLevel--;
			if ( PrintAnnotate ) freeBlkFsets(q);
			if ( q->end->p1 != NULL ) PRINT(q->end->p1);
			break;
		case aOptBlk :
			if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
			pLevel++;
			if ( pLevel==1 )
			{
				if ( pAlt1==1 ) printf("=>");
				printf("\t");
			}
			else printf(" ");
			printf("{");
			if ( pLevel==1 ) printf(" ");
			pBlk(q,q->jtype);
			if ( pLevel>1 ) printf(" ");
			else printf("\n\t");
			printf("}");
			pLevel--;
			if ( PrintAnnotate ) freeBlkFsets(q);
			if ( q->end->p1 != NULL ) PRINT(q->end->p1);
			break;
		case aLoopBegin :
			if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
			pLevel++;
			if ( pLevel==1 )
			{
				if ( pAlt1==1 ) printf("=>");
				printf("\t");
			}
			else printf(" ");
			printf("(");
			if ( pLevel==1 ) printf(" ");
			pBlk(q,q->jtype);
			if ( pLevel>1 ) printf(" ");
			else printf("\n\t");
			printf(")*");
			pLevel--;
			if ( PrintAnnotate ) freeBlkFsets(q);
			if ( q->end->p1 != NULL ) PRINT(q->end->p1);
			break;
		case aLoopBlk :
			if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
			pBlk(q,q->jtype);
			if ( PrintAnnotate ) freeBlkFsets(q);
			break;
		case aPlusBlk :
			if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k);
			pLevel++;
			if ( pLevel==1 )
			{
				if ( pAlt1==1 ) printf("=>");
				printf("\t");
			}
			else printf(" ");
			printf("(");
			if ( pLevel==1 ) printf(" ");
			pBlk(q,q->jtype);
			if ( pLevel>1 ) printf(" ");
			printf(")+");
			pLevel--;
			if ( PrintAnnotate ) freeBlkFsets(q);
			if ( q->end->p1 != NULL ) PRINT(q->end->p1);
			break;
		case EndBlk :
			break;
		case RuleBlk :
			printf( "\n%s :\n", q->rname);
			PRINT(q->p1);
			if ( q->p2 != NULL ) PRINT(q->p2);
			break;
		case Generic :
			if ( q->p1 != NULL ) PRINT(q->p1);
			q->pvisited = FALSE;
			if ( q->p2 != NULL ) PRINT(q->p2);
			break;
		case EndRule :
			printf( "\n\t;\n");
			break;
	}
	q->pvisited = FALSE;
}

/* How to print out a rule reference node */
void
#ifdef __USE_PROTOS
pRuleRef( RuleRefNode *p )
#else
pRuleRef( p )
RuleRefNode *p;
#endif
{
	require(p!=NULL, "pRuleRef: NULL node");
	require(p->ntype==nRuleRef, "pRuleRef: not rule ref node");
	
	printf( " %s", p->text);
	PRINT(p->next);
}

/* How to print out a terminal node */
void
#ifdef __USE_PROTOS
pToken( TokNode *p )
#else
pToken( p )
TokNode *p;
#endif
{
	require(p!=NULL, "pToken: NULL node");
	require(p->ntype==nToken, "pToken: not token node");

	if ( p->wild_card ) printf(" .");
	printf( " %s", TerminalString(p->token));
	PRINT(p->next);
}

/* How to print out a terminal node */
void
#ifdef __USE_PROTOS
pAction( ActionNode *p )
#else
pAction( p )
ActionNode *p;
#endif
{
	require(p!=NULL, "pAction: NULL node");
	require(p->ntype==nAction, "pAction: not action node");
	
	PRINT(p->next);
}

					/* F i l l  F o l l o w  L i s t s */

/*
 * Search all rules for all rule reference nodes, q to rule, r.
 * Add q->next to follow list dangling off of rule r.
 * i.e.
 *
 *		r: -o-R-o-->o--> Ptr to node following rule r in another rule
 *					|
 *					o--> Ptr to node following another reference to r.
 *
 * This is the data structure employed to avoid FOLLOW set computation.  We
 * simply compute the FIRST (reach) of the EndRule Node which follows the
 * list found at the end of all rules which are referenced elsewhere.  Rules
 * not invoked by other rules have no follow list (r->end->p1==NULL).
 * Generally, only start symbols are not invoked by another rule.
 *
 * Note that this mechanism also gives a free cross-reference mechanism.
 *
 * The entire syntax diagram is layed out like this:
 *
 * SynDiag
 *	|
 *	v
 *	o-->R1--o
 *	|
 *	o-->R2--o
 *	|
 *	...
 *	|
 *	o-->Rn--o
 *
 */
void
#ifdef __USE_PROTOS
FoLink( Node *p )
#else
FoLink( p )
Node *p;
#endif
{
	RuleEntry *q;
	Junction *j = (Junction *) p;
	RuleRefNode *r = (RuleRefNode *) p;

	if ( p==NULL ) return;
	require(p->ntype>=1 && p->ntype<=NumNodeTypes,
			eMsgd("FoLink: invalid diagram node: ntype==%d",p->ntype));
	switch ( p->ntype )
	{
		case nJunction :
			if ( j->fvisited ) return;
			if ( j->jtype == EndRule ) return;
			j->fvisited = TRUE;
			FoLink( j->p1 );
			FoLink( j->p2 );
/* MR14 */
/* MR14 */  /* Need to determine whether the guess block is an         */
/* MR14 */  /* of the form (alpha)? beta before follow sets are        */
/* MR14 */  /* computed.  This is necessary to solve problem           */
/* MR14 */  /* of doing follow on the alpha of an (alpha)? beta block. */
/* MR14 */
/* MR14 */  /* This is performed by analysis_point as a side-effect.   */
/* MR14 */
/* MR14 */
/* MR14 */  if (j->jtype == aSubBlk && j->guess) {
/* MR14 */    Junction *ignore;
/* MR14 */    ignore=analysis_point(j);
/* MR14 */  }
/* MR14 */
			return;
		case nRuleRef :
			if ( r->linked ) return;
			q = (RuleEntry *) hash_get(Rname, r->text);
			if ( q == NULL )
			{
				warnFL( eMsg1("rule %s not defined",r->text), FileStr[r->file], r->line );
			}
			else
			{
				if ( r->parms!=NULL && RulePtr[q->rulenum]->pdecl==NULL )
				{
					warnFL( eMsg1("rule %s accepts no parameter(s)", r->text),
							FileStr[r->file], r->line );
				}
				if ( r->parms==NULL && RulePtr[q->rulenum]->pdecl!=NULL )
				{
					warnFL( eMsg1("rule %s requires parameter(s)", r->text),
							FileStr[r->file], r->line );
				}
				if ( r->assign!=NULL && RulePtr[q->rulenum]->ret==NULL )
				{
					warnFL( eMsg1("rule %s yields no return value(s)", r->text),
							FileStr[r->file], r->line );
				}
				if ( r->assign==NULL && RulePtr[q->rulenum]->ret!=NULL )
				{
					warnFL( eMsg1("rule %s returns a value(s)", r->text),
							FileStr[r->file], r->line );
				}
				if ( !r->linked )
				{
					addFoLink(	r->next, r->rname, RulePtr[q->rulenum] );
					r->linked = TRUE;
				}
			}
			FoLink( r->next );
			return;
		case nToken :
			FoLink( ((TokNode *)p)->next );
			return;
		case nAction :
			FoLink( ((ActionNode *)p)->next );
			return;
		default :
			fatal_internal("invalid node type");
	}
}

/*
 * Add a reference to the end of a rule.
 *
 * 'r' points to the RuleBlk node in a rule.  r->end points to the last node
 * (EndRule jtype) in a rule.
 *
 * Initial:
 *		r->end --> 	o
 *
 * After:
 *		r->end --> 	o-->o--> Ptr to node following rule r in another rule
 *						|
 *						o--> Ptr to node following another reference to r.
 *
 * Note that the links are added to the head of the list so that r->end->p1
 * always points to the most recently added follow-link.  At the end, it should
 * point to the last reference found in the grammar (starting from the 1st rule).
 */
void
#ifdef __USE_PROTOS
addFoLink( Node *p, char *rname, Junction *r )
#else
addFoLink( p, rname, r )
Node *p;
char *rname;
Junction *r;
#endif
{
	Junction *j;
	require(r!=NULL,				"addFoLink: incorrect rule graph");
	require(r->end!=NULL,			"addFoLink: incorrect rule graph");
	require(r->end->jtype==EndRule,	"addFoLink: incorrect rule graph");
	require(p!=NULL,				"addFoLink: NULL FOLLOW link");

	j = newJunction();
	j->rname = rname;			/* rname on follow links point to target rule */
	j->p1 = p;					/* link to other rule */
	j->p2 = (Node *) r->end->p1;/* point to head of list */
	r->end->p1 = (Node *) j;	/* reset head to point to new node */
}

void
#ifdef __USE_PROTOS
GenCrossRef( Junction *p )
#else
GenCrossRef( p )
Junction *p;
#endif
{
	set a;
	Junction *j;
	RuleEntry *q;
	unsigned e;
	require(p!=NULL, "GenCrossRef: why are you passing me a null grammar?");

	printf("Cross Reference:\n\n");
	a = empty;
	for (; p!=NULL; p = (Junction *)p->p2)
	{
		printf("Rule %20s referenced by {", p->rname);
		/* make a set of rules for uniqueness */
		for (j = (Junction *)(p->end)->p1; j!=NULL; j = (Junction *)j->p2)
		{
			q = (RuleEntry *) hash_get(Rname, j->rname);
			require(q!=NULL, "GenCrossRef: FoLinks are screwed up");
			set_orel(q->rulenum, &a);

⌨️ 快捷键说明

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