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