Predictive_Parser::Predictive_Parser(CFG *grammar) {

	//init vars
	this->grammar = grammar;
	first = new map<string, set<string>*> ();
	follow = new map<string, set<string>*> ();
	subset_first = new map<pair<string,int>,set<string>*>();

	parse_table = new Parse_Table_Entry*[grammar->get_nonterminals()->size()];

	//size = size of terminals + 1 (input end marker)
	for (unsigned int i = 0; i < grammar->get_nonterminals()->size(); ++i)
		parse_table[i] = new Parse_Table_Entry[grammar->get_terminals()->size() + 1];


	//calculate first
	set<string>* nonterminals = grammar->get_nonterminals();
	for (set<string>::iterator it = nonterminals->begin(); it
			!= nonterminals->end(); ++it) {
		calc_first(*it);
	}

	//calculate follow
	calc_follow();

	//generate parsing table
	generate_table();
}
示例#2
0
文件: Lex_1.cpp 项目: wangchaohui/lib
void LL_construct()
{
	try
	{
		prepare_nonterminals();
		calc_first();
		print_first();
		calc_follow();
		print_follow();
		parse_table_generate();
		print_parse_table();
	}
	catch (ConstructException &e)
	{
		puts(e.message);
		puts("Syntax analyzer construct failed.");
	}
}
示例#3
0
文件: slr.c 项目: fmes/complex-sim
/* Calculates the value of FOLLOW for all nonterminals (and terminals
   while we're at it, but they're not useful).  Sets
   symbols[].follow. */
static void
precalc_follow (void)
{
  int i;

  for (i = 0; i < n_symbols; i++)
    set_init (&symbols[i].follow);

  set_add (&find_symbol (G[0].left)->follow, '$');

  for (;;)
    {
      int added = 0;
      
      for (i = 0; i < n_grammar; i++)
	{
	  const struct production *prod;
	  struct symbol *A;
	  int j;

	  prod = &G[i];
	  A = find_symbol (prod->left);
	  for (j = 0; j < prod->n_right - 1; j++)
	    {
	      struct symbol *B;
	      struct set first_Beta;

	      B = find_symbol (prod->right[j]);
	      calc_first (&first_Beta,
			  &prod->right[j + 1], prod->n_right - (j + 1));
	      added |= set_merge (&B->follow, &first_Beta, 0);

	      if (set_contains (&first_Beta, 0))
		added |= set_merge (&B->follow, &A->follow, 1);

	      set_free (&first_Beta);
	    }
	  
	  if (prod->n_right > 0)
	    {
	      struct symbol *B = find_symbol (prod->right[prod->n_right - 1]);
	      added |= set_merge (&B->follow, &A->follow, 1);
	    }
	}

      if (!added)
	break;
    }

  if (debug) 
    {
      printf ("FOLLOW function:\n");
      for (i = 0; i < n_symbols; i++)
	{
	  struct symbol *sym = &symbols[i];

	  if (!sym->nonterminal)
	    continue;
	  printf ("\tFOLLOW(%c) = ", sym->sym);
	  set_print (&sym->follow);
	  putchar ('\n');
	}
    }
}
void Predictive_Parser::calc_first(string head) {
	//if already calculated then return
	if (first->find(head) != first->end())
		return;

	vector<vector<string>*> * productions =
			(*(grammar->get_productions()))[head];

	//init set
	set<string> * production_first = new set<string> ();
	(*first)[head] = production_first;

	//terminal added from this production
	int added;
	//loop on productions
	for (unsigned int i = 0; i < productions->size(); ++i) {
		//init subset of this production
		(*subset_first)[make_pair(head,i)] = new set<string>();

		added = 0;
		//loop on tokens of specific production
		for (unsigned int j = 0; j < productions->at(i)->size(); ++j) {
			string token = productions->at(i)->at(j);
			//if terminal
			if (grammar->get_terminals()->find(token)
					!= grammar->get_terminals()->end()) {
				++added;
				production_first->insert(token);
				//add to subset first of this production
				subset_first->find(make_pair(head,i))->second->insert(token);
				break;
			} else {
				//NON terminal
				if (token == EPSILON_TOKEN)
					continue;
				//wasn't calculated before
				if (first->find(token) == first->end()) {
					calc_first(token);
				}

				bool has_epsilon = false;
				set<string> * token_first = first->find(token)->second;
				set<string>::iterator it = token_first->begin();
				for (; it != token_first->end(); ++it) {
					if ((*it) == EPSILON_TOKEN)
						has_epsilon = true;
					else {
						++added;
						production_first->insert(*it);
						//add to subset first of this production
						subset_first->find(make_pair(head,i))->second->insert(*it);
					}
				}
				//if first of token doesn't contain epsilon then
				//no need to see the rest of this production
				if (!has_epsilon)
					break;
			}
		}
		//add epsilon to first of this non terminal
		if (added == 0){
			production_first->insert(EPSILON_TOKEN);
			//add to subset first of this production
			subset_first->find(make_pair(head,i))->second->insert(EPSILON_TOKEN);
		}

	}

}