mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-26 05:30:48 +00:00 
			
		
		
		
	 604371b98d
			
		
	
	
		604371b98d
		
	
	
	
	
		
			
			git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1676 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			822 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			822 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * pred.c -- source for predicate detection, manipulation
 | |
|  *
 | |
|  * SOFTWARE RIGHTS
 | |
|  *
 | |
|  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
 | |
|  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
 | |
|  * company may do whatever they wish with source code distributed with
 | |
|  * PCCTS or the code generated by PCCTS, including the incorporation of
 | |
|  * PCCTS, or its output, into commerical software.
 | |
|  *
 | |
|  * We encourage users to develop software with PCCTS.  However, we do ask
 | |
|  * that credit is given to us for developing PCCTS.  By "credit",
 | |
|  * we mean that if you incorporate our source code into one of your
 | |
|  * programs (commercial product, research project, or otherwise) that you
 | |
|  * acknowledge this fact somewhere in the documentation, research report,
 | |
|  * etc...  If you like PCCTS and have developed a nice tool with the
 | |
|  * output, please mention that you developed it using PCCTS.  In
 | |
|  * addition, we ask that this header remain intact in our source code.
 | |
|  * As long as these guidelines are kept, we expect to continue enhancing
 | |
|  * this system and expect to make other tools available as they are
 | |
|  * completed.
 | |
|  *
 | |
|  * ANTLR 1.33
 | |
|  * Terence Parr
 | |
|  * Parr Research Corporation
 | |
|  * with Purdue University and AHPCRC, University of Minnesota
 | |
|  * 1989-2001
 | |
|  */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include "pcctscfg.h"
 | |
| #include "set.h"
 | |
| #include "syn.h"
 | |
| #include "hash.h"
 | |
| #include "generic.h"
 | |
| #include "dlgdef.h"
 | |
| #include <ctype.h>
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| static void complete_context_sets(RuleRefNode *, Predicate *);
 | |
| static void complete_context_trees(RuleRefNode *, Predicate *);
 | |
| #else
 | |
| static void complete_context_sets();
 | |
| static void complete_context_trees();
 | |
| #endif
 | |
| 
 | |
| char *PRED_AND_LIST = "AND";
 | |
| char *PRED_OR_LIST = "OR";
 | |
| 
 | |
| /*
 | |
|  * In C mode, return the largest constant integer found as the
 | |
|  * sole argument to LATEXT(i).
 | |
|  *
 | |
|  * In C++ mode, return the largest constant integer found as the
 | |
|  * sole argument to LT(i) given that the char before is nonalpha.
 | |
|  */
 | |
| 
 | |
| int
 | |
| #ifdef __USE_PROTOS
 | |
| predicateLookaheadDepth(ActionNode *a)
 | |
| #else
 | |
| predicateLookaheadDepth(a)
 | |
| ActionNode *a;
 | |
| #endif
 | |
