git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1676 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			2251 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2251 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * fset2.c
 | |
|  *
 | |
|  * Compute FIRST sets for full LL(k)
 | |
|  *
 | |
|  * 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 <stdlib.h>
 | |
| 
 | |
| #ifdef PCCTS_USE_STDARG
 | |
| #include <stdarg.h>
 | |
| #else
 | |
| #include <varargs.h>
 | |
| #endif
 | |
| 
 | |
| #include "set.h"
 | |
| #include "syn.h"
 | |
| #include "hash.h"
 | |
| #include "generic.h"
 | |
| #include "dlgdef.h"
 | |
| 
 | |
| /* ick! globals.  Used by permute() to track which elements of a set have been used */
 | |
| 
 | |
| static int *findex;
 | |
| set *fset;              /* MR11 make global */
 | |
| static unsigned **ftbl;
 | |
| static set *constrain; /* pts into fset. constrains tToken() to 'constrain' */
 | |
| int ConstrainSearch;
 | |
| int maxk;               /* set to initial k upon tree construction request */
 | |
|                         /* MR11 make global */
 | |
| static Tree *FreeList = NULL;
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| static int tmember_of_context(Tree *, Predicate *);
 | |
| #else
 | |
| static int tmember_of_context();
 | |
| #endif
 | |
| 
 | |
| #if TREE_DEBUG
 | |
| set     set_of_tnodes_in_use;
 | |
| int     stop_on_tnode_seq_number=(-1);     /* (-1) to disable */
 | |
| #endif
 | |
| 
 | |
| /* Do root
 | |
|  * Then each sibling
 | |
|  */
 | |
| 
 | |
| void
 | |
| #ifdef __USE_PROTOS
 | |
| preorder( Tree *tree )
 | |
| #else
 | |
| preorder( tree )
 | |
| Tree *tree;
 | |
| #endif
 | |
| {
 | |
| 	if ( tree == NULL ) return;
 | |
| 	if ( tree->down != NULL ) fprintf(stderr, " (");
 | |
| 	if ( tree->token == ALT ) fprintf(stderr, " ALT");
 | |
| 	else fprintf(stderr, " %s", TerminalString(tree->token));
 | |
| 	if ( tree->token==EpToken ) fprintf(stderr, "(%d)", tree->v.rk);
 | |
| 	preorder(tree->down);
 | |
| 	if ( tree->down != NULL ) fprintf(stderr, " )");
 | |
| 	preorder(tree->right);
 | |
| }
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| int MR_tree_matches_constraints(int k,set * constrain,Tree *t)
 | |
| #else
 | |
| int MR_tree_matches_constraints(k,constrain,t)
 | |
|   int       k;
 | |
|   set *     constrain;
 | |
|   Tree *    t;
 | |
| #endif
 | |
| {
 | |
|   int       i;
 | |
|   Tree      *u;
 | |
| 
 | |
|   if (k == 0) return 1;
 | |
| 
 | |
|   /* for testing guard predicates: if the guard tree is shorter
 | |
|      than the constraint then it is a match.  The reason is that
 | |
|      a guard of (A B) should be equivalent to a guard of (A B . . .)
 | |
|      where "." matches every token.  Thus a match which runs out
 | |
|      of tree before constraint is a match.
 | |
|   */
 | |
| 
 | |
|   if (t == NULL) return 1;
 | |
|   require (set_deg(constrain[0]) == 1,
 | |
|             "MR_tree_matches_constraints: set_deg != 1");
 | |
|   i=set_int(constrain[0]);
 | |
|   if (t->token != i) return 0;
 | |
|   if (k-1 == 0) return 1;
 | |
|   for (u=t->down; u != NULL; u=u->right) {
 | |
|     if (MR_tree_matches_constraints(k-1,&constrain[1],u)) {
 | |
|        return 1;
 | |
|     };
 | |
|   };
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| /* check the depth of each primary sibling to see that it is exactly
 | |
|  * k deep. e.g.;
 | |
|  *
 | |
|  *	ALT
 | |
|  *   |
 | |
|  *   A ------- B
 | |
|  *   |         |
 | |
|  *   C -- D    E
 | |
|  *
 | |
|  * Remove all branches <= k deep.
 | |
|  *
 | |
|  * Added by TJP 9-23-92 to make the LL(k) constraint mechanism to work.
 | |
|  */
 | |
| 
 | |
| static int pruneCount=0;
 | |
| static int prunePeak=200;
 | |
| 
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| prune( Tree *t, int k )
 | |
| #else
 | |
| prune( t, k )
 | |
| Tree *t;
 | |
| int k;
 | |
| #endif
 | |
| {
 | |
|     pruneCount++;
 | |
|     if (pruneCount > prunePeak+100) {
 | |
|       prunePeak=pruneCount;
 | |
| #if 0
 | |
| ***   fprintf(stderr,"pruneCount=%d\n",pruneCount);
 | |
| /***  preorder(t);   ***/
 | |
| ***   fprintf(stderr,"\n",pruneCount);
 | |
| #endif
 | |
|     };
 | |
|     if ( t == NULL ) {
 | |
|         pruneCount--;
 | |
|         return NULL;
 | |
|     };
 | |
|     if ( t->token == ALT ) fatal_internal("prune: ALT node in FIRST tree");
 | |
|     if ( t->right!=NULL ) t->right = prune(t->right, k);
 | |
|     if ( k>1 )
 | |
| 	{
 | |
| 		if ( t->down!=NULL ) t->down = prune(t->down, k-1);
 | |
| 		if ( t->down == NULL )
 | |
| 		{
 | |
| 			Tree *r = t->right;
 | |
| 			t->right = NULL;
 | |
| 			Tfree(t);
 | |
|             pruneCount--;
 | |
| 			return r;
 | |
| 		}
 | |
| 	}
 | |
|     pruneCount--;
 | |
|     return t;
 | |
| }
 | |
| 
 | |
| /* build a tree (root child1 child2 ... NULL) */
 | |
| #ifdef PCCTS_USE_STDARG
 | |
| Tree *tmake(Tree *root, ...)
 | |
| #else
 | |
| Tree *tmake(va_alist)
 | |
| va_dcl
 | |
| #endif
 | |
| {
 | |
| 	Tree *w;
 | |
| 	va_list ap;
 | |
| 	Tree *child, *sibling=NULL, *tail=NULL;
 | |
| #ifndef PCCTS_USE_STDARG
 | |
| 	Tree *root;
 | |
| #endif
 | |
| 
 | |
| #ifdef PCCTS_USE_STDARG
 | |
| 	va_start(ap, root);
 | |
| #else
 | |
| 	va_start(ap);
 | |
| 	root = va_arg(ap, Tree *);
 | |
| #endif
 | |
| 	child = va_arg(ap, Tree *);
 | |
| 	while ( child != NULL )
 | |
| 	{
 | |
| #ifdef DUM
 | |
| 		/* added "find end of child" thing TJP March 1994 */
 | |
| 		for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */
 | |
| #else
 | |
| 		w = child;
 | |
| #endif
 | |
| 
 | |
| 		if ( sibling == NULL ) {sibling = child; tail = w;}
 | |
| 		else {tail->right = child; tail = w;}
 | |
| 		child = va_arg(ap, Tree *);
 | |
| 	}
 | |
| 
 | |
| 	/* was "root->down = sibling;" */
 | |
| 	if ( root==NULL ) root = sibling;
 | |
| 	else root->down = sibling;
 | |
| 
 | |
| 	va_end(ap);
 | |
| 	return root;
 | |
| }
 | |
| 
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tnode( int tok )
 | |
| #else
 | |
| tnode( tok )
 | |
| int tok;
 | |
| #endif
 | |
| {
 | |
| 	Tree *p, *newblk;
 | |
| 	static int n=0;
 | |
| 	
 | |
| 	if ( FreeList == NULL )
 | |
| 	{
 | |
| 		/*fprintf(stderr, "tnode: %d more nodes\n", TreeBlockAllocSize);*/
 | |
| 		if ( TreeResourceLimit > 0 )
 | |
| 		{
 | |
| 			if ( (n+TreeBlockAllocSize) >= TreeResourceLimit )
 | |
| 			{
 | |
| 				fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline);
 | |
| 				fprintf(stderr, " hit analysis resource limit while analyzing alts %d and %d %s\n",
 | |
| 								CurAmbigAlt1,
 | |
| 								CurAmbigAlt2,
 | |
| 								CurAmbigbtype);
 | |
| 				exit(PCCTS_EXIT_FAILURE);
 | |
| 			}
 | |
| 		}
 | |
| 		newblk = (Tree *)calloc(TreeBlockAllocSize, sizeof(Tree));
 | |
| 		if ( newblk == NULL )
 | |
| 		{
 | |
| 			fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline);
 | |
| 			fprintf(stderr, " out of memory while analyzing alts %d and %d %s\n",
 | |
| 							CurAmbigAlt1,
 | |
| 							CurAmbigAlt2,
 | |
| 							CurAmbigbtype);
 | |
| 			exit(PCCTS_EXIT_FAILURE);
 | |
| 		}
 | |
| 		n += TreeBlockAllocSize;
 | |
| 		for (p=newblk; p<&(newblk[TreeBlockAllocSize]); p++)
 | |
| 		{
 | |
| 			p->right = FreeList;	/* add all new Tree nodes to Free List */
 | |
| 			FreeList = p;
 | |
| 		}
 | |
| 	}
 | |
