fset2.c

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

C
2,251
字号
	/*
	fprintf(stderr, "trm_perm(");
	preorder(t); fprintf(stderr, ",");
	preorder(p); fprintf(stderr, " )\n");
	*/
	if ( t == NULL || p == NULL ) return NULL;
	if ( t->token == ALT )
	{
		t->down = trm_perm(t->down, p);
		if ( t->down == NULL ) 				/* nothing left below, rm cur node */
		{
			Tree *u = t->right;
			_Tfree( t );
			return trm_perm(u, p);
		}
		t->right = trm_perm(t->right, p);	/* look for more instances of p */
		return t;
	}
	if ( p->token != t->token )				/* not found, try a sibling */
	{
		t->right = trm_perm(t->right, p);
		return t;
	}
	t->down = trm_perm(t->down, p->down);
	if ( t->down == NULL ) 					/* nothing left below, rm cur node */
	{
		Tree *u = t->right;
		_Tfree( t );
		return trm_perm(u, p);
	}
	t->right = trm_perm(t->right, p);		/* look for more instances of p */
	return t;
}

/* add the permutation 'perm' to the LL_k sets in 'fset' */
void
#ifdef __USE_PROTOS
tcvt( set *fset, Tree *perm )
#else
tcvt( fset, perm )
set *fset;
Tree *perm;
#endif
{
	if ( perm==NULL ) return;
	set_orel(perm->token, fset);
	tcvt(fset+1, perm->down);
}

/* for each element of ftbl[k], make it the root of a tree with permute(ftbl[k+1])
 * as a child.
 */
Tree *
#ifdef __USE_PROTOS
permute( int k, int max_k )
#else
permute( k, max_k )
int k, max_k;
#endif
{
	Tree *t, *u;
	
	if ( k>max_k ) return NULL;
	if ( ftbl[k][findex[k]] == nil ) return NULL;
	t = permute(k+1, max_k);
	if ( t==NULL&&k<max_k )		/* no permutation left below for k+1 tokens? */
	{
		findex[k+1] = 0;
		(findex[k])++;			/* try next token at this k */
		return permute(k, max_k);
	}
	
	u = tmake(tnode(ftbl[k][findex[k]]), t, NULL);
	if ( k == max_k ) (findex[k])++;
	return u;
}

/* Compute LL(k) trees for alts alt1 and alt2 of p.
 * function result is tree of ambiguous input permutations
 *
 * ALGORITHM may change to look for something other than LL_k size
 * trees ==> maxk will have to change.
 */
Tree *
#ifdef __USE_PROTOS
VerifyAmbig( Junction *alt1, Junction *alt2, unsigned **ft, set *fs, Tree **t, Tree **u, int *numAmbig )
#else
VerifyAmbig( alt1, alt2, ft, fs, t, u, numAmbig )
Junction *alt1;
Junction *alt2;
unsigned **ft;
set *fs;
Tree **t;
Tree **u;
int *numAmbig;
#endif
{
	set rk;
	Tree *perm, *ambig=NULL;
	Junction *p;
	int k;
    int    tnodes_at_start=TnodesAllocated;
    int    tnodes_at_end;
    int    tnodes_used;
    set    *save_fs;
    int    j;

    save_fs=(set *) calloc(CLL_k+1,sizeof(set));
    require(save_fs != NULL,"save_fs calloc");

    for (j=0; j <= CLL_k ; j++) save_fs[j]=set_dup(fs[j]);

	maxk = LL_k;				/* NOTE: for now, we look for LL_k */
	ftbl = ft;
	fset = fs;
	constrain = &(fset[1]);
	findex = (int *) calloc(LL_k+1, sizeof(int));
	if ( findex == NULL )
	{
		fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline);
		fprintf(stderr, " out of memory while analyzing alts %d and %d of %s\n",
						CurAmbigAlt1,
						CurAmbigAlt2,
						CurAmbigbtype);
		exit(PCCTS_EXIT_FAILURE);
	}
	for (k=1; k<=LL_k; k++) findex[k] = 0;

	rk = empty;
	ConstrainSearch = 1;	/* consider only tokens in ambig sets */

	p = analysis_point((Junction *)alt1->p1);
	TRAV(p, LL_k, &rk, *t);
	*t = tshrink( *t );
	*t = tflatten( *t );
	*t = tleft_factor( *t );    /* MR10 */
	*t = prune(*t, LL_k);
	*t = tleft_factor( *t );