| {
 | |
| 	int     max_k=0;
 | |
| 
 | |
|     if (a->predEntry != NULL) {
 | |
|        MR_pred_depth(a->predEntry->pred,&max_k);
 | |
|        goto PREDENTRY_EXIT;
 | |
|     }
 | |
| 
 | |
| 	if ( GenCC )
 | |
| 	{
 | |
| 		/* scan for LT(i) */
 | |
| 		int k = 0;
 | |
| 		char *p = a->action;
 | |
| 		while ( p!=NULL )
 | |
| 		{
 | |
| 			p = strstr(p, "LT(");
 | |
| 			if ( p!=NULL )
 | |
| 			{
 | |
| 				if ( p>=a->action && !isalpha(*(p-1)) )
 | |
| 				{
 | |
| 					k = atoi(p+strlen("LT("));
 | |
| 					if ( k>max_k ) max_k=k;
 | |
| 				}
 | |
| 				p += strlen("LT(");
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	else {
 | |
| 		/* scan for LATEXT(i) */
 | |
| 		int k = 0;
 | |
| 		char *p = a->action;
 | |
| 		while ( p!=NULL )
 | |
| 		{
 | |
| 			p = strstr(p, "LATEXT(");
 | |
| 			if ( p!=NULL )
 | |
| 			{
 | |
| 				p += strlen("LATEXT(");
 | |
| 				k = atoi(p);
 | |
| 				if ( k>max_k ) max_k=k;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (max_k==0) {
 | |
| 		max_k = 1;	   /* MR33 Badly designed if didn't set max_k when CLL_k = 1 */
 | |
| 		if (CLL_k > 1) /* MR27 Don't warn if max(k,ck) == 1 */
 | |
| 		{
 | |
| 			if ( !a->frmwarned )
 | |
| 			{
 | |
| 				a->frmwarned = 1;
 | |
| 				warnFL(eMsg1("predicate: %s missing, bad, or with i=0; assuming i=1",
 | |
| 							 GenCC?"LT(i)":"LATEXT(i)"),
 | |
| 					   FileStr[a->file], a->line);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| /* MR10 */    if ( max_k > CLL_k) {
 | |
| /* MR10 */		if ( !a->frmwarned )
 | |
| /* MR10 */        {
 | |
| /* MR10 */			a->frmwarned = 1;
 | |
| /* MR11 */ errFL(eMsgd2("predicate refers to lookahead token %d. Semantic lookahead is limited to max(k,ck)==%d",
 | |
| /* MR10 */                        max_k,CLL_k),
 | |
| /* MR10 */                        FileStr[a->file],a->line);
 | |
| /* MR10 */          if (max_k >= OutputLL_k) {
 | |
| /* MR10 */            if (!GenCC) {
 | |
| /* MR10 */              errFL(eMsgd("    the lookahead buffer size in C mode is %d token(s) (including the one just recognized)",
 | |
| /* MR10 */                        OutputLL_k),
 | |
| /* MR10 */                        FileStr[a->file],a->line);
 | |
| /* MR10 */            };
 | |
| /* MR10 */          };
 | |
| /* MR10 */        };
 | |
| /* MR10 */        max_k= CLL_k;
 | |
| /* MR10 */    };
 | |
| 
 | |
| PREDENTRY_EXIT:
 | |
| 	return max_k;
 | |
| }
 | |
| 
 | |
| /* Find all predicates in a block of alternatives.  DO NOT find predicates
 | |
|  * behind the block because that predicate could depend on things set in
 | |
|  * one of the nonoptional blocks
 | |
|  */
 | |
| 
 | |
| Predicate *
 | |
| #ifdef __USE_PROTOS
 | |
| find_in_aSubBlk( Junction *alt )
 | |
| #else
 | |
| find_in_aSubBlk( alt )
 | |
| Junction *alt;
 | |
| #endif
 | |
| {
 | |
| 	Predicate *a, *head=NULL, *tail=NULL, *root=NULL;
 | |
| 	Junction *p = alt;
 | |
| 
 | |
|     if (MRhoisting) {
 | |
|       return MR_find_in_aSubBlk(alt);
 | |
|     };
 | |
| 	for (; p!=NULL; p=(Junction *)p->p2)
 | |
| 	{
 | |
| 		/* ignore empty alts */
 | |
| 		if ( p->p1->ntype != nJunction ||
 | |
| 			 ((Junction *)p->p1)->jtype != EndBlk )
 | |
| 		{
 | |
| 			a = find_predicates(p->p1);	/* get preds for this alt */
 | |
| 			if ( a==NULL ) continue;
 | |
| 
 | |
| 			/* make an OR list of predicates */
 | |
| 			if ( head==NULL )
 | |
| 			{
 | |
| 				root = new_pred();
 | |
| 				root->expr = PRED_OR_LIST;
 | |
| 				head = tail = a;
 | |
| 				root->down = head;
 | |
| 			}
 | |
| 			else {
 | |
| 				tail->right = a;
 | |
| 				a->left = tail;
 | |
| 				a->up = tail->up;
 | |
| 				tail = a;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* if just one pred, remove OR root */
 | |
| 	if ( root!=NULL && root->down->right == NULL )
 | |
| 	{
 | |
| 		Predicate *d = root->down;
 | |
| 		free( (char *) root);
 | |
| 		return d;
 | |
| 	}
 | |
| 
 | |
| 	return root;
 | |
| }
 | |
| 
 | |
| Predicate *
 | |
| #ifdef __USE_PROTOS
 | |
| find_in_aOptBlk( Junction *alt )
 | |
| #else
 | |
| find_in_aOptBlk( alt )
 | |
| Junction *alt;
 | |
| #endif
 | |
| {
 | |
| 	return find_in_aSubBlk( alt );
 | |
| }
 | |
| 
 | |
| Predicate *
 | |
| #ifdef __USE_PROTOS
 | |
| find_in_aLoopBegin( Junction *alt )
 | |
| #else
 | |
| find_in_aLoopBegin( alt )
 | |
| Junction *alt;
 | |
| #endif
 | |
| {
 | |
| 	return find_in_aSubBlk( (Junction *) alt->p1 );	/* get preds in alts */
 | |
| }
 | |
| 
 | |
| Predicate *
 | |
| #ifdef __USE_PROTOS
 | |
| find_in_aPlusBlk( Junction *alt )
 | |
| #else
 | |
| find_in_aPlusBlk( alt )
 | |
| Junction *alt;
 | |
| #endif
 | |
| {
 | |
| 	require(alt!=NULL&&alt->p2!=NULL, "invalid aPlusBlk");
 | |
| 	return find_in_aSubBlk( alt );
 | |
| }
 | |
| 
 | |
| /* Look for a predicate;
 | |
|  *
 | |
|  * Do not pass anything but Junction nodes; no Actions, Tokens, RuleRefs.
 | |
|  * This means that a "hoisting distance" of zero is the only distance
 | |
|  * allowable.  Init actions are ignored.
 | |
|  *
 | |
|  * WARNING:
 | |
|  *		Assumes no (..)? block after predicate for the moment.
 | |
|  *		Does not check to see if pred is in production that can generate
 | |
|  *			a sequence contained in the set of ambiguous tuples.
 | |
|  *
 | |
|  * Return the predicate found if any.
 | |
|  */
 | |
| 
 | |
| 
 | |
| Predicate *
 | |
| #ifdef __USE_PROTOS
 | |
| find_predicates( Node *alt )
 | |
| #else
 | |
| find_predicates( alt )
 | |
| Node *alt;
 | |
| #endif
 | |
| {
 | |
| #ifdef DBG_PRED
 | |
| 	Junction *j;
 | |
| 	RuleRefNode *r;
 | |
| 	TokNode *t;
 | |
| #endif
 | |
| 	Predicate *pred;
 | |
| 
 | |
| 	if ( alt==NULL ) return NULL;
 | |
| 
 | |
| #ifdef DBG_PRED
 | |
| 	switch ( alt->ntype )
 | |
| 	{
 | |
| 		case nJunction :
 | |
| 			j = (Junction *) alt;
 | |
| 			fprintf(stderr, "Junction(in %s)", j->rname);
 | |
| 			switch ( j->jtype )
 | |
| 			{
 | |
| 				case aSubBlk :
 | |
| 					fprintf(stderr,"aSubBlk\n");
 | |
| 					break;
 | |
| 				case aOptBlk :
 | |
| 					fprintf(stderr,"aOptBlk\n");
 | |
| 					break;
 | |
| 				case aLoopBegin :
 | |
| 					fprintf(stderr,"aLoopBeginBlk\n");
 | |
| 					break;
 | |
| 				case aLoopBlk :
 | |
| 					fprintf(stderr,"aLoopBlk\n");
 | |
| 					break;
 | |
| 				case aPlusBlk :
 | |
| 					fprintf(stderr,"aPlusBlk\n");
 | |
| 					break;
 | |
| 				case EndBlk :
 | |
| 					fprintf(stderr,"EndBlk\n");
 | |
| 					break;
 | |
| 				case RuleBlk :
 | |
| 					fprintf(stderr,"RuleBlk\n");
 | |
| 					break;
 | |
| 				case Generic :
 | |
| 					fprintf(stderr,"Generic\n");
 | |
| 					break;
 | |
| 				case EndRule :
 | |
| 					fprintf(stderr,"EndRule\n");
 | |
| 					break;
 | |
| 			}
 | |
| 			break;
 | |
| 		case nRuleRef :
 | |
| 			r = (RuleRefNode *) alt;
 | |
| 			fprintf(stderr, "RuleRef(in %s)\n", r->rname);
 | |
| 			break;
 | |
| 		case nToken :
 | |
| 			t = (TokNode *) alt;
 | |
| 			fprintf(stderr, "TokenNode(in %s)%s\n", t->rname, TokenString(t->token));
 | |
| 			break;
 | |
| 		case nAction :
 | |
| 			fprintf(stderr, "Action\n");
 | |
| 			break;
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	switch ( alt->ntype )
 | |
| 	{
 | |
| 		case nJunction :
 | |
| 		{
 | |
| 			Predicate *a, *b;
 | |
| 			Junction *p = (Junction *) alt;	
 | |
| 
 | |
| 			/* lock nodes */
 | |
| 			if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||
 | |
| 				 p->jtype==aPlusBlk || p->jtype==EndRule )
 | |
| 			{
 | |
| 				require(p->pred_lock!=NULL, "rJunc: lock array is NULL");
 | |
| 				if ( p->pred_lock[1] )
 | |
| 				{
 | |
| 					return NULL;
 | |
| 				}
 | |
| 				p->pred_lock[1] = TRUE;
 | |
| 			}
 | |
| 
 | |
| 			switch ( p->jtype )
 | |
| 			{
 | |
| 				case aSubBlk :
 | |
| 					a = find_in_aSubBlk(p);
 | |
| 					return a;	/* nothing is visible past this guy */
 | |
| 				case aOptBlk :
 | |
| 					a = find_in_aOptBlk(p);
 | |
| 					return a;
 | |
| 				case aLoopBegin :
 | |
| 					a = find_in_aLoopBegin(p);
 | |
| 					return a;
 | |
| 				case aLoopBlk :
 | |
| 					a = find_in_aSubBlk(p);
 | |
| 					p->pred_lock[1] = FALSE;
 | |
| 					return a;
 | |
| 				case aPlusBlk :
 | |
| 					a = find_in_aPlusBlk(p);
 | |
| 					p->pred_lock[1] = FALSE;
 | |
| 					return a;	/* nothing is visible past this guy */
 | |
| 				case RuleBlk :
 | |
| 					a = find_predicates(p->p1);
 | |
| 					p->pred_lock[1] = FALSE;
 | |
| 					return a;
 | |
| 				case Generic :
 | |
| 					a = find_predicates(p->p1);
 | |
| 					b = find_predicates(p->p2);
 | |
| 					if ( p->pred_lock!=NULL ) p->pred_lock[1] = FALSE;
 | |
| 					if ( a==NULL ) return b;
 | |
| 					if ( b==NULL ) return a;
 | |
| 					/* otherwise OR the two preds together */
 | |
| 					{
 | |
| 					fatal_internal("hit unknown situation during predicate hoisting");
 | |
| 					}
 | |
| 				case EndBlk :
 | |
| 				case EndRule :	/* Find no predicates after a rule ref */
 | |
| 					return NULL;
 | |
| 				default:
 | |
| 					fatal_internal("this cannot be printed\n");
 | |
| 					break;
 | |
| 			}
 | |
| 		}
 | |
| 		case nAction :
 | |
| 		{
 | |
| 			ActionNode *p = (ActionNode *) alt;
 | |
|             if ( p->noHoist) return NULL;                           /* MR12c */
 | |
| 			if ( p->init_action ) return find_predicates(p->next);
 | |
| 			if ( p->is_predicate )
 | |
| 			{
 | |
| 				Tree *t=NULL;
 | |
| #ifdef DBG_PRED
 | |
| 				fprintf(stderr, "predicate: <<%s>>?\n", p->action);
 | |
| #endif
 | |
| 				if ( p->guardpred!=NULL )
 | |
| 				{
 | |
| 					pred = predicate_dup(p->guardpred);
 | |
|                     MR_guardPred_plainSet(p,pred);                  /* MR12c */
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					pred = new_pred();
 | |
| 					pred->k = predicateLookaheadDepth(p);
 | |
| 					pred->source = p;
 | |
| 					pred->expr = p->action;
 | |
| 					if ( HoistPredicateContext && pred->k > 1 )
 | |
| 					{
 | |
| 						/* MR30 No need to use first_item_is_guess_block_extra
 | |
| 						   since we know this is an action, not a (...)* or
 | |
| 						   (...)+ block.
 | |
| 						*/
 | |
| 
 | |
| 						if ( first_item_is_guess_block((Junction *)p->next) )
 | |
| 						{
 | |
|                             warnFL("cannot compute context of predicate in front of (..)? block",
 | |
|                             FileStr[p->file], p->line);
 | |
| 						}
 | |
| 						else
 | |
| 						{
 | |
| 							ConstrainSearch = 0;
 | |
| /* MR11 */                  if (p->ampersandPred != NULL) {
 | |
| /* MR11 */  					TRAV(p,
 | |
| /* MR11 */							 pred->k,
 | |
| /* MR11 */  						 &(pred->completionTree), t);
 | |
| /* MR11 */                  } else {
 | |
|     							TRAV(p->next,
 | |
|     								 pred->k,
 | |
|     								 &(pred->completionTree), t);
 | |
|                             };
 | |
| 							pred->tcontext = t;
 | |
|                             MR_check_pred_too_long(pred,pred->completionTree);
 | |
| #ifdef DBG_PRED
 | |
| 							fprintf(stderr, "LL(%d) context:", pred->k);
 | |
| 							preorder(t);
 | |
| 							fprintf(stderr, "\n");
 | |
| #endif
 | |
| 						}
 | |
| 					}
 | |
| 					else if ( HoistPredicateContext && pred->k == 1 )
 | |
| 					{
 | |
| 						pred->scontext[1] = empty;
 | |
| 						/* MR30 No need to use first_item_is_guess_block_extra
 | |
| 						   since we know this is an action.
 | |
| 						*/
 | |
| 						if ( first_item_is_guess_block((Junction *)p->next) )
 | |
| 						{
 | |
|                         warnFL("cannot compute context of predicate in front of (..)? block",
 | |
|                                              FileStr[p->file], p->line);
 | |
| 						}
 | |
| 						else
 | |
| 						{
 | |
| 							REACH((Junction *)p->next,
 | |
| 								  1,
 | |
| 								  &(pred->completionSet),
 | |
| 								  pred->scontext[1]);
 | |
|                             MR_check_pred_too_long(pred,pred->completionSet);
 | |
| #ifdef DBG_PRED
 | |
| 							fprintf(stderr, "LL(1) context:");
 | |
| 							s_fprT(stderr, pred->scontext[1]);
 | |
| 							fprintf(stderr, "\n");
 | |
| #endif
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 				{
 | |
| 					Predicate  *d = find_predicates(p->next);
 | |
|                     Predicate  *root;
 | |
| 
 | |
| /* Warning: Doesn't seem like the up pointers will all be set correctly;
 | |
|  * TJP: that's ok, we're not using them now.
 | |
|  */
 | |
| 					if ( d!=NULL )
 | |
| 					{
 | |
| 						root = new_pred();
 | |
| 						root->expr = PRED_AND_LIST;
 | |
| 						root->down = pred;
 | |
| 						pred->right = d;
 | |
| 						pred->up = root;
 | |
| 						d->left = pred;
 | |
| 						d->up = pred->up;
 | |
| 						return root;
 | |
| 					}
 | |
| 				}
 | |
| 				return pred;
 | |
| 			}
 | |
| 			return NULL;
 | |
| 		}
 | |
| 		case nRuleRef :
 | |
| 		{
 | |
| 			Predicate   *a;
 | |
| 			RuleRefNode *p = (RuleRefNode *) alt;
 | |
| 			Junction    *r;
 | |
|             Junction    *save_MR_RuleBlkWithHalt;
 | |
| 
 | |
| 			RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text);
 | |
| 			if ( q == NULL )
 | |
| 			{
 | |
| 				warnFL( eMsg1("rule %s not defined",p->text), FileStr[p->file], p->line );
 | |
| 				return NULL;
 | |
| 			}
 | |
| 			r = RulePtr[q->rulenum];
 | |
| 			if ( r->pred_lock[1] )
 | |
| 			{
 | |
| 				/* infinite left-recursion; ignore 'cause LL sup 1 (k) analysis
 | |
| 				 * must have seen it earlier.
 | |
| 				 */
 | |
| 				return NULL;
 | |
| 			}
 | |
| 
 | |
|             /* MR10 There should only be one halt set at a time.        */
 | |
|             /* MR10 Life would have been easier with a global variable  */
 | |
|             /* MR10    (at least for this particular need)              */
 | |
|             /* MR10 Unset the old one and set the new one, later undo.  */
 | |
| 
 | |
|             require(r->end->halt == FALSE,"should only have one halt at a time");
 | |
| 
 | |
| /* MR10 */  require(MR_RuleBlkWithHalt == NULL ||
 | |
| /* MR10 */          (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE),
 | |
| /* MR10 */             "RuleBlkWithHalt->end not RuleBlk or does not have halt set");
 | |
| /* MR10 */  if (MR_RuleBlkWithHalt != NULL) {
 | |
| /* MR10 */    MR_RuleBlkWithHalt->end->halt=FALSE;
 | |
| /* MR10 */  };
 | |
| 
 | |
| /***        fprintf(stderr,"\nSetting halt on junction #%d\n",r->end->seq);     ***/
 | |
| 
 | |
|             require(r->end->halt == FALSE,"rule->end->halt already set");
 | |
| 
 | |
|             save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt;
 | |
| 
 | |
| /* MR10 */  MR_pointerStackPush(&MR_RuleBlkWithHaltStack,MR_RuleBlkWithHalt);
 | |
| /* MR10 */  MR_pointerStackPush(&MR_PredRuleRefStack,p);
 | |
| 
 | |
| 			r->end->halt = TRUE;
 | |
| /* MR10 */  MR_RuleBlkWithHalt=r;
 | |
| 
 | |
| 			a = find_predicates((Node *)r);
 | |
| 
 | |
|             require(r->end->halt == TRUE,"rule->end->halt not set");
 | |
|             r->end->halt = FALSE;
 | |
| 
 | |
| /* MR10 */  MR_pointerStackPop(&MR_PredRuleRefStack);
 | |
| /* MR10 */  MR_RuleBlkWithHalt=(Junction *) MR_pointerStackPop(&MR_RuleBlkWithHaltStack);
 | |
| 
 | |
|             require (MR_RuleBlkWithHalt==save_MR_RuleBlkWithHalt,
 | |
|                     "RuleBlkWithHaltStack not consistent");
 | |
| 
 | |
| /* MR10 */  require(MR_RuleBlkWithHalt == NULL ||
 | |
| /* MR10 */          (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == FALSE),
 | |
| /* MR10 */             "RuleBlkWithHalt->end not RuleBlk or has no halt set");
 | |
| /* MR10 */  if (MR_RuleBlkWithHalt != NULL) {
 | |
| /* MR10 */    MR_RuleBlkWithHalt->end->halt=TRUE;
 | |
| /* MR10 */  };
 | |
| 
 | |
| /***        fprintf(stderr,"\nRestoring halt on junction #%d\n",r->end->seq);   ***/
 | |
| 
 | |
| 			if ( a==NULL ) return NULL;
 | |
| 
 | |
| 			/* attempt to compute the "local" FOLLOW just like in normal lookahead
 | |
| 			 * computation if needed
 | |
| 			 */
 | |
| 
 | |
| 			complete_context_sets(p,a);
 | |
| 			complete_context_trees(p,a);
 | |
| 
 | |
| /* MR10 */  MR_cleanup_pred_trees(a);
 | |
| 
 | |
| 			return a;
 | |
| 		}
 | |
| 		case nToken :
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| Predicate *MR_find_predicates_and_supp(Node *alt)
 | |
| #else
 | |
| Predicate *MR_find_predicates_and_supp(alt)
 | |
|   Node      *alt;
 | |
| #endif
 | |
| {
 | |
|     Predicate   *p;
 | |
| 
 | |
|     p=find_predicates(alt);
 | |
|     p=MR_suppressK(alt,p);
 | |
|     return p;
 | |
| }
 | |
| 
 | |
| Predicate *
 | |
| #ifdef __USE_PROTOS
 | |
| new_pred( void )
 | |
| #else
 | |
| new_pred( )
 | |
| #endif
 | |
| {
 | |
| 	Predicate *p = (Predicate *) calloc(1,sizeof(Predicate)); /* MR10 */
 | |
| 	require(p!=NULL, "new_pred: cannot alloc predicate");
 | |
|     p->scontext[0]=empty;
 | |
|     p->scontext[1]=empty;
 | |
|     p->completionTree=empty;
 | |
|     p->completionSet=empty;
 | |
|     p->plainSet=empty;
 | |
| 	return p;
 | |
| }
 | |
| 
 | |
| static void
 | |
| #ifdef __USE_PROTOS
 | |
| complete_context_sets( RuleRefNode *p, Predicate *a )
 | |
| #else
 | |
| complete_context_sets( p, a )
 | |
| RuleRefNode *p;
 | |
| Predicate *a;
 | |
| #endif
 | |
| {
 | |
| 	set rk2, b;
 | |
| 	int k2;
 | |
| 
 | |
| #ifdef DBG_PRED
 | |
| 	fprintf(stderr, "enter complete_context_sets\n");
 | |
| #endif
 | |
| 	for (; a!=NULL; a=a->right)
 | |
| 	{
 | |
| 		if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST )
 | |
| 		{
 | |
| 			complete_context_sets(p,a->down);
 | |
| 			continue;
 | |
| 		}
 | |
| 		rk2 = b = empty;
 | |
| 		while ( !set_nil(a->completionSet) )
 | |
| 		{
 | |
| 			k2 = set_int(a->completionSet);
 | |
| 			set_rm(k2, a->completionSet);
 | |
| 
 | |
|             REACH(p->next, k2, &rk2, b);
 | |
| 			set_orin(&(a->scontext[1]), b);
 | |
| 			set_free(b);
 | |
| 		}
 | |
| 
 | |
| 		set_orin(&(a->completionSet), rk2);/* remember what we couldn't do */
 | |
| 		set_free(rk2);
 | |
| #ifdef DBG_PRED
 | |
| 		fprintf(stderr, "LL(1) context for %s(addr 0x%x) after ruleref:", a->expr, a);
 | |
| 		s_fprT(stderr, a->scontext[1]);
 | |
| 		fprintf(stderr, "\n");
 | |
| #endif
 | |
| /*		complete_context_sets(p, a->down);*/
 | |
| 	}
 | |
| #ifdef DBG_PRED
 | |
| 	fprintf(stderr, "exit complete_context_sets\n");
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static void
 | |
| #ifdef __USE_PROTOS
 | |
| complete_context_trees( RuleRefNode *p, Predicate *a )
 | |
| #else
 | |
| complete_context_trees( p, a )
 | |
| RuleRefNode *p;
 | |
| Predicate *a;
 | |
| #endif
 | |
| {
 | |
| 	set rk2;
 | |
| 	int k2;
 | |
| 	Tree *u;
 | |
| 
 | |
| #ifdef DBG_PRED
 | |
| 	fprintf(stderr, "enter complete_context_trees\n");
 | |
| #endif
 | |
| 	for (; a!=NULL; a=a->right)
 | |
| 	{
 | |
| 		if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST )
 | |
| 		{
 | |
| 			complete_context_trees(p, a->down);
 | |
| 			continue;
 | |
| 		}
 | |
| 		rk2 = empty;
 | |
| 
 | |
| 		/* any k left to do? if so, link onto tree */
 | |
| 		while ( !set_nil(a->completionTree) )
 | |
| 		{	
 | |
| 			k2 = set_int(a->completionTree);
 | |
| 			set_rm(k2, a->completionTree);
 | |
| 			u = NULL;
 | |
| 
 | |
|             TRAV(p->next, k2, &rk2, u);
 | |
| 
 | |
| 			/* any subtrees missing k2 tokens, add u onto end */
 | |
| 			a->tcontext = tlink(a->tcontext, u, k2);
 | |
|             Tfree(u);   /* MR10 */
 | |
| 		}
 | |
| 		set_orin(&(a->completionTree), rk2);/* remember what we couldn't do */
 | |
| 		set_free(rk2);
 | |
| #ifdef DBG_PRED
 | |
| 		fprintf(stderr, "LL(i<%d) context after ruleref:", LL_k);
 | |
| 		preorder(a->tcontext);
 | |
| 		fprintf(stderr, "\n");
 | |
| #endif
 | |
| /*		complete_context_trees(p, a->down);*/
 | |
| 	}
 | |
| #ifdef DBG_PRED
 | |
| 	fprintf(stderr, "exit complete_context_trees\n");
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /* Walk a list of predicates and return the set of all tokens in scontext[1]'s */
 | |
| set
 | |
| #ifdef __USE_PROTOS
 | |
| covered_set( Predicate *p )
 | |
| #else
 | |
| covered_set( p )
 | |
| Predicate *p;
 | |
| #endif
 | |
| {
 | |
| 	set a;
 | |
| 
 | |
| 	a = empty;
 | |
| 	for (; p!=NULL; p=p->right)
 | |
| 	{
 | |
| 		if ( p->expr == PRED_AND_LIST || p->expr == PRED_OR_LIST )
 | |
| 		{
 | |
| 			set_orin(&a, covered_set(p->down));
 | |
| 			continue;
 | |
| 		}
 | |
| 		set_orin(&a, p->scontext[1]);
 | |
| 		set_orin(&a, covered_set(p->down));
 | |
| 	}
 | |
| 	return a;
 | |
| }
 | |
| 
 | |
| /* MR10 predicate_free()
 | |
|    MR10 Don't free the leaf nodes since they are part of the action node
 | |
| */
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| void predicate_free(Predicate *p)
 | |
| #else
 | |
| void predicate_free(p)
 | |
|   Predicate     *p;
 | |
| #endif
 | |
| {
 | |
|   if (p == NULL) return;
 | |
|   predicate_free(p->right);
 | |
|   predicate_free(p->down);
 | |
|   if (p->cloned ||
 | |
|       p->source == NULL ||
 | |
|       p->source->guardpred == NULL ||
 | |
|       p->expr == PRED_AND_LIST ||
 | |
|       p->expr == PRED_OR_LIST) {
 | |
|     set_free(p->scontext[1]);
 | |
|     set_free(p->completionSet);
 | |
|     set_free(p->completionTree);
 | |
|     set_free(p->plainSet);
 | |
|     Tfree(p->tcontext);
 | |
|     free( (char *) p);
 | |
|   } else {
 | |
|     p->right=NULL;
 | |
|     p->down=NULL;  /* MR13 *** debug */
 | |
|   };
 | |
| }
 | |
| 
 | |
| /* MR10 predicate_dup() */
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| Predicate * predicate_dup_xxx(Predicate *p,int contextToo)
 | |
| #else
 | |
| Predicate * predicate_dup_xxx(p,contextToo)
 | |
|   Predicate     *p;
 | |
|   int           contextToo;
 | |
| #endif
 | |
| {
 | |
|   Predicate     *q;
 | |
| 
 | |
|   if (p == NULL) return NULL;
 | |
|   q=new_pred();
 | |
|   q->down=predicate_dup(p->down);
 | |
|   q->right=predicate_dup(p->right);
 | |
| 
 | |
|   /*
 | |
|      don't replicate expr - it is read-only
 | |
|      and address comparison is used to look
 | |
|      for identical predicates.
 | |
|   */
 | |
| 
 | |
|   q->expr=p->expr;
 | |
|   q->k=p->k;
 | |
|   q->source=p->source;
 | |
|   q->cloned=1;
 | |
|   q->ampersandStyle=p->ampersandStyle;
 | |
|   q->inverted=p->inverted;
 | |
|   q->predEntry=p->predEntry;
 | |
|   q->plainSet=set_dup(p->plainSet);
 | |
| 
 | |
|   if (contextToo) {
 | |
|     q->tcontext=tdup(p->tcontext);
 | |
|     q->scontext[0]=set_dup(p->scontext[0]);
 | |
|     q->scontext[1]=set_dup(p->scontext[1]);
 | |
|     q->completionTree=set_dup(p->completionTree);
 | |
|     q->completionSet=set_dup(p->completionSet);
 | |
|   };
 | |
| 
 | |
|   /* don't need to dup "redundant" */
 | |
| 
 | |
|   return q;
 | |
| 
 | |
| }
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| Predicate * predicate_dup_without_context(Predicate *p)
 | |
| #else
 | |
| Predicate * predicate_dup_without_context(p)
 | |
|   Predicate     *p;
 | |
| #endif
 | |
| {
 | |
|   return predicate_dup_xxx(p,0);
 | |
| }
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| Predicate * predicate_dup(Predicate *p)
 | |
| #else
 | |
| Predicate * predicate_dup(p)
 | |
|   Predicate     *p;
 | |
| #endif
 | |
| {
 | |
|   return predicate_dup_xxx(p,1);
 | |
| }
 | |
| 
 |