| 	p = FreeList;
 | |
| 	FreeList = FreeList->right;		/* remove a tree node */
 | |
| 	p->right = NULL;				/* zero out ptrs */
 | |
| 	p->down = NULL;
 | |
| 	p->token = tok;
 | |
| 
 | |
|     TnodesAllocated++;                                      /* MR10 */
 | |
|     TnodesInUse++;                                          /* MR10 */
 | |
|     if (TnodesInUse > TnodesPeak) TnodesPeak=TnodesInUse;   /* MR10 */
 | |
| 
 | |
| #ifdef TREE_DEBUG
 | |
| 	require(!p->in_use, "tnode: node in use!");
 | |
| 	p->in_use = 1;
 | |
|     p->seq=TnodesAllocated;
 | |
|     set_orel( (unsigned) TnodesAllocated,&set_of_tnodes_in_use);
 | |
|     if (stop_on_tnode_seq_number == p->seq) {
 | |
|       fprintf(stderr,"\n*** just allocated tnode #%d ***\n",
 | |
|             stop_on_tnode_seq_number);
 | |
|     };
 | |
| #endif
 | |
| 	return p;
 | |
| }
 | |
| 
 | |
| static Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| eofnode( int k )
 | |
| #else
 | |
| eofnode( k )
 | |
| int k;
 | |
| #endif
 | |
| {
 | |
| 	Tree *t=NULL;
 | |
| 	int i;
 | |
| 
 | |
| 	for (i=1; i<=k; i++)
 | |
| 	{
 | |
| 		t = tmake(tnode((TokenInd!=NULL?TokenInd[EofToken]:EofToken)), t, NULL);
 | |
| 	}
 | |
| 	return t;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void
 | |
| #ifdef __USE_PROTOS
 | |
| _Tfree( Tree *t )
 | |
| #else
 | |
| _Tfree( t )
 | |
| Tree *t;
 | |
| #endif
 | |
| {
 | |
| 	if ( t!=NULL )
 | |
| 	{
 | |
| #ifdef TREE_DEBUG
 | |
|         if (t->seq == stop_on_tnode_seq_number) {
 | |
|            fprintf(stderr,"\n*** just freed tnode #%d ***\n",t->seq);
 | |
|         };
 | |
| 		require(t->in_use, "_Tfree: node not in use!");
 | |
| 		t->in_use = 0;
 | |
|         set_rm( (unsigned) t->seq,set_of_tnodes_in_use);
 | |
| #endif
 | |
| 		t->right = FreeList;
 | |
| 		FreeList = t;
 | |
|         TnodesInUse--;                   /* MR10 */
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* tree duplicate */
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tdup( Tree *t )
 | |
| #else
 | |
| tdup( t )
 | |
| Tree *t;
 | |
| #endif
 | |
| {
 | |
| 	Tree *u;
 | |
| 	
 | |
| 	if ( t == NULL ) return NULL;
 | |
| 	u = tnode(t->token);
 | |
| 	u->v.rk = t->v.rk;
 | |
| 	u->right = tdup(t->right);
 | |
| 	u->down = tdup(t->down);
 | |
| 	return u;
 | |
| }
 | |
| 
 | |
| /* tree duplicate (assume tree is a chain downwards) */
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tdup_chain( Tree *t )
 | |
| #else
 | |
| tdup_chain( t )
 | |
| Tree *t;
 | |
| #endif
 | |
| {
 | |
| 	Tree *u;
 | |
| 	
 | |
| 	if ( t == NULL ) return NULL;
 | |
| 	u = tnode(t->token);
 | |
| 	u->v.rk = t->v.rk;
 | |
| 	u->down = tdup(t->down);
 | |
| 	return u;
 | |
| }
 | |
| 
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tappend( Tree *t, Tree *u )
 | |
| #else
 | |
| tappend( t, u )
 | |
| Tree *t;
 | |
| Tree *u;
 | |
| #endif
 | |
| {
 | |
| 	Tree *w;
 | |
| 
 | |
| /*** fprintf(stderr, "tappend(");
 | |
|  *** preorder(t); fprintf(stderr, ",");
 | |
|  *** preorder(u); fprintf(stderr, " )\n");
 | |
| */
 | |
| 	if ( t == NULL ) return u;
 | |
| 	if ( t->token == ALT && t->right == NULL ) return tappend(t->down, u);
 | |
| 	for (w=t; w->right!=NULL; w=w->right) {;}
 | |
| 	w->right = u;
 | |
| 	return t;
 | |
| }
 | |
| 
 | |
| /* dealloc all nodes in a tree */
 | |
| void
 | |
| #ifdef __USE_PROTOS
 | |
| Tfree( Tree *t )
 | |
| #else
 | |
| Tfree( t )
 | |
| Tree *t;
 | |
| #endif
 | |
| {
 | |
| 	if ( t == NULL ) return;
 | |
| 	Tfree( t->down );
 | |
| 	Tfree( t->right );
 | |
| 	_Tfree( t );
 | |
| }
 | |
| 
 | |
| /* find all children (alts) of t that require remaining_k nodes to be LL_k
 | |
|  * tokens long.
 | |
|  *
 | |
|  * t-->o
 | |
|  *     |
 | |
|  *     a1--a2--...--an		<-- LL(1) tokens
 | |
|  *     |   |        |
 | |
|  *     b1  b2  ...  bn		<-- LL(2) tokens
 | |
|  *     |   |        |
 | |
|  *     .   .        .
 | |
|  *     .   .        .
 | |
|  *     z1  z2  ...  zn		<-- LL(LL_k) tokens
 | |
|  *
 | |
|  * We look for all [Ep] needing remaining_k nodes and replace with u.
 | |
|  * u is not destroyed or actually used by the tree (a copy is made).
 | |
|  */
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tlink( Tree *t, Tree *u, int remaining_k )
 | |
| #else
 | |
| tlink( t, u, remaining_k )
 | |
| Tree *t;
 | |
| Tree *u;
 | |
| int remaining_k;
 | |
| #endif
 | |
| {
 | |
| 	Tree *p;
 | |
| 	require(remaining_k!=0, "tlink: bad tree");
 | |
| 
 | |
| 	if ( t==NULL ) return NULL;
 | |
| 	/*fprintf(stderr, "tlink: u is:"); preorder(u); fprintf(stderr, "\n");*/
 | |
| 	if ( t->token == EpToken && t->v.rk == remaining_k )
 | |
| 	{
 | |
| 		require(t->down==NULL, "tlink: invalid tree");
 | |
| 		if ( u == NULL ) {
 | |
| /* MR10 */  Tree  *tt=t->right;
 | |
| /* MR10 */  _Tfree(t);
 | |
| /* MR10 */  return tt;
 | |
|         };
 | |
| 		p = tdup( u );
 | |
| 		p->right = t->right;
 | |
| 		_Tfree( t );
 | |
| 		return p;
 | |
| 	}
 | |
| 	t->down = tlink(t->down, u, remaining_k);
 | |
| 	t->right = tlink(t->right, u, remaining_k);
 | |
| 	return t;
 | |
| }
 | |
| 
 | |
| /* remove as many ALT nodes as possible while still maintaining semantics */
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tshrink( Tree *t )
 | |
| #else
 | |
| tshrink( t )
 | |
| Tree *t;
 | |
| #endif
 | |
| {
 | |
| 	if ( t == NULL ) return NULL;
 | |
| 	t->down = tshrink( t->down );
 | |
| 	t->right = tshrink( t->right );
 | |
| 	if ( t->down == NULL )
 | |
| 	{
 | |
| 		if ( t->token == ALT )
 | |
| 		{
 | |
| 			Tree *u = t->right;
 | |
| 			_Tfree(t);
 | |
| 			return u;			/* remove useless alts */
 | |
| 		}
 | |
| 		return t;
 | |
| 	}
 | |
| 
 | |
| 	/* (? (ALT (? ...)) s) ==> (? (? ...) s) where s = sibling, ? = match any */
 | |
| 	if ( t->token == ALT && t->down->right == NULL)
 | |
| 	{
 | |
| 		Tree *u = t->down;
 | |
| 		u->right = t->right;
 | |
| 		_Tfree( t );
 | |
| 		return u;
 | |
| 	}
 | |
| 	/* (? (A (ALT t)) s) ==> (? (A t) s) where A is a token; s,t siblings */
 | |
| 	if ( t->token != ALT && t->down->token == ALT && t->down->right == NULL )
 | |
| 	{
 | |
| 		Tree *u = t->down->down;
 | |
| 		_Tfree( t->down );
 | |
| 		t->down = u;
 | |
| 		return t;
 | |
| 	}
 | |
| 	return t;
 | |
| }
 | |
| 
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tflatten( Tree *t )
 | |
| #else
 | |
| tflatten( t )
 | |
| Tree *t;
 | |
| #endif
 | |
| {
 | |
| 	if ( t == NULL ) return NULL;
 | |
| 	t->down = tflatten( t->down );
 | |
| 	t->right = tflatten( t->right );
 | |
| 	if ( t->down == NULL ) return t;
 | |
| 	
 | |
| 	if ( t->token == ALT )
 | |
| 	{
 | |
| 		Tree *u;
 | |
| 		/* find tail of children */
 | |
| 		for (u=t->down; u->right!=NULL; u=u->right) {;}
 | |
| 		u->right = t->right;
 | |
| 		u = t->down;
 | |
| 		_Tfree( t );
 | |
| 		return u;
 | |
| 	}
 | |
| 	return t;
 | |
| }
 | |
| 
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tJunc( Junction *p, int k, set *rk )
 | |
| #else
 | |
| tJunc( p, k, rk )
 | |
| Junction *p;
 | |
| int k;
 | |
| set *rk;
 | |
| #endif
 | |
| {
 | |
| 	Tree *t=NULL, *u=NULL;
 | |
| 	Junction *alt;
 | |
| 	Tree *tail=NULL, *r;
 | |
| 
 | |
| #ifdef DBG_TRAV
 | |
| 	fprintf(stderr, "tJunc(%d): %s in rule %s\n", k,
 | |
| 			decodeJType[p->jtype], ((Junction *)p)->rname);
 | |
| #endif
 | |
| 
 | |
| /* MR14 */    if (AlphaBetaTrace && p->alpha_beta_guess_end) {
 | |
| /* MR14 */         warnFL(
 | |
| /* MR14 */           "not possible to compute follow set for alpha in an \"(alpha)? beta\" block.  ",
 | |
| /* MR14 */                 FileStr[p->file],p->line);
 | |
| /* MR14 */         MR_alphaBetaTraceReport();
 | |
| /* MR14 */    };
 | |
| 
 | |
| /* MR14 */    if (p->alpha_beta_guess_end) {
 | |
| /* MR14 */      return NULL;
 | |
| /* MR14 */    }
 | |
| 
 | |
| 	if ( p->jtype==aLoopBlk || p->jtype==RuleBlk ||
 | |
| 		 p->jtype==aPlusBlk || p->jtype==aSubBlk || p->jtype==aOptBlk )
 | |
| 	{
 | |
| 		if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) {
 | |
| 			require(p->lock!=NULL, "rJunc: lock array is NULL");
 | |
| 			if ( p->lock[k] ) return NULL;
 | |
| 			p->lock[k] = TRUE;
 | |
| 		}
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);
 | |
| /* MR10 */    };
 | |
| 
 | |
| 		TRAV(p->p1, k, rk, tail);
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);
 | |
| /* MR10 */    };
 | |
