pred.c

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

C
822
字号
/*
 * 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);
						}

⌨️ 快捷键说明

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