/***	fprintf(stderr, "after shrink&flatten&prune&left_factor:"); preorder(*t); fprintf(stderr, "\n");*/
	if ( *t == NULL )
	{
/***	fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/
		Tfree( *t );	/* kill if impossible to have ambig */
		*t = NULL;
	}

	p = analysis_point((Junction *)alt2->p1);

	TRAV(p, LL_k, &rk, *u);
	*u = tshrink( *u );
	*u = tflatten( *u );
	*t = tleft_factor( *t );    /* MR10 */
	*u = prune(*u, LL_k);
	*u = tleft_factor( *u );
/*	fprintf(stderr, "after shrink&flatten&prune&lfactor:"); preorder(*u); fprintf(stderr, "\n");*/
	if ( *u == NULL )
	{
/*		fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/
		Tfree( *u );
		*u = NULL;
	}

	for (k=1; k<=LL_k; k++) set_clr( fs[k] );

	ambig = tnode(ALT);
	k = 0;
	if ( *t!=NULL && *u!=NULL )
	{
		while ( (perm=permute(1,LL_k))!=NULL )
		{
/*			fprintf(stderr, "chk perm:"); preorder(perm); fprintf(stderr, "\n");*/
			if ( tmember(perm, *t) && tmember(perm, *u) )
			{
/*				fprintf(stderr, "ambig upon"); preorder(perm); fprintf(stderr, "\n");*/

				k++;
				perm->right = ambig->down;
				ambig->down = perm;
				tcvt(&(fs[1]), perm);
			}
			else Tfree( perm );
		}
	}

    for (j=0; j <= CLL_k ; j++) fs[j]=save_fs[j];
    free( (char *) save_fs);

    tnodes_at_end=TnodesAllocated;
    tnodes_used=tnodes_at_end - tnodes_at_start;

    if (TnodesReportThreshold > 0 && tnodes_used > TnodesReportThreshold) {
      fprintf(stdout,"There were %d tuples whose ambiguity could not be resolved by full lookahead\n",k);
      fprintf(stdout,"There were %d tnodes created to resolve ambiguity between:\n\n",tnodes_used);
      fprintf(stdout,"  Choice 1: %s  line %d  file %s\n",
                                 MR_ruleNamePlusOffset( (Node *) alt1),alt1->line,FileStr[alt1->file]);
      fprintf(stdout,"  Choice 2: %s  line %d  file %s\n",
                                 MR_ruleNamePlusOffset( (Node *) alt2),alt2->line,FileStr[alt2->file]);
      for (j=1; j <= CLL_k ; j++) {
        fprintf(stdout,"\n    Intersection of lookahead[%d] sets:\n",j);
        MR_dumpTokenSet(stdout,2,fs[j]);
      };
      fprintf(stdout,"\n");
    };

	*numAmbig = k;
	if ( ambig->down == NULL ) {_Tfree(ambig); ambig = NULL;}
	free( (char *)findex );
/*	fprintf(stderr, "final ambig:"); preorder(ambig); fprintf(stderr, "\n");*/
	return ambig;
}

static Tree *
#ifdef __USE_PROTOS
bottom_of_chain( Tree *t )
#else
bottom_of_chain( t )
Tree *t;
#endif
{
    if ( t==NULL ) return NULL;
    for (; t->down != NULL; t=t->down) {;}
    return t;
}

/*
 * Make a tree from k sets where the degree of the first k-1 sets is 1.
 */
Tree *
#ifdef __USE_PROTOS
make_tree_from_sets( set *fset1, set *fset2 )
#else
make_tree_from_sets( fset1, fset2 )
set *fset1;
set *fset2;
#endif
{
	set inter;
	int i;
	Tree *t=NULL, *n, *u;
	unsigned *p,*q;
	require(LL_k>1, "make_tree_from_sets: LL_k must be > 1");

	/* do the degree 1 sets first */
	for (i=1; i<=LL_k-1; i++)
	{
		inter = set_and(fset1[i], fset2[i]);
		require(set_deg(inter)==1, "invalid set to tree conversion");
		n = tnode(set_int(inter));
		if (t==NULL) t=n; else tmake(t, n, NULL);
		set_free(inter);
	}

	/* now add the chain of tokens at depth k */
	u = bottom_of_chain(t);
	inter = set_and(fset1[LL_k], fset2[LL_k]);
	if ( (q=p=set_pdq(inter)) == NULL ) fatal_internal("Can't alloc space for set_pdq");
	/* first one is linked to bottom, then others are sibling linked */
	n = tnode(*p++);
	u->down = n;
	u = u->down;
	while ( *p != nil )
	{
		n = tnode(*p);
		u->right = n;
		u = u->right;
		p++;
	}
	free((char *)q);

	return t;
}

/* create and return the tree of lookahead k-sequences that are in t, but not
 * in the context of predicates in predicate list p.
 */