| 
 | |
| 		if ( p->jtype==RuleBlk ) {p->lock[k] = FALSE; return tail;}
 | |
| 		r = tmake(tnode(ALT), tail, NULL);
 | |
| 		for (alt=(Junction *)p->p2; alt!=NULL; alt = (Junction *)alt->p2)
 | |
| 		{
 | |
| 			/* if this is one of the added optional alts for (...)+ then break */
 | |
| 			if ( alt->ignore ) break;
 | |
| 
 | |
| 			if ( tail==NULL ) {TRAV(alt->p1, k, rk, tail); r->down = tail;}
 | |
| 			else
 | |
| 			{
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);
 | |
| /* MR10 */    };
 | |
| 
 | |
| 				TRAV(alt->p1, k, rk, tail->right);
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);
 | |
| /* MR10 */    };
 | |
| 				if ( tail->right != NULL ) tail = tail->right;
 | |
| 			}
 | |
| 		}
 | |
| 		if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) p->lock[k] = FALSE;
 | |
| #ifdef DBG_TREES
 | |
| 		fprintf(stderr, "blk(%s) returns:",((Junction *)p)->rname); preorder(r); fprintf(stderr, "\n");
 | |
| #endif
 | |
| 		if ( r->down == NULL ) {_Tfree(r); return NULL;}
 | |
| 		return r;
 | |
| 	}
 | |
| 
 | |
| 	if ( p->jtype==EndRule )
 | |
| 	{
 | |
| 		if ( p->halt )						/* don't want FOLLOW here? */
 | |
| 		{
 | |
| /****		if ( ContextGuardTRAV ) return NULL; ****/
 | |
| 			set_orel( (unsigned) k, rk);	/* indicate this k value needed */ /* MR10 cast */
 | |
| 			t = tnode(EpToken);
 | |
| 			t->v.rk = k;
 | |
| 			return t;
 | |
| 		}
 | |
| 		require(p->lock!=NULL, "rJunc: lock array is NULL");
 | |
| 		if ( p->lock[k] ) return NULL;
 | |
| 		/* if no FOLLOW assume k EOF's */
 | |
| 		if ( p->p1 == NULL ) return eofnode(k);
 | |
| 		p->lock[k] = TRUE;
 | |
| 	}
 | |
| 
 | |
| /* MR14 */	if (p->p1 != NULL && p->guess &&  p->guess_analysis_point == NULL) {
 | |
| /* MR14 */    Node * guess_point;
 | |
| /* MR14 */    guess_point=(Node *)analysis_point(p);
 | |
| /* MR14 */    if (guess_point == (Node *)p) {
 | |
| /* MR14 */      guess_point=p->p1;
 | |
| /* MR14 */    }
 | |
| /* MR14 */    p->guess_analysis_point=guess_point;
 | |
| /* MR14 */  }	
 | |
| 
 | |
| 	if ( p->p2 == NULL )
 | |
| 	{
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);
 | |
| /* MR10 */    };
 | |
| 
 | |
| /* M14 */        if (p->guess_analysis_point != NULL) {
 | |
| /* M14 */ 		   TRAV(p->guess_analysis_point, k, rk,t);
 | |
| /* M14 */        } else {
 | |
|         		   TRAV(p->p1, k, rk,t);
 | |
| /* M14 */        }
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);
 | |
| /* MR10 */    };
 | |
| 
 | |
| 		if ( p->jtype==EndRule ) p->lock[k]=FALSE;
 | |
| 		return t;
 | |
| 	}
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p);
 | |
| /* MR10 */    };
 | |
| 
 | |
| /* M14 */        if (p->guess_analysis_point != NULL) {
 | |
| /* M14 */ 		   TRAV(p->guess_analysis_point, k, rk,t);
 | |
| /* M14 */        } else {
 | |
|         		   TRAV(p->p1, k, rk,t);
 | |
| /* M14 */        }
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack);
 | |
| /* MR10 */    };
 | |
| 
 | |
| 	if ( p->jtype!=RuleBlk && /* MR14 */ !p->guess) TRAV(p->p2, k, rk, u);
 | |
| 
 | |
| 	if ( p->jtype==EndRule ) p->lock[k] = FALSE;/* unlock node */
 | |
| 
 | |
| 	if ( t==NULL ) return tmake(tnode(ALT), u, NULL);
 | |
| 	return tmake(tnode(ALT), t, u, NULL);
 | |
| }
 | |
| 
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tRuleRef( RuleRefNode *p, int k, set *rk_out )
 | |
| #else
 | |
| tRuleRef( p, k, rk_out )
 | |
| RuleRefNode *p;
 | |
| int k;
 | |
| set *rk_out;
 | |
| #endif
 | |
| {
 | |
| 	int k2;
 | |
| 	Tree *t=NULL, *u=NULL;
 | |
| 	Junction *r;
 | |
| 	set rk, rk2;
 | |
| 	int save_halt;
 | |
| 	RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text);
 | |
| 	
 | |
| #ifdef DBG_TRAV
 | |
| 	fprintf(stderr, "tRuleRef: %s\n", p->text);
 | |
