Beispiel #1
0
int	PGBuildLR1::MAKE_KERNEL (int camefrom, int symb)
{
      int i, la, c, first_item;
//		prt_log ("\nFROM STATE %d MAKING STATE %d\n\n", camefrom, n_states);
      hash_no = 0;
		first_item = -1;
      f_lrkernel[n_states] = n_lrkernels;
      for (c = 0; c < N_clo[camefrom]; c++)		// For all closure items.  
      {
         i = Closure[camefrom][c].item;			// Get item #.
         if (item[i].symb == symb)					// If head symbol match?
         {
				if (first_item == -1) first_item = i;
            la = Closure[camefrom][c].LA;       // Get old LA.
            hash_no += N_terms*(i+1) + la;		// Add both to hash number. 
            lrkernel [n_lrkernels].item = i+1;  // Make new LR1 item.
            lrkernel [n_lrkernels].LA   = la;   // Keep same look ahead.
//          prt_item ("Making LR1 kernel ", i+1, la);
            if (++n_lrkernels >= max_lrkernels) MemCrash ("Number of LR(1) kernels", max_lrkernels);
         }
      }
      l_lrkernel[n_states] = n_lrkernels;
      if (n_lrkernels == f_lrkernel[n_states]) InternalError (255);
//    PRT_LRSTA (n_states);
		return first_item;
}
Beispiel #2
0
void  PGBuildLR1::MAKE_KERNEL (int state)          // Make lrkernel items for state 0.
{
      int p, head;
      head = 0;                        // Head symbol is the Goal symbol.
      f_lrkernel[state] = 0;
      for (p = F_prod [head]; p < F_prod [head+1]; p++) // Should be only one production.                                      
      {
         lrkernel [n_lrkernels].item = f_item[p];
         lrkernel [n_lrkernels].LA   = 0; // Not used anyway, 0 is safe.      
         if (++n_lrkernels >= max_lrkernels)  MemCrash ("Number of LR(1) kernels", max_lrkernels);
      }
      l_lrkernel[state] = n_lrkernels;
      f_final [state]   = 0;           // Nothing.
      l_final [state]   = 0;           // Nothing.
}
Beispiel #3
0
int   PGBuildLR1::TRANSITION (int sym)
{
      uint probe;
		LRKERNEL temp;
		int  compatible = 1;
      int  fk, lk, nk, ni, fi, i, j, k, x, y, p;

	//	PRT_LRSTA (n_states);
		fk = f_lrkernel[n_states];
		lk = l_lrkernel[n_states];
      nk = lk - fk;					
		fi = 0;
		x  = n_states;
		#ifdef PG_DEBUG
	  	PRT_LRSTA (x);
		#endif
		if (optn[PG_CLR_PARSER]) 
		{
			if (nk > 1)						
			{
				LR1_SORT (lrkernel, fk, lk);	 
			}
			probe = hash_no % max_hashes;
			while ((y = hash_vector[probe]) != -1)	// Get state y with same hash cell. 
			{
				if (l_lrkernel[y] - f_lrkernel[y] == nk) // Same number of kernels?
				{
					for (i = f_lrkernel[x], j = f_lrkernel[y]; i < l_lrkernel[x]; i++, j++)
					{
						if (lrkernel[i].item != lrkernel[j].item)	goto Next1;	
						if (lrkernel[i].LA   != lrkernel[j].LA  ) goto Next1;
					}
					n_lrkernels = fk;						// Reset this.
					return (y);								// Return old state number.
				}  
Next1:		probe = (hash_no *= 65549) / hash_div;
			}
		}
		else // PG_LR_PARSER or PG_LALR_PARSER
		{
			ni = LR0_SORT (lrkernel, fk, lk);	 
		  	if (ni == 1)									// Number of lrkernel items is 1 or 0?
			{
	  		  	i = lrkernel[fk].item;					// Get item #
				if (item[i].symb == -32767) 
				{
					if (optn[PG_LALR_PARSER])
					{
						p = item [i].prod;				// Get production.
						reduce_state[p] = 1;				// Mark production for reduce-state creation.   
						return (-p);						// Return production number.
					}
				  	fi = i;									// Save the final item.
				}
			}	 
			probe = hash_no % max_hashes;
			while ((y = hash_vector[probe]) != -1)	// Get state y with same hash cell. 
			{
				#ifdef PG_DEBUG
			  	PRINT ("Comparing to:\n\n");
			  	PRT_LRSTA (y);
				#endif
				int n = 0, m = 0;
				memset (item_added, 0, n_items);
				for (i = f_lrkernel[x]; i < l_lrkernel[x]; i++)
				{
					if (item_added[lrkernel[i].item] == 0)	// Item not added yet?
					{
						n++; item_added [lrkernel[i].item] = 1; // Add it.
					}
				}
				for (i = f_lrkernel[y]; i < l_lrkernel[y]; i++)
				{
					if (item_added[lrkernel[i].item] == 0) goto Next2; // Missmatch!
					if (item_added[lrkernel[i].item] == 1)				   // Match!?
					{
						m++; item_added [lrkernel[i].item] = 2;
					}
				}
				if (n == m) // LALR(1) satisfied?
				{
					if (!optn[PG_LALR_PARSER]) 
					{
						if (!COMPATIBLE (x, y)) 
						{
							compatible = 0;
							goto Next2;
						}
					}
					#ifdef PG_DEBUG
				  	PRINT ("Got a match!\n");
					#endif
					n_lrkernels = fk;					// Reset this, not a new state.
					if (fi)								// If final item defined?
					{
						p = item [fi].prod;			// Get production.
						reduce_state[p] = 1;			// Mark production for reduce-state creation.   
						return (-p);					// Return production number.
					}
					return (y);			 // Return old state number.
				}
Next2:		probe = (hash_no *= 65549) / hash_div;
			}
		}
		if (!compatible) extra_states++;
		if (fi)								// If final item defined by LR or LALR?
		{
			#ifdef PG_DEBUG
  	  		PRINT ("Reduce-ony state!\n");
			#endif
			p = item [fi].prod;			// Get production.
			reduce_state[p] = 1;			// Mark production for reduce-state creation.   
			return (-p);					// Return production number.
		}

	// NEW STATE ...
		#ifdef PG_DEBUG
  	  	PRINT ("New state %d\n", n_states);
		#endif
      accessor [n_states] = sym;
      hash_vector [probe] = n_states;
      DO_CLOSURE (n_states); 
      if (n_states % 50000 == 0) prt_log ("         %7d states\n", n_states);
      if (n_states >= max_states) MemCrash ("Number of states", max_states);
      return (n_states++);
}
Beispiel #4
0
void 	LGCheckGrammar::make_prod (int h, int p) 
{
		int t, t0, tn, sym, q, n, P, I, T;

		F_TAIL   [N_PRODS] = N_TAILS;
		RET_NUMB [N_PRODS] = ret_numb[p];
		RET_NAME [N_PRODS] = ret_name[p];
	//	printf ("\nmake_prod (%d, %d) ...\n", h, p);

		n  = 0;
		t0 = f_tail[p];
		tn = l_tail[p];
		for (t = t0; t < tn; t++)
		{
			if (vector [t-t0] == 1) // keep this tail ?
			{
				n++;
				sym = tail[t];
Check:		if (sym < 0 && nullable [-sym])
				{
					q = f_prod[-sym];
					if (l_tail[q] - f_tail[q] == 0)           // Null first production?
					{
						if (l_tail [q+1] - f_tail [q+1] == 1)  // Only one tail on 2nd production?
						{
							sym = tail [f_tail[q+1]];           // First (and only) tail of 2nd prod.
							goto Check;	
						}
					}
				}
				if (N_TAILS >= max_tails) MemCrash ("Number of tail symbols", max_tails);
				TAILSYM[N_TAILS++] = sym;
			//	if (sym < 0) printf (" %s", head_name[-sym]);
			//	else         printf (" %s", term_name[ sym]);
			}
		}
	//	if (n == 0) printf ("<null>\n");
	//	else        printf ("\n");
		L_TAIL [N_PRODS] = N_TAILS;

	// Check for previous existence of this production. 
		if (n > 0)
		{
			if (n == 1 && -sym == h) goto Undo;
			for (P = F_PROD [N_HEADS]; P < N_PRODS; P++)
			{
				int PLO = L_TAIL [P]       - F_TAIL [P];
				int PLN = L_TAIL [N_PRODS] - F_TAIL [N_PRODS];
				if (PLO == PLN)
				{
					I = F_TAIL [N_PRODS];
					for (T = F_TAIL [P]; T < L_TAIL [P]; T++)
					{	
					//	char a[50]; 
					//	char b[50]; 
					//	symstr(TAILSYM[T], a);
					//	symstr(TAILSYM[I], b);
					//	printf ("Comparing %s to %s\n", b, a);
						if (TAILSYM[T] != TAILSYM[I++]) goto NextP;
					}
				//	printf ("already exists\n\n");
					goto Undo; // Production already exists!
				}
NextP:		continue;
			}
		//	printf ("new production accepted\n");
		}
		else // New production is NULL!
		{
			int FP = F_PROD [N_HEADS];
			if (N_PRODS > FP) // Already have some productions?
			{
				if (F_TAIL [FP] == L_TAIL [FP]) goto Undo; // Already have NULL.
			}
		// Move current productions down one. 
			for (P = N_PRODS; P > FP; P--)
			{
				F_TAIL [P] = F_TAIL [P-1];
				L_TAIL [P] = L_TAIL [P-1];
			}
		// Create NULL production in first place. 
			F_TAIL [P] = F_TAIL [P+1];
			L_TAIL [P] = F_TAIL [P+1];
		//	printf ("<null> production accepted\n");
		}
		if (++N_PRODS >= max_prods) 
			MemCrash ("Number of productions", max_prods);
      return;

Undo: N_TAILS = F_TAIL [N_PRODS]; // Reset number of tails.
	//	printf ("new production rejected\n");
		return;
}
Beispiel #5
0
void  LGCheckGrammar::P_UNREACHABLES ()
{
      char *head_used;
      int  n_unreachables;
		int  *used_list, h, p, t, s, i, n_used, x;

      ALLOC (used_list, n_heads);
      ALLOC (head_used, n_heads);
      memset(head_used, 0, n_heads);

		i = 0;							// Goal symbol!
      n_used = 0;						// Start with 0. 
      head_used[i] = 1;				// Mark goal symbol used.
      used_list[n_used++] = i;	// Add goal symbol to list.

	// Traverse from goal symbol and mark all nonterminals that are used.
      for (; i < n_used; i++)
      {
         h = used_list[i];										// Pick head from list.
		//	printf ("%s\n", head_name[h]);
			for (p = f_prod[h]; p < l_prod[h]; p++)		// All of its rules. 
			{
				for (t = f_tail[p]; t < l_tail[p]; t++)	// All of its tails. 
				{
					if ((s = tail[t]) < 0)						// Nonterminal?      
					{
						if (head_used[-s] == 0)					// Not used?   
						{
							head_used[-s] = 1;					// Mark it used.     
							used_list[n_used++] = -s;			// Add it to list.   
						//	printf ("   %s used\n", head_name[-s]);
						}  
					}  
				}  
			}  
      }

	// Traverse from {ignore} symbols and mark all nonterminals that are used.
		int n_ignores = 0;
      for (int H = 0; H < n_heads; H++)
      {
			if (head_type[H] & IGNORESYM) 
			{
				n_ignores++;
			//	printf ("%s unused\n", head_name[H]);
				i = n_used;
				head_used[H] = 1;				// Mark ignore symbol used.
				used_list[n_used++] = H;	// Add ignore symbol to list.
				for (; i < n_used; i++)
				{
					h = used_list[i];										// Pick head from list.
				//	printf ("%s\n", head_name[h]);
					for (p = f_prod[h]; p < l_prod[h]; p++)		// All of its rules. 
					{
						for (t = f_tail[p]; t < l_tail[p]; t++)	// All of its tails. 
						{
							if ((s = tail[t]) < 0)						// Nonterminal?      
							{
								if (head_used[-s] == 0)					// Not marked yet?   
								{
									head_used[-s] = 1;				// Mark it used.     
									used_list[n_used++] = -s;		// Add it to list.   
								//	printf ("   %s used %d\n", head_name[-s], n_used);
								}  
							}  
						}  
					}  
				}
			}
		}
      FREE (used_list, n_heads);

	// List unreachable heads ...
		n_unreachables = 0;
      for (h = 0; h < n_heads; h++)		 
      {
			if (!(head_type[h] & IGNORESYM) && head_used[h] == 0) // Not {ignore} and not used?         
         {
				if (head_line[h] != 0)							// Not generated symbol?
				{
					if (head_type[h] & SETNAME)				// If setname (or escape symbol).
					{
						// Nothing. 
					}
					else if (head_type[h] & LEXICON)			// If lexicon symbol.
					{
						n_unreachables++;
						head_type[h] |= UNREACHABLE;
						x = strlen(head_name[h]) -1;
						head_name[h][x] = 0;
						sprintf (string, "<%s> is not reachable from the goal symbol. To ignore, rename to {%s}.\n", head_name[h]+1, head_name[h]+1);
						head_name[h][x] = '>';
						prt_error (string, head_name[h], 0, head_line[h]); 
					} 
					else
					{
						n_unreachables++;
						head_type[h] |= UNREACHABLE;
						sprintf (string, "%s is not reachable from the goal symbol. To ignore, rename to {%s}.\n", head_name[h], head_name[h]);
						prt_error (string, head_name[h], 0, head_line[h]); 
					} 
				}
         }  
      }
      FREE (head_used, n_heads);

	// If we have any unreachables ...
		if (n_ignores && n_errors == 0)
		{
			if (n_prods + n_unreachables >= max_prods)
				MemCrash ("Number of productions", max_prods); 
			if (n_tails + n_unreachables >= max_tails)
				MemCrash ("Number of tail symbols", max_tails);
	  		RenumberProductions (n_ignores);
		}
}