Tree *
#ifdef __USE_PROTOS
tdif( Tree *ambig_tuples, Predicate *p, set *fset1, set *fset2 )
#else
tdif( ambig_tuples, p, fset1, fset2 )
Tree *ambig_tuples;
Predicate *p;
set *fset1;
set *fset2;
#endif
{
	unsigned **ft;
	Tree *dif=NULL;
	Tree *perm;
	set b;
	int i,k;

	if ( p == NULL ) return tdup(ambig_tuples);

	ft = (unsigned **) calloc(CLL_k+1, sizeof(unsigned *));
	require(ft!=NULL, "cannot allocate ft");
	for (i=1; i<=CLL_k; i++)
	{
		b = set_and(fset1[i], fset2[i]);
		ft[i] = set_pdq(b);
		set_free(b);
	}
	findex = (int *) calloc(LL_k+1, sizeof(int));
	if ( findex == NULL )
	{
		fatal_internal("out of memory in tdif while checking predicates");
	}
	for (k=1; k<=LL_k; k++) findex[k] = 0;

#ifdef DBG_TRAV
	fprintf(stderr, "tdif_%d[", p->k);
	preorder(ambig_tuples);
	fprintf(stderr, ",");
	preorder(p->tcontext);
	fprintf(stderr, "] =");
#endif

	ftbl = ft;
	while ( (perm=permute(1,p->k))!=NULL )
	{
#ifdef DBG_TRAV
		fprintf(stderr, "test perm:"); preorder(perm); fprintf(stderr, "\n");
#endif
		if ( tmember_constrained(perm, ambig_tuples) &&
			 !tmember_of_context(perm, p) )
		{
#ifdef DBG_TRAV
			fprintf(stderr, "satisfied upon"); preorder(perm); fprintf(stderr, "\n");
#endif
			k++;
			if ( dif==NULL ) dif = perm;
			else
			{
				perm->right = dif;
				dif = perm;
			}
		}
		else Tfree( perm );
	}

#ifdef DBG_TRAV
	preorder(dif);
	fprintf(stderr, "\n");
#endif

	for (i=1; i<=CLL_k; i++) free( (char *)ft[i] );
	free((char *)ft);
	free((char *)findex);

	return dif;
}

/* is lookahead sequence t a member of any context tree for any
 * predicate in p?
 */
static int
#ifdef __USE_PROTOS
tmember_of_context( Tree *t, Predicate *p )
#else
tmember_of_context( t, p )
Tree *t;
Predicate *p;
#endif
{
	for (; p!=NULL; p=p->right)
	{
		if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST )
			return tmember_of_context(t, p->down);
		if ( tmember_constrained(t, p->tcontext) ) return 1;
		if ( tmember_of_context(t, p->down) ) return 1;
	}
	return 0;
}

int
#ifdef __USE_PROTOS
is_single_tuple( Tree *t )
#else
is_single_tuple( t )
Tree *t;
#endif
{
	if ( t == NULL ) return 0;
	if ( t->right != NULL ) return 0;
	if ( t->down == NULL ) return 1;
	return is_single_tuple(t->down);
}


/* MR10 Check that a context guard contains only allowed things */
/* MR10   (mainly token references).                            */

#ifdef __USE_PROTOS
int contextGuardOK(Node *p,int h,int *hmax)
#else
int contextGuardOK(p,h,hmax)
  Node  *p;
  int   h;
  int   *hmax;
#endif
{
    Junction     *j;
    TokNode      *tn;

    if (p == NULL) return 1;
    if (p->ntype == nToken) {
      h++;
      if (h > *hmax) *hmax=h;
      tn=(TokNode *)p;
      if (tn->el_label != NULL) {
        warnFL(eMsg1("a label (\"%s\") for a context guard element is meaningless",tn->el_label),
                             FileStr[p->file],p->line);
      };
      return contextGuardOK( ( (TokNode *) p)->next,h,hmax);
    } else if (p->ntype == nAction) {
      goto Fail;
    } else if (p->ntype == nRuleRef) {
      goto Fail;
    } else {
      require (p->ntype == nJunction,"Unexpected ntype");
      j=(Junction *) p;
      if (j->jtype != Generic &&
          j->jtype != aSubBlk &&        /* pretty sure this one is allowed */
/****     j->jtype != aOptBlk && ****/  /* pretty sure this one is allowed */ /* MR11 not any more ! */
          j->jtype != EndBlk) {
        errFL("A context guard may not contain an option block: {...} or looping block: (...)* or (...)+",
                  FileStr[p->file],p->line);
        contextGuardOK(j->p1,h,hmax);
        return 0;
      };
      /* do both p1 and p2 so use | rather than ||  */
      return contextGuardOK(j->p2,h,hmax) | contextGuardOK(j->p1,h,hmax);
    };
Fail:
    errFL("A context guard may contain only Token references - guard will be ignored",
                             FileStr[p->file],p->line);
    contextGuardOK( ( (ActionNode *) p)->next,h,hmax);
    return 0;
}