| #endif
 | |
| 	if ( q == NULL )
 | |
| 	{
 | |
| 		TRAV(p->next, k, rk_out, t);/* ignore undefined rules */
 | |
| 		return t;
 | |
| 	}
 | |
| 	rk = rk2 = empty;
 | |
|     if (RulePtr == NULL) fatal("RulePtr==NULL");
 | |
| 	r = RulePtr[q->rulenum];
 | |
| 	if ( r->lock[k] ) return NULL;
 | |
| 	save_halt = r->end->halt;
 | |
| 	r->end->halt = TRUE;		/* don't let reach fall off end of rule here */
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      MR_pointerStackPush(&MR_BackTraceStack,p);
 | |
| /* MR10 */    };
 | |
| 
 | |
| 	TRAV(r, k, &rk, t);
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      MR_pointerStackPop(&MR_BackTraceStack);
 | |
| /* MR10 */    };
 | |
| 
 | |
| 	r->end->halt = save_halt;
 | |
| #ifdef DBG_TREES
 | |
| 	fprintf(stderr, "after ruleref, t is:"); preorder(t); fprintf(stderr, "\n");
 | |
| #endif
 | |
| 	t = tshrink( t );
 | |
| 	while ( !set_nil(rk) ) {	/* any k left to do? if so, link onto tree */
 | |
| 		k2 = set_int(rk);
 | |
| 		set_rm(k2, rk);
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      MR_pointerStackPush(&MR_BackTraceStack,p);
 | |
| /* MR10 */    };
 | |
| 
 | |
| 		TRAV(p->next, k2, &rk2, u);
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      MR_pointerStackPop(&MR_BackTraceStack);
 | |
| /* MR10 */    };
 | |
| 
 | |
| 		t = tlink(t, u, k2);	/* any alts missing k2 toks, add u onto end */
 | |
|         Tfree(u);               /* MR10 */
 | |
| 	}
 | |
| 	set_free(rk);				/* rk is empty, but free it's memory */
 | |
| 	set_orin(rk_out, rk2);		/* remember what we couldn't do */
 | |
| 	set_free(rk2);
 | |
| 	return t;
 | |
| }
 | |
| 
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tToken( TokNode *p, int k, set *rk )
 | |
| #else
 | |
| tToken( p, k, rk )
 | |
| TokNode *p;
 | |
| int k;
 | |
| set *rk;
 | |
| #endif
 | |
| {
 | |
| 	Tree *t=NULL, *tset=NULL, *u;
 | |
| 
 | |
| 	if (ConstrainSearch) {
 | |
|       if (MR_AmbSourceSearch) {
 | |
| 		require(constrain>=fset&&constrain<=&(fset[CLL_k]),"tToken: constrain is not a valid set");
 | |
|       } else {
 | |
| 		require(constrain>=fset&&constrain<=&(fset[LL_k]),"tToken: constrain is not a valid set");
 | |
|       };
 | |
|       constrain = &fset[maxk-k+1];
 | |
| 	}
 | |
| 
 | |
| #ifdef DBG_TRAV
 | |
|         	fprintf(stderr, "tToken(%d): %s\n", k, TerminalString(p->token));
 | |
|         	if ( ConstrainSearch ) {
 | |
|         		fprintf(stderr, "constrain is:"); s_fprT(stderr, *constrain); fprintf(stderr, "\n");
 | |
|         	}
 | |
| #endif
 | |
| 
 | |
| 	/* is it a meta token (set of tokens)? */
 | |
| 
 | |
| 	if ( !set_nil(p->tset) )
 | |
| 	{
 | |
| 		unsigned e=0;
 | |
| 		set a;
 | |
| 		Tree *n, *tail = NULL;
 | |
| 
 | |
| 		if ( ConstrainSearch ) {
 | |
|           a = set_and(p->tset, *constrain);
 | |
|           if (set_nil(a)) {         /* MR10 */
 | |
|             set_free(a);            /* MR11 */
 | |
|             return NULL;            /* MR10 */
 | |
|           };                        /* MR10 */
 | |
| 		} else {
 | |
|           a = set_dup(p->tset);
 | |
|         };
 | |
| 
 | |
| 		for (; !set_nil(a); set_rm(e, a))
 | |
| 		{
 | |
| 			e = set_int(a);
 | |
| 			n = tnode(e);
 | |
| 			if ( tset==NULL ) { tset = n; tail = n; }
 | |
| 			else { tail->right = n; tail = n; }
 | |
| 		}
 | |
| 		set_free( a );
 | |
| 	}
 | |
| 	else if ( ConstrainSearch && !set_el(p->token, *constrain) )
 | |
|     {
 | |
| /*      fprintf(stderr, "ignoring token %s(%d)\n", TerminalString(p->token),
 | |
|                 k);*/
 | |
|         return NULL;
 | |
|     }
 | |
| 	else {
 | |
|         tset = tnode( p->token );
 | |
|     };
 | |
| 
 | |
| /* MR10 */    if (MR_MaintainBackTrace) {
 | |
| /* MR10 */      if (k == 1) {
 | |
| /* MR10 */        MR_pointerStackPush(&MR_BackTraceStack,p);
 | |
| /* MR13 */        if (MR_SuppressSearch) {
 | |
| /* MR13 */          MR_suppressSearchReport();
 | |
| /* MR13 */        } else {
 | |
| /* MR10 */          MR_backTraceReport();
 | |
| /* MR13 */        };
 | |
| /* MR10 */        MR_pointerStackPop(&MR_BackTraceStack);
 | |
| /* MR11 */        Tfree(tset);
 | |
| /* MR11 */        return NULL;
 | |
| /* MR10 */      };
 | |
| /* MR10 */    };
 | |
| 
 | |
| 	if ( k == 1 ) return tset;
 | |
| 
 | |
|     if (MR_MaintainBackTrace) {
 | |
|       MR_pointerStackPush(&MR_BackTraceStack,p);
 | |
|     };
 | |
| 
 | |
| 	TRAV(p->next, k-1, rk, t);
 | |
| 
 | |
|     if (MR_MaintainBackTrace) {
 | |
|       Tfree(t);
 | |
|       Tfree(tset);
 | |
|       MR_pointerStackPop(&MR_BackTraceStack);
 | |
|       return NULL;
 | |
|     };
 | |
| 
 | |
| 	/* here, we are positive that, at least, this tree will not contribute
 | |
| 	 * to the LL(2) tree since it will be too shallow, IF t==NULL.
 | |
| 	 * If doing a context guard walk, then don't prune.
 | |
| 	 */
 | |
| 	if ( t == NULL && !ContextGuardTRAV )	/* tree will be too shallow */
 | |
| 	{
 | |
| 		if ( tset!=NULL ) Tfree( tset );
 | |
| 		return NULL;
 | |
| 	}
 | |
| #ifdef DBG_TREES
 | |
| 	fprintf(stderr, "tToken(%d)->next:",k); preorder(t); fprintf(stderr, "\n");
 | |
| #endif
 | |
| 
 | |
| 	/* if single token root, then just make new tree and return */
 | |
|     /* MR10 - set_nil(p->tset) isn't a good test because of ConstraintSearch */
 | |
| 
 | |
| 	if (tset->right == NULL) return tmake(tset, t, NULL);    /* MR10 */
 | |
| 
 | |
| 	/* here we must make a copy of t as a child of each element of the tset;
 | |
| 	 * e.g., "T1..T3 A" would yield ( nil ( T1 A ) ( T2 A ) ( T3 A ) )
 | |
| 	 */
 | |
| 	for (u=tset; u!=NULL; u=u->right)
 | |
| 	{
 | |
| 		/* make a copy of t and hook it onto bottom of u */
 | |
| 		u->down = tdup(t);
 | |
| 	}
 | |
| 	Tfree( t );
 | |
| #ifdef DBG_TREES
 | |
| 	fprintf(stderr, "range is:"); preorder(tset); fprintf(stderr, "\n");
 | |
| #endif
 | |
| 	return tset;
 | |
| }
 | |
| 
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tAction( ActionNode *p, int k, set *rk )
 | |
| #else
 | |
| tAction( p, k, rk )
 | |
| ActionNode *p;
 | |
| int k;
 | |
| set *rk;
 | |
| #endif
 | |
