grammar.cpp.svn-base

来自「Complete support for EBNF notation; Obje」· SVN-BASE 代码 · 共 639 行 · 第 1/2 页

SVN-BASE
639
字号
#include <fstream>#include "whale.h"#include "grammar.h"#include "parser.h"//#include "nstl/stl.h"#include "ancillary.h"#include "utilities.h"#include "process.h"using namespace std;using namespace Whale;//#define DEBUG_RULE_NUMBERS//#define DEBUG_MAKE_CREATOR_OR_UPDATER_OR_USE_EXISTING_ONEtemplate<class T> set<vector<T> > concatenate_sets_of_vectors(const set<vector<T> > &s1, const set<vector<T> > &s2);template<class T> inline set<vector<T> > set_consisting_of_a_single_one_element_vector(const T &x);template<class T> inline set<vector<T> > set_consisting_of_a_single_empty_vector();set<vector<NonterminalExpression *> > make_rules_proc(NonterminalExpression *expr);int find_creator_or_updater_in_rule(const RuleData &rule, int pos);SymbolNumber make_creator_or_updater_or_use_existing_one(const set<RuleData> &requested_rules, RuleData &rule, int last1);void build_create_and_update_operator_locations_and_source_rules_database();bool make_rules(){	bool flag=true;	set<NonterminalExpressionConnectUp *> bad_connect_up_operators;	for(int i=0; i<data.nonterminals.size(); i++)	{		data.nonterminals[i].first_rule=data.rules.size();		NonterminalData::Category category=data.nonterminals[i].category;		if(category==NonterminalData::NORMAL ||			category==NonterminalData::EXTERNAL ||			category==NonterminalData::BODY)		{			set<RuleData> requested_rules;			for(int j=0; j<data.nonterminals[i].alternatives.size(); j++)			{				AlternativeData &alternative=data.nonterminals[i].alternatives[j];				set<vector<NonterminalExpression *> > rule_bodies=make_rules_proc(alternative.expr);				for(set<vector<NonterminalExpression *> >::iterator p=rule_bodies.begin(); p!=rule_bodies.end(); p++)				{					RuleData rule(i, j);					rule.expr_body=*p;					for(int k=rule.expr_body.size()-1; k>=0; k--)					{						NonterminalExpression *expr=(*p)[k];						if(typeid(*expr)==typeid(NonterminalExpressionCode))						{							NonterminalExpressionCode *expr_code=dynamic_cast<NonterminalExpressionCode *>(expr);							// to be activated upon reduce.							if(rule.code_to_execute_upon_reduce==NULL)							{								rule.code_to_execute_upon_reduce=expr_code;								rule.expr_body.pop_back();							}							else								break;						}						else if(typeid(*expr)==typeid(NonterminalExpressionConnectUp))						{							NonterminalExpressionConnectUp *expr_up=dynamic_cast<NonterminalExpressionConnectUp *>(expr);							alternative.connect_up=true;						//	data.variables.connect_up_operators_are_used=true;							rule.expr_body.pop_back();						}						else							break;					}					for(int k=0; k<rule.expr_body.size(); k++)					{						NonterminalExpression *expr=rule.expr_body[k];						if(typeid(*expr)==typeid(NonterminalExpressionSymbol))							rule.body.push_back(dynamic_cast<NonterminalExpressionSymbol *>(expr)->sn);						else if(typeid(*expr)==typeid(NonterminalExpressionIteration))							rule.body.push_back(SymbolNumber::for_nonterminal(dynamic_cast<NonterminalExpressionIteration *>(expr)->iterator_nn));						else if(typeid(*expr)==typeid(NonterminalExpressionIterationPair))							rule.body.push_back(SymbolNumber::for_nonterminal(dynamic_cast<NonterminalExpressionIterationPair *>(expr)->iterator_nn));						else if(typeid(*expr)==typeid(NonterminalExpressionCreate) ||							typeid(*expr)==typeid(NonterminalExpressionUpdate))						{							rule.body.push_back(make_creator_or_updater_or_use_existing_one(requested_rules, rule, k));						}						else if(typeid(*expr)==typeid(NonterminalExpressionCode))						{							NonterminalExpressionCode *expr_code=dynamic_cast<NonterminalExpressionCode *>(expr);							if(expr_code->invoker_nn==-1)							{								int local_invoker_number=++data.nonterminals[i].number_of_invokers;								expr_code->invoker_nn=make_invoker_or_creator_or_updater(i, j, local_invoker_number, 0, NonterminalData::INVOKER, expr_code->code);								data.nonterminals[expr_code->invoker_nn].code_invoker_declaration=expr_code;							}							rule.body.push_back(SymbolNumber::for_nonterminal(expr_code->invoker_nn));						}						else if(typeid(*expr)==typeid(NonterminalExpressionConnectUp))						{							NonterminalExpressionConnectUp *expr_up=dynamic_cast<NonterminalExpressionConnectUp *>(expr);							// in this version, all							// of them are considered bad.							bad_connect_up_operators.insert(expr_up);							rule.expr_body.erase(rule.expr_body.begin()+k, rule.expr_body.begin()+k+1);							k--;						}						else if(typeid(*expr)==typeid(NonterminalExpressionPrecedence))						{							NonterminalExpressionPrecedence *expr_pr=dynamic_cast<NonterminalExpressionPrecedence *>(expr);							rule.precedence_expressions.push_back(expr_pr);							rule.expr_body.erase(rule.expr_body.begin()+k, rule.expr_body.begin()+k+1);							k--;						}						else							assert(false);					}					assert(rule.body.size()==rule.expr_body.size());					requested_rules.insert(rule);				}			}			// note: no autoincrement in this for statement.			for(set<RuleData>::const_iterator p=requested_rules.begin(); p!=requested_rules.end(); )			{				// looking for rules with the same body, they				// should reside in the close vicinity.				set<RuleData>::const_iterator p2;				int count=0;				map<int, int> how_many_rules_from_alternative;				for(p2=p; p2!=requested_rules.end(); p2++, count++)				{					if(p2->body!=p->body)						break;					how_many_rules_from_alternative[p2->an]++;				}				assert(count>0);				if(count>1)				{					bool more_than_one_from_single_alternative=(count>how_many_rules_from_alternative.size());					bool different_alternatives=(how_many_rules_from_alternative.size()>1);					cout << "Rule " << p->in_printable_form()						<< " can be generated in " << english1_itoa(count, false)						<< " different ways";					if(different_alternatives || data.nonterminals[i].multiple_alternatives_mode)					{						if(different_alternatives)							cout << ": ";						for(map<int, int>::const_iterator p4=how_many_rules_from_alternative.begin(); p4!=how_many_rules_from_alternative.end(); p4++)						{							if(p4!=how_many_rules_from_alternative.begin())							{								map<int, int>::const_iterator p5=p4;								p5++;								if(p5!=how_many_rules_from_alternative.end())									cout << "; ";								else									cout << " and ";							}							if(different_alternatives && more_than_one_from_single_alternative)								cout << "in " << english1_itoa(p4->second, false)									<< " way" << (p4->second==1 ? "" : "s")									<< " from the " << english2_itoa(p4->first+1, false)									<< " alternative";							else								cout << "from the " << english2_itoa(p4->first+1, false) << " alternative";						}						cout << ".\n";					}					else						cout << ".\n";				}				data.rules.push_back(*p);				p=p2;			}		}		else if(category==NonterminalData::START)		{			assert(!i);			RuleData rule(i, 0);			rule.body.push_back(SymbolNumber::for_nonterminal(data.start_nonterminal_number));			data.rules.push_back(rule);		}		else if(category==NonterminalData::ITERATOR)		{			ClassHierarchy::Class *type=data.nonterminals[i].type;			assert(type);			if(type->template_parameters.size()==1)			{				RuleData rule1(i, 0);				rule1.body.push_back(type->template_parameters[0]->assigned_to);				data.rules.push_back(rule1);				RuleData rule2(i, 0);				rule2.body.push_back(SymbolNumber::for_nonterminal(i));				rule2.body.push_back(type->template_parameters[0]->assigned_to);				data.rules.push_back(rule2);			}			else if(type->template_parameters.size()==2)			{				RuleData rule1(i, 0);				rule1.body.push_back(type->template_parameters[0]->assigned_to);				data.rules.push_back(rule1);				RuleData rule2(i, 0);				rule2.body.push_back(SymbolNumber::for_nonterminal(i));				rule2.body.push_back(type->template_parameters[1]->assigned_to);				rule2.body.push_back(type->template_parameters[0]->assigned_to);				data.rules.push_back(rule2);			}			else				assert(false);		}		else if(category==NonterminalData::CREATOR || category==NonterminalData::UPDATER)		{			RuleData rule(i, 0);			// rule.body=epsilon			data.rules.push_back(rule);		}		else if(category==NonterminalData::INVOKER)		{			RuleData rule(i, 0);			// rule.body=epsilon		//	cout << data.nonterminals[i].name << "\n";			assert(data.nonterminals[i].code_invoker_declaration);			rule.code_to_execute_upon_reduce=data.nonterminals[i].code_invoker_declaration;			data.rules.push_back(rule);		}		else			assert(false);		data.nonterminals[i].last_rule=data.rules.size();	#ifdef DEBUG_RULE_NUMBERS		cout << data.nonterminals[i].name << ": " << data.nonterminals[i].first_rule << " " << data.nonterminals[i].last_rule << "\n";	#endif		assert((data.nonterminals[i].last_rule>data.nonterminals[i].first_rule) ||			(category==NonterminalData::NORMAL && data.nonterminals[i].alternatives.size()==0));	}	if(bad_connect_up_operators.size()>0)	{		vector<Terminal *> v;		for(set<NonterminalExpressionConnectUp *>::const_iterator p=bad_connect_up_operators.begin(); p!=bad_connect_up_operators.end(); p++)			v.push_back((*p)->kw);		cout << "The current version of Whale doesn't support "			<< "connect_up operators other than in the rightmost "			<< "position in rule; thus, declaration"			<< (bad_connect_up_operators.size()==1 ? " " : "s ");		print_a_number_of_terminal_locations(cout, v, "at");		cout << (bad_connect_up_operators.size()==1 ? " is " : " are ")			<< "invalid.\n";		flag=false;	}	cout << data.terminals.size() << " terminals, ";	cout << data.nonterminals.size() << " nonterminals, ";	cout << classes.total_classes << " classes, ";	cout << classes.total_data_members << " data members";	cout << ".\n";	cout << data.rules.size() << " context-free rules created.\n";	if(data.variables.dump_grammar_to_file)	{		string grammar_file_name=data.file_name+string(".grammar");		ofstream grammar_file(grammar_file_name.c_str());		print_grammar(grammar_file);	}	build_create_and_update_operator_locations_and_source_rules_database();	return flag;}void print_grammar(ostream &os){	os << "\tContext-free grammar:\n";	for(int i=0; i<data.rules.size(); i++)		os << data.rules[i].in_printable_form() << "\n";}template<class T> set<vector<T> > concatenate_sets_of_vectors(const set<vector<T> > &s1, const set<vector<T> > &s2){	set<vector<T> > result;	for(set<vector<T> >::const_iterator p1=s1.begin(); p1!=s1.end(); p1++)		for(set<vector<T> >::const_iterator p2=s2.begin(); p2!=s2.end(); p2++)		{			vector<T> v(*p1);			copy((*p2).begin(), (*p2).end(), back_inserter(v));			result.insert(v);		}	return result;

⌨️ 快捷键说明

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