/*
 * Look at a (...)? generalized-predicate context-guard and compute
 * either a lookahead set (k==1) or a lookahead tree for k>1.  The
 * k level is determined by the guard itself rather than the LL_k
 * variable.  For example, ( A B )? is an LL(2) guard and ( ID )?
 * is an LL(1) guard.  For the moment, you can only have a single
 * tuple in the guard.  Physically, the block must look like this
 *   --o-->TOKEN-->o-->o-->TOKEN-->o-- ... -->o-->TOKEN-->o--
 * An error is printed for any other type.
 */
Predicate *
#ifdef __USE_PROTOS
computePredFromContextGuard(Graph blk,int *msgDone)    /* MR10 */
#else
computePredFromContextGuard(blk,msgDone)               /* MR10 */
  Graph     blk;
  int       *msgDone;                                       /* MR10 */
#endif
{
    Junction *junc = (Junction *)blk.left, *p;
    Tree        *t=NULL;
	Predicate   *pred = NULL;
	set         scontext, rk;
    int         ok;
    int         hmax=0;

    require(junc!=NULL && junc->ntype == nJunction, "bad context guard");

/* MR10 Check for anything other than Tokens and generic junctions */

    *msgDone=0;                                             /* MR10 */
    ok=contextGuardOK( (Node *)junc,0,&hmax);               /* MR10 */
    if (! ok) {                                             /* MR10 */
      *msgDone=1;                                           /* MR10 */
      return NULL;                                          /* MR10 */
    };                                                      /* MR10 */
    if (hmax == 0) {
errFL("guard is 0 tokens long",FileStr[junc->file],junc->line);          /* MR11 */
      *msgDone=1;
      return NULL;
    };
    if (hmax > CLL_k) {                                     /* MR10 */
errFL(eMsgd2("guard is %d tokens long - lookahead is limited to max(k,ck)==%d", /* MR10 */
        hmax,CLL_k),                                        /* MR10 */
        FileStr[junc->file],junc->line);                    /* MR10 */
      *msgDone=1;                                           /* MR10 */
      return NULL;                                          /* MR10 */
    };                                                      /* MR10 */

	rk = empty;
	p = junc;
	pred = new_pred();
	pred->k = hmax;     /* MR10 should be CLL_k, not LLK ? */
	if (hmax > 1 )      /* MR10 was LL_k                   */
	{
		ConstrainSearch = 0;
		ContextGuardTRAV = 1;
		TRAV(p, hmax, &rk, t);  /* MR10 was LL_k */
		ContextGuardTRAV = 0;
		set_free(rk);
		t = tshrink( t );
		t = tflatten( t );
		t = tleft_factor( t );
/*
		fprintf(stderr, "ctx guard:");
		preorder(t);
		fprintf(stderr, "\n");
*/
		pred->tcontext = t;
	}
	else
	{
		REACH(p, 1, &rk, scontext);
		require(set_nil(rk), "rk != nil");
		set_free(rk);
/*
		fprintf(stderr, "LL(1) ctx guard is:");
		s_fprT(stderr, scontext);
		fprintf(stderr, "\n");
*/
		pred->scontext[1] = scontext;
	}

    list_add(&ContextGuardPredicateList,pred);     /* MR13 */

	return pred;
}

/* MR13
   When the context guard is originally computed the
   meta-tokens are not known.
*/

#ifdef __USE_PROTOS
void recomputeContextGuard(Predicate *pred)
#else
void recomputeContextGuard(pred)
    Predicate   *pred;
#endif
{
    Tree *          t=NULL;
	set             scontext;
    set             rk;
    ActionNode *    actionNode;
    Junction *      p;

    actionNode=pred->source;
    require (actionNode != NULL,"context predicate's source == NULL");

    p=actionNode->guardNodes;
    require (p != NULL,"context predicate's guardNodes == NULL");

	rk = empty;
	if (pred->k > 1 )
	{
		ConstrainSearch = 0;
		ContextGuardTRAV = 1;
		TRAV(p, pred->k, &rk, t);
		ContextGuardTRAV = 0;
		set_free(rk);
		t = tshrink( t );
		t = tflatten( t );

⌨️ 快捷键说明

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