| {
 | |
| 	Tree        *t=NULL;
 | |
|     set         *save_fset=NULL;
 | |
|     int         i;
 | |
| 
 | |
| 	/* fprintf(stderr, "tAction\n"); */
 | |
| 
 | |
| /*  An MR_SuppressSearch is looking for things that can be
 | |
|       reached even when the predicate is false.
 | |
| 
 | |
|     There are three kinds of predicates:
 | |
|         plain:              r1: <<p>>? r2
 | |
|         guarded:            r1: (A)? => <<p>>? r2
 | |
|         ampersand style:    r1: (A)? && <<p>>? r2
 | |
| 
 | |
|     Of the three kinds of predicates, only a guard predicate
 | |
|       has things which are reachable even when the predicate
 | |
|       is false.  To be reachable the constraint must *not*
 | |
|       match the guard.
 | |
| 
 | |
| */
 | |
| 
 | |
|     if (p->is_predicate && MR_SuppressSearch) {
 | |
| 
 | |
|       Predicate     *pred=p->guardpred;
 | |
| 
 | |
|       if (pred == NULL) {
 | |
|         t=NULL;
 | |
|         goto EXIT;
 | |
|       };
 | |
|       constrain = &fset[maxk-k+1];
 | |
|       if (pred->k == 1) {
 | |
|         set     dif;
 | |
|         dif=set_dif(*constrain,pred->scontext[1]);
 | |
|         if (set_nil(dif)) {
 | |
|           set_free(dif);
 | |
|           t=NULL;
 | |
|           goto EXIT;
 | |
|         };
 | |
|         set_free(dif);
 | |
|       } else {
 | |
|         if (MR_tree_matches_constraints(k,constrain,pred->tcontext)) {
 | |
|           t=NULL;
 | |
|           goto EXIT;
 | |
|         };
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     /* The ampersand predicate differs from the
 | |
|          other predicates because its first set
 | |
|          is a subset of the first set behind the predicate
 | |
| 
 | |
|             r1: (A)? && <<p>>? r2 ;
 | |
|             r2: A | B;
 | |
| 
 | |
|        In this case first[1] of r1 is A, even
 | |
|          though first[1] of r2 is {A B}.
 | |
|     */
 | |
| 
 | |
|     if (p->is_predicate && p->ampersandPred != NULL) {
 | |
| 
 | |
|       Predicate     *pred=p->ampersandPred;
 | |
|       Tree          *tAND;
 | |
|       Tree          *tset;
 | |
| 
 | |
|       if (k <= pred->k) {
 | |
|         if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p);
 | |
|         TRAV(p->guardNodes,k,rk,t);
 | |
|         if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack);
 | |
|         return t;
 | |
|       } else {
 | |
|         require (k>1,"tAction for ampersandpred: k <= 1");
 | |
|         if (ConstrainSearch) {
 | |
|           if (MR_AmbSourceSearch) {
 | |
|     		require(constrain>=fset&&constrain<=&(fset[CLL_k]),
 | |
|                                 "tToken: constrain is not a valid set");
 | |
|           } else {
 | |
|     		require(constrain>=fset&&constrain<=&(fset[LL_k]),
 | |
|                                 "tToken: constrain is not a valid set");
 | |
|           };
 | |
|           save_fset=(set *) calloc (CLL_k+1,sizeof(set));
 | |
|           require (save_fset != NULL,"tAction save_fset alloc");
 | |
|           for (i=1; i <= CLL_k ; i++) {
 | |
|             save_fset[i]=set_dup(fset[i]);
 | |
|           };
 | |
|           if (pred->k == 1) {
 | |
|             constrain = &fset[maxk-k+1];
 | |
|             set_andin(constrain,pred->scontext[1]);
 | |
|             if (set_nil(*constrain)) {
 | |
|               t=NULL;
 | |
|               goto EXIT;
 | |
|             };
 | |
|           } else {
 | |
|             constrain = &fset[maxk-k+1];
 | |
|             if (! MR_tree_matches_constraints(pred->k,constrain,pred->tcontext)) {
 | |
|                t=NULL;
 | |
|                goto EXIT;
 | |
|             };  /* end loop on i          */
 | |
|           }; /* end loop on pred scontext/tcontext */
 | |
|         }; /* end if on k > pred->k     */
 | |
|       }; /* end if on constrain search  */
 | |
| 
 | |
|       TRAV(p->next,k,rk,t);
 | |
| 
 | |
|       if (t != NULL) {
 | |
|         t=tshrink(t);
 | |
|         t=tflatten(t);
 | |
|         t=tleft_factor(t);
 | |
|         if (pred->tcontext != NULL) {
 | |
|           tAND=MR_computeTreeAND(t,pred->tcontext);
 | |
|         } else {
 | |
|           tset=MR_make_tree_from_set(pred->scontext[1]);
 | |
|           tAND=MR_computeTreeAND(t,tset);
 | |
|           Tfree(tset);
 | |
|         };
 | |
|         Tfree(t);
 | |
|         t=tAND;
 | |
|       };
 | |
|       goto EXIT;
 | |
| 
 | |
|     }; /* end if on ampersand predicate */
 | |
| 
 | |
|     TRAV(p->next,k,rk,t);
 | |
| 
 | |
| EXIT:
 | |
|     if (save_fset != NULL) {
 | |
|       for (i=1 ; i <= CLL_k ; i++) {
 | |
|         set_free(fset[i]);
 | |
|         fset[i]=save_fset[i];
 | |
|       };
 | |
|       free ( (char *) save_fset);
 | |
|     };
 | |
| 	return t;
 | |
| }
 | |
| 
 | |
| /* see if e exists in s as a possible input permutation (e is always a chain) */
 | |
| 
 | |
| int
 | |
| #ifdef __USE_PROTOS
 | |
| tmember( Tree *e, Tree *s )
 | |
| #else
 | |
| tmember( e, s )
 | |
| Tree *e;
 | |
| Tree *s;
 | |
| #endif
 | |
| {
 | |
| 	if ( e==NULL||s==NULL ) return 0;
 | |
| /** fprintf(stderr, "tmember(");
 | |
| ***	preorder(e); fprintf(stderr, ",");
 | |
| ***	preorder(s); fprintf(stderr, " )\n");
 | |
| */
 | |
| 	if ( s->token == ALT && s->right == NULL ) return tmember(e, s->down);
 | |
| 	if ( e->token!=s->token )
 | |
| 	{
 | |
| 		if ( s->right==NULL ) return 0;
 | |
| 		return tmember(e, s->right);
 | |
| 	}
 | |
| 	if ( e->down==NULL && s->down == NULL ) return 1;
 | |
| 	if ( tmember(e->down, s->down) ) return 1;
 | |
| 	if ( s->right==NULL ) return 0;
 | |
| 	return tmember(e, s->right);
 | |
| }
 | |
| 
 | |
| /* see if e exists in s as a possible input permutation (e is always a chain);
 | |
|  * Only check s to the depth of e.  In other words, 'e' can be a shorter
 | |
|  * sequence than s.
 | |
|  */
 | |
| int
 | |
| #ifdef __USE_PROTOS
 | |
| tmember_constrained( Tree *e, Tree *s)
 | |
| #else
 | |
| tmember_constrained( e, s )
 | |
| Tree *e;
 | |
| Tree *s;
 | |
| #endif
 | |
| {
 | |
| 	if ( e==NULL||s==NULL ) return 0;
 | |
| /**	fprintf(stderr, "tmember_constrained(");
 | |
| ***	preorder(e); fprintf(stderr, ",");
 | |
| ***	preorder(s); fprintf(stderr, " )\n");
 | |
| **/
 | |
| 	if ( s->token == ALT && s->right == NULL )
 | |
| 		return tmember_constrained(e, s->down);
 | |
| 	if ( e->token!=s->token )
 | |
| 	{
 | |
| 		if ( s->right==NULL ) return 0;
 | |
| 		return tmember_constrained(e, s->right);
 | |
| 	}
 | |
| 	if ( e->down == NULL ) return 1; /* if s is matched to depth of e return */
 | |
| 	if ( tmember_constrained(e->down, s->down) ) return 1;
 | |
| 	if ( s->right==NULL ) return 0;
 | |
| 	return tmember_constrained(e, s->right);
 | |
| }
 | |
| 
 | |
| /* combine (? (A t) ... (A u) ...) into (? (A t u)) */
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| tleft_factor( Tree *t )
 | |
| #else
 | |
| tleft_factor( t )
 | |
| Tree *t;
 | |
| #endif
 | |
| {
 | |
| 	Tree *u, *v, *trail, *w;
 | |
| 
 | |
| 	/* left-factor what is at this level */
 | |
| 	if ( t == NULL ) return NULL;
 | |
| 	for (u=t; u!=NULL; u=u->right)
 | |
| 	{
 | |
| 		trail = u;
 | |
| 		v=u->right;
 | |
| 		while ( v!=NULL )
 | |
| 		{
 | |
| 			if ( u->token == v->token )
 | |
| 			{
 | |
| 				if ( u->down!=NULL )
 | |
| 				{
 | |
| 					for (w=u->down; w->right!=NULL; w=w->right) {;}
 | |
| 					w->right = v->down;	/* link children together */
 | |
| 				}
 | |
| 				else u->down = v->down;
 | |
| 				trail->right = v->right;		/* unlink factored node */
 | |
| 				_Tfree( v );
 | |
| 				v = trail->right;
 | |
| 			}
 | |
| 			else {trail = v; v=v->right;}
 | |
| 		}
 | |
| 	}
 | |
| 	/* left-factor what is below */
 | |
| 	for (u=t; u!=NULL; u=u->right) u->down = tleft_factor( u->down );
 | |
| 	return t;
 | |
| }
 | |
| 
 | |
| /* remove the permutation p from t if present */
 | |
| Tree *
 | |
| #ifdef __USE_PROTOS
 | |
| trm_perm( Tree *t, Tree *p )
 | |
| #else
 | |
| trm_perm( t, p )
 | |
| Tree *t;
 | |
| Tree *p;
 | |
| #endif
 | |
| {
 | |
| 	/*
 | |
| 	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 );
 | |
| 		t = tleft_factor( t );
 | |
|         Tfree(pred->tcontext);
 | |
| 		pred->tcontext = t;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		REACH(p, 1, &rk, scontext);
 | |
| 		require(set_nil(rk), "rk != nil");
 | |
| 		set_free(rk);
 | |
|         set_free(pred->scontext[1]);
 | |
| 		pred->scontext[1] = scontext;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* MR11 - had enough of flags yet ? */
 | |
| 
 | |
| int     MR_AmbSourceSearch=0;
 | |
| int     MR_AmbSourceSearchGroup=0;
 | |
| int     MR_AmbSourceSearchChoice=0;
 | |
| int     MR_AmbSourceSearchLimit=0;
 | |
| int     MR_matched_AmbAidRule=0;
 | |
| 
 | |
| static    set         *matchSets[2]={NULL,NULL};
 | |
| static    int         *tokensInChain=NULL;
 | |
| static    Junction    *MR_AmbSourceSearchJ[2];
 | |
| 
 | |
| void MR_traceAmbSourceKclient()
 | |
| {
 | |
|   int       i;
 | |
|   set       *save_fset;
 | |
|   int       save_ConstrainSearch;
 | |
|   set       incomplete;
 | |
|   Tree      *t;
 | |
| 
 | |
|   if (matchSets[0] == NULL) {
 | |
|     matchSets[0]=(set *) calloc (CLL_k+1,sizeof(set));
 | |
|     require (matchSets[0] != NULL,"matchSets[0] alloc");
 | |
|     matchSets[1]=(set *) calloc (CLL_k+1,sizeof(set));
 | |
|     require (matchSets[1] != NULL,"matchSets[1] alloc");
 | |
|   };
 | |
| 
 | |
|   for (i=1 ; i <= MR_AmbSourceSearchLimit ; i++) {
 | |
|     set_clr(matchSets[0][i]);
 | |
|     set_orel( (unsigned) tokensInChain[i],
 | |
|                               &matchSets[0][i]);
 | |
|     set_clr(matchSets[1][i]);
 | |
|     set_orel( (unsigned) tokensInChain[i],
 | |
|                               &matchSets[1][i]);
 | |
|   };
 | |
| 
 | |
|   save_fset=fset;
 | |
|   save_ConstrainSearch=ConstrainSearch;
 | |
| 
 | |
| 
 | |
| 
 | |
|   for (i=0 ; i < 2 ; i++) {
 | |
| 
 | |
| #if 0
 | |
| **    fprintf(stdout,"  Choice:%d  Depth:%d  ",i+1,MR_AmbSourceSearchLimit);
 | |
| **    fprintf(stdout,"(");
 | |
| **    for (j=1 ; j <= MR_AmbSourceSearchLimit ; j++) {
 | |
| **      if (j != 1) fprintf(stdout," ");
 | |
| **      fprintf(stdout,"%s",TerminalString(tokensInChain[j]));
 | |
| **    };
 | |
| **    fprintf(stdout,")\n\n");
 | |
| #endif
 | |
| 
 | |
|     fset=matchSets[i];
 | |
| 
 | |
|     MR_AmbSourceSearch=1;
 | |
|     MR_MaintainBackTrace=1;
 | |
|     MR_AmbSourceSearchChoice=i;
 | |
|     ConstrainSearch=1;
 | |
| 
 | |
|     maxk = MR_AmbSourceSearchLimit;
 | |
| 
 | |
|     incomplete=empty;
 | |
|     t=NULL;
 | |
| 
 | |
|     constrain = &(fset[1]);
 | |
|     MR_pointerStackReset(&MR_BackTraceStack);
 | |
| 
 | |
|     TRAV(MR_AmbSourceSearchJ[i],maxk,&incomplete,t);
 | |
| 
 | |
|     Tfree(t);
 | |
| 
 | |
|     require (set_nil(incomplete),"MR_traceAmbSourceK TRAV incomplete");
 | |
|     require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0");
 | |
| 
 | |
|     set_free(incomplete);
 | |
|   };
 | |
| 
 | |
|   ConstrainSearch=save_ConstrainSearch;
 | |
|   fset=save_fset;
 | |
|   MR_AmbSourceSearch=0;
 | |
|   MR_MaintainBackTrace=0;
 | |
|   MR_AmbSourceSearchChoice=0;
 | |
| }
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| Tree *tTrunc(Tree *t,int depth)
 | |
| #else
 | |
| Tree *tTrunc(t,depth)
 | |
|   Tree  *t;
 | |
| #endif
 | |
| {
 | |
|     Tree    *u;
 | |
| 
 | |
|     require ( ! (t == NULL && depth > 0),"tree too short");
 | |
| 
 | |
|     if (depth == 0) return NULL;
 | |
| 
 | |
|     if (t->token == ALT) {
 | |
|       u=tTrunc(t->down,depth);
 | |
|     } else {
 | |
|       u=tnode(t->token);
 | |
|       u->down=tTrunc(t->down,depth-1);
 | |
|     };
 | |
|     if (t->right != NULL) u->right=tTrunc(t->right,depth);
 | |
|     return u;
 | |
| }
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| void MR_iterateOverTree(Tree *t,int chain[])
 | |
| #else
 | |
| void MR_iterateOverTree(t,chain)
 | |
|   Tree          *t;
 | |
|   int           chain[];
 | |
| #endif
 | |
| {
 | |
|   if (t == NULL) return;
 | |
|   chain[0]=t->token;
 | |
|   if (t->down != NULL) {
 | |
|     MR_iterateOverTree(t->down,&chain[1]);
 | |
|   } else {
 | |
|     MR_traceAmbSourceKclient();
 | |
|   };
 | |
|   MR_iterateOverTree(t->right,&chain[0]);
 | |
|   chain[0]=0;
 | |
| }
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| void MR_traceAmbSourceK(Tree *t,Junction *alt1,Junction *alt2)
 | |
| #else
 | |
| void MR_traceAmbSourceK(t,alt1,alt2)
 | |
|   Tree      *t;
 | |
|   Junction  *alt1;
 | |
|   Junction  *alt2;
 | |
| #endif
 | |
| {
 | |
|     int         i;
 | |
|     int         depth;
 | |
|     int         maxDepth;
 | |
|     Tree        *truncatedTree;
 | |
| 
 | |
|     if (MR_AmbAidRule == NULL) return;
 | |
| 
 | |
|     if ( ! (
 | |
|             strcmp(MR_AmbAidRule,alt1->rname) == 0 ||
 | |
|             strcmp(MR_AmbAidRule,alt2->rname) == 0 ||
 | |
|             MR_AmbAidLine==alt1->line ||
 | |
|             MR_AmbAidLine==alt2->line
 | |
|            )
 | |
|        ) return;
 | |
| 
 | |
|     MR_matched_AmbAidRule++;
 | |
| 
 | |
|     /* there are no token sets in trees, only in TokNodes */
 | |
| 
 | |
|     MR_AmbSourceSearchJ[0]=analysis_point( (Junction *) alt1->p1);
 | |
|     MR_AmbSourceSearchJ[1]=analysis_point( (Junction *) alt2->p1);
 | |
| 
 | |
|     if (tokensInChain == NULL) {
 | |
|       tokensInChain=(int *) calloc (CLL_k+1,sizeof(int));
 | |
|       require (tokensInChain != NULL,"tokensInChain alloc");
 | |
|     };
 | |
| 
 | |
|     MR_AmbSourceSearchGroup=0;
 | |
| 
 | |
|     fprintf(stdout,"\n");
 | |
|     fprintf(stdout,"  Ambiguity Aid                 ");
 | |
|     fprintf(stdout,
 | |
|                 (MR_AmbAidDepth <= LL_k ?
 | |
|                     "(-k %d  -aa %s  %s  -aad %d)\n\n" :
 | |
|                         "(-k %d  -aa %s  %s  [-k value limits -aad %d])\n\n"),
 | |
|                 LL_k,
 | |
|                 MR_AmbAidRule,
 | |
|                 (MR_AmbAidMultiple ? "-aam" : ""),
 | |
|                 MR_AmbAidDepth);
 | |
| 
 | |
|     for (i=0 ; i < 2 ; i++) {
 | |
|       fprintf(stdout,"    Choice %d: %-25s  line %d  file %s\n",
 | |
|                   (i+1),
 | |
|                   MR_ruleNamePlusOffset( (Node *) MR_AmbSourceSearchJ[i]),
 | |
|                   MR_AmbSourceSearchJ[i]->line,
 | |
|                   FileStr[MR_AmbSourceSearchJ[i]->file]);
 | |
|     };
 | |
| 
 | |
|     fprintf(stdout,"\n");
 | |
| 
 | |
|     if (MR_AmbAidDepth < LL_k) {
 | |
|       maxDepth=MR_AmbAidDepth;
 | |
|     } else {
 | |
|       maxDepth=LL_k;
 | |
|     };
 | |
| 
 | |
|     for (depth=1 ; depth <= maxDepth; depth++) {
 | |
|       MR_AmbSourceSearchLimit=depth;
 | |
|       if (depth < LL_k) {
 | |
|         truncatedTree=tTrunc(t,depth);
 | |
|         truncatedTree=tleft_factor(truncatedTree);
 | |
|         MR_iterateOverTree(truncatedTree,&tokensInChain[1]);    /* <===== */
 | |
|         Tfree(truncatedTree);
 | |
|       } else {
 | |
|         MR_iterateOverTree(t,tokensInChain);                /* <===== */
 | |
|       };
 | |
|       fflush(stdout);
 | |
|       fflush(stderr);
 | |
|     };
 | |
| 
 | |
|     fprintf(stdout,"\n");
 | |
|     MR_AmbSourceSearch=0;
 | |
|     MR_MaintainBackTrace=0;
 | |
|     MR_AmbSourceSearchGroup=0;
 | |
|     MR_AmbSourceSearchChoice=0;
 | |
|     MR_AmbSourceSearchLimit=0;
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| /* this if for k=1 grammars only
 | |
| 
 | |
|    this is approximate only because of the limitations of linear
 | |
|    approximation lookahead.  Don't want to do a k=3 search when
 | |
|    the user only specified a ck=3 grammar
 | |
| */
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| void MR_traceAmbSource(set *matchSets,Junction *alt1, Junction *alt2)
 | |
| #else
 | |
| void MR_traceAmbSource(matchSets,alt1,alt2)
 | |
|   set       *matchSets;
 | |
|   Junction  *alt1;
 | |
|   Junction  *alt2;
 | |
| #endif
 | |
| {
 | |
|     set         *save_fset;
 | |
|     Junction    *p[2];
 | |
|     int         i;
 | |
|     int         j;
 | |
|     set         *dup_matchSets;
 | |
|     set         intersection;
 | |
|     set         incomplete;
 | |
|     set         tokensUsed;
 | |
|     int         depth;
 | |
| 
 | |
|     if (MR_AmbAidRule == NULL) return;
 | |
|     if ( ! (
 | |
|             strcmp(MR_AmbAidRule,alt1->rname) == 0 ||
 | |
|             strcmp(MR_AmbAidRule,alt2->rname) == 0 ||
 | |
|             MR_AmbAidLine==alt1->line ||
 | |
|             MR_AmbAidLine==alt2->line
 | |
|            )
 | |
|        ) return;
 | |
| 
 | |
|     MR_matched_AmbAidRule++;
 | |
| 
 | |
|     save_fset=fset;
 | |
| 
 | |
|     dup_matchSets=(set *) calloc(CLL_k+1,sizeof(set));
 | |
|     require (dup_matchSets != NULL,"Can't allocate dup_matchSets");
 | |
| 
 | |
|     p[0]=analysis_point( (Junction *) alt1->p1);
 | |
|     p[1]=analysis_point( (Junction *) alt2->p1);
 | |
| 
 | |
|     fprintf(stdout,"\n");
 | |
| 
 | |
|     fprintf(stdout,"  Ambiguity Aid                 ");
 | |
|     fprintf(stdout,
 | |
|                 (MR_AmbAidDepth <= CLL_k ?
 | |
|                     "(-ck %d  -aa %s  %s  -aad %d)\n\n" :
 | |
|                         "(-ck %d  -aa %s  %s  [-ck value limits -aad %d])\n\n"),
 | |
|                 CLL_k,
 | |
|                 MR_AmbAidRule,
 | |
|                 (MR_AmbAidMultiple ? "-aam" : ""),
 | |
|                 MR_AmbAidDepth);
 | |
| 
 | |
|     for (i=0 ; i < 2 ; i++) {
 | |
|       fprintf(stdout,"    Choice %d: %-25s  line %d  file %s\n",
 | |
|                             (i+1),
 | |
|                             MR_ruleNamePlusOffset( (Node *) p[i]),
 | |
|                             p[i]->line,FileStr[p[i]->file]);
 | |
|     };
 | |
| 
 | |
|     for (j=1; j <= CLL_k ; j++) {
 | |
|       fprintf(stdout,"\n    Intersection of lookahead[%d] sets:\n",j);
 | |
|       intersection=set_and(alt1->fset[j],alt2->fset[j]);
 | |
|       MR_dumpTokenSet(stdout,2,intersection);
 | |
|       set_free(intersection);
 | |
|     };
 | |
| 
 | |
|     fprintf(stdout,"\n");
 | |
| 
 | |
|     require (1 <= MR_AmbAidDepth && MR_AmbAidDepth <= CLL_k,
 | |
|                 "illegal MR_AmbAidDepth");
 | |
| 
 | |
|     MR_AmbSourceSearchGroup=0;
 | |
|     for (depth=1; depth <= MR_AmbAidDepth; depth++) {
 | |
|         MR_AmbSourceSearchLimit=depth;
 | |
|         for (i=0 ; i < 2 ; i++) {
 | |
| 
 | |
| /***        fprintf(stdout,"  Choice:%d  Depth:%d\n\n",i+1,depth);  ***/
 | |
| 
 | |
|             for (j=0 ; j <= CLL_k ; j++) { dup_matchSets[j]=set_dup(matchSets[j]); };
 | |
|             fset=dup_matchSets;
 | |
| 
 | |
|             fflush(output);
 | |
|             fflush(stdout);
 | |
| 
 | |
|             MR_AmbSourceSearch=1;
 | |
|             MR_MaintainBackTrace=1;
 | |
|             MR_AmbSourceSearchChoice=i;
 | |
| 
 | |
|             maxk = depth;
 | |
|             tokensUsed=empty;
 | |
|             incomplete=empty;
 | |
| 
 | |
|             constrain = &(fset[1]);
 | |
|             MR_pointerStackReset(&MR_BackTraceStack);
 | |
| 
 | |
|             REACH(p[i],depth,&incomplete,tokensUsed);
 | |
| 
 | |
|             fflush(output);
 | |
|             fflush(stdout);
 | |
| 
 | |
|             require (set_nil(incomplete),"MR_traceAmbSource REACH incomplete");
 | |
|             require (MR_BackTraceStack.count == 0,"1: MR_BackTraceStack.count != 0");
 | |
| 
 | |
|             set_free(incomplete);
 | |
|             set_free(tokensUsed);
 | |
| 
 | |
|             for (j=0 ; j <= CLL_k ; j++) { set_free(dup_matchSets[j]); };
 | |
|         };
 | |
|     };
 | |
| 
 | |
|     fprintf(stdout,"\n");
 | |
| 
 | |
|     MR_AmbSourceSearch=0;
 | |
|     MR_MaintainBackTrace=0;
 | |
|     MR_AmbSourceSearchGroup=0;
 | |
|     MR_AmbSourceSearchChoice=0;
 | |
|     MR_AmbSourceSearchLimit=0;
 | |
| 
 | |
|     fset=save_fset;
 | |
|     free ( (char *) dup_matchSets);
 | |
| }
 | |
| 
 | |
| static int itemCount;
 | |
| 
 | |
| void MR_backTraceDumpItemReset() {
 | |
|   itemCount=0;
 | |
| }
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| void MR_backTraceDumpItem(FILE *f,int skip,Node *n)
 | |
| #else
 | |
| void MR_backTraceDumpItem(f,skip,n)
 | |
|   FILE      *f;
 | |
|   int       skip;
 | |
|   Node      *n;
 | |
| #endif
 | |
| {
 | |
|   TokNode       *tn;
 | |
|   RuleRefNode   *rrn;
 | |
|   Junction      *j;
 | |
|   ActionNode    *a;
 | |
| 
 | |
|   switch (n->ntype) {
 | |
|     case nToken:
 | |
|         itemCount++; if (skip) goto EXIT;
 | |
|         tn=(TokNode *)n;
 | |
|         if (set_nil(tn->tset)) {
 | |
|           fprintf(f,"  %2d #token %-23s",itemCount,TerminalString(tn->token));
 | |
|         } else {
 | |
|           fprintf(f,"  %2d #tokclass %-20s",itemCount,TerminalString(tn->token));
 | |
|         };
 | |
|         break;
 | |
|     case nRuleRef:
 | |
|         itemCount++; if (skip) goto EXIT;
 | |
|         rrn=(RuleRefNode *)n;
 | |
|         fprintf(f,"  %2d to %-27s",itemCount,rrn->text);
 | |
|         break;
 | |
|     case nAction:
 | |
|         a=(ActionNode *)n;
 | |
|         goto EXIT;
 | |
|     case nJunction:
 | |
| 
 | |
|       j=(Junction *)n;
 | |
| 
 | |
|       switch (j->jtype) {
 | |
|         case aSubBlk:
 | |
|             if (j->guess) {
 | |
|               itemCount++; if (skip) goto EXIT;
 | |
|               fprintf(f,"  %2d %-30s",itemCount,"in (...)? block at");
 | |
|               break;
 | |
|             };
 | |
| /******     fprintf(f,"  %2d %-32s",itemCount,"in (...) block at");  *******/
 | |
| /******     break;                                                          *******/
 | |
|             goto EXIT;
 | |
|         case aOptBlk:
 | |
|             itemCount++; if (skip) goto EXIT;
 | |
|             fprintf(f,"  %2d %-30s",itemCount,"in {...} block");
 | |
|             break;
 | |
|         case aLoopBlk:
 | |
|             itemCount++; if (skip) goto EXIT;
 | |
|             fprintf(f,"  %2d %-30s",itemCount,"in (...)* block");
 | |
|             break;
 | |
|         case EndBlk:
 | |
|             if (j->alpha_beta_guess_end) {
 | |
|               itemCount++; if (skip) goto EXIT;
 | |
|               fprintf(f,"  %2d %-30s",itemCount,"end (...)? block at");
 | |
|               break;
 | |
|             };
 | |
|             goto EXIT;
 | |
| /******     fprintf(f,"  %2d %-32s",itemCount,"end of a block at");     *****/
 | |
| /******     break;                                                             *****/
 | |
|         case RuleBlk:
 | |
|             itemCount++; if (skip) goto EXIT;
 | |
|             fprintf(f,"  %2d %-30s",itemCount,j->rname);
 | |
|             break;
 | |
|         case Generic:
 | |
|             goto EXIT;
 | |
|         case EndRule:
 | |
|             itemCount++; if (skip) goto EXIT;
 | |
|             fprintf (f,"  %2d end %-26s",itemCount,j->rname);
 | |
|             break;
 | |
|         case aPlusBlk:
 | |
|             itemCount++; if (skip) goto EXIT;
 | |
|             fprintf(f,"  %2d %-30s",itemCount,"in (...)+ block");
 | |
|             break;
 | |
|         case aLoopBegin:
 | |
|             goto EXIT;
 | |
|       };
 | |
|       break;
 | |
|   };
 | |
|   fprintf(f," %-23s line %-4d  %s\n",MR_ruleNamePlusOffset(n),n->line,FileStr[n->file]);
 | |
| EXIT:
 | |
|   return;
 | |
| }
 | |
| 
 | |
| 
 | |
| static PointerStack     previousBackTrace={0,0,NULL};
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| void MR_backTraceReport(void)
 | |
| #else
 | |
| void MR_backTraceReport()
 | |
| #endif
 | |
| {
 | |
|   int       i;
 | |
|   int       match = 0;
 | |
|   int       limitMatch;
 | |
| 
 | |
|   Node      *p;
 | |
|   TokNode   *tn;
 | |
|   set       remainder;
 | |
|   int       depth;
 | |
| 
 | |
|   /* Even when doing a k=2 search this routine can get
 | |
|        called when there is only 1 token on the stack.
 | |
|      This is because something like rRuleRef can change
 | |
|        the search value of k from 2 to 1 temporarily.
 | |
|      It does this because the it wants to know the k=1
 | |
|        first set before it does a k=2 search
 | |
|   */
 | |
| 
 | |
|   depth=0;
 | |
|   for (i=0; i < MR_BackTraceStack.count ; i++) {
 | |
|     p=(Node *) MR_BackTraceStack.data[i];
 | |
|     if (p->ntype == nToken) depth++;
 | |
|   };
 | |
| 
 | |
| /* MR14 */  if (MR_AmbSourceSearch) {
 | |
| /* MR14 */     require (depth <= MR_AmbSourceSearchLimit,"depth > MR_AmbSourceSearchLimit");
 | |
| /* MR14 */  }
 | |
| 
 | |
|   /* MR23 THM - Traceback report was being called at the wrong time for -alpha reports */
 | |
|   /*            Reported by Arpad Beszedes (beszedes@inf.u-szeged.hu)                  */
 | |
| 
 | |
|   if (MR_AmbSourceSearchLimit == 0 || depth < MR_AmbSourceSearchLimit) {
 | |
|     return;
 | |
|   };
 | |
| 
 | |
|   MR_backTraceDumpItemReset();
 | |
| 
 | |
|   limitMatch=MR_BackTraceStack.count;
 | |
|   if (limitMatch > previousBackTrace.count) {
 | |
|     limitMatch=previousBackTrace.count;
 | |
|   };
 | |
| 
 | |
|   for (match=0; match < limitMatch; match++) {
 | |
|     if (MR_BackTraceStack.data[match] !=
 | |
|         previousBackTrace.data[match]) {
 | |
|       break;
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   /* not sure at the moment why there would be duplicates */
 | |
| 
 | |
|   if (match != MR_BackTraceStack.count) {
 | |
| 
 | |
|     fprintf(stdout,"     Choice:%d  Depth:%d  Group:%d",
 | |
|         (MR_AmbSourceSearchChoice+1),
 | |
|         MR_AmbSourceSearchLimit,
 | |
|         ++MR_AmbSourceSearchGroup);
 | |
| 
 | |
|     depth=0;
 | |
|     fprintf(stdout,"  (");
 | |
|     for (i=0; i < MR_BackTraceStack.count ; i++) {
 | |
|       p=(Node *) MR_BackTraceStack.data[i];
 | |
|       if (p->ntype != nToken) continue;
 | |
|       tn=(TokNode *)p;
 | |
|       if (depth != 0) fprintf(stdout," ");
 | |
|       fprintf(stdout,TerminalString(tn->token));
 | |
|       depth++;
 | |
|       if (! MR_AmbAidMultiple) {
 | |
|         if (set_nil(tn->tset)) {
 | |
|           set_rm( (unsigned) tn->token,fset[depth]);
 | |
|         } else {
 | |
|           remainder=set_dif(fset[depth],tn->tset);
 | |
|           set_free(fset[depth]);
 | |
|           fset[depth]=remainder;
 | |
|         };
 | |
|       };
 | |
|     };
 | |
|     fprintf(stdout,")\n");
 | |
| 
 | |
|     for (i=0; i < MR_BackTraceStack.count ; i++) {
 | |
|       MR_backTraceDumpItem(stdout, (i<match) ,(Node *) MR_BackTraceStack.data[i]);
 | |
|     };
 | |
|     fprintf(stdout,"\n");
 | |
|     fflush(stdout);
 | |
| 
 | |
|     MR_pointerStackReset(&previousBackTrace);
 | |
| 
 | |
|     for (i=0; i < MR_BackTraceStack.count ; i++) {
 | |
|       MR_pointerStackPush(&previousBackTrace,MR_BackTraceStack.data[i]);
 | |
|     };
 | |
| 
 | |
|   };
 | |
| }
 | |
| 
 | |
| #ifdef __USE_PROTOS
 | |
| void MR_setConstrainPointer(set * newConstrainValue)
 | |
| #else
 | |
| void MR_setConstrainPointer(newConstrainValue)
 | |
|   set * newConstrainValue;
 | |
| #endif
 | |
| {
 | |
| 	constrain=newConstrainValue;
 | |
| }
 |