⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process.cpp.svn-base

📁 Complete support for EBNF notation; Object-oriented parser design; C++ output; Deterministic bottom-
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
#include "whale.h"#include "parser.h"#include <stdio.h>#include <iostream>#include <typeinfo>using namespace std;#include "assert.h"#include "process.h"//#include "stl.h"#include "classes.h"#include "utilities.h"#include "ancillary.h"using namespace Whale;//#define DEBUG//#define DEBUG_DATA_MEMBERS_IN_BODIES//#define DEBUG_COMMON_ANCESTORvoid make_built_in_symbols();bool process_class_declarations();bool process_expressions();bool process_expression_proc(NonterminalExpression *expr, ProcessExpressionProcData &proc_data);bool process_expression_proc_ii(NonterminalExpression *expression, ProcessExpressionProcIIData &proc_data);bool process_terminal_type_declaration(TerminalData &terminal, NonterminalTypeExpression *type);bool process_nonterminal_type_declaration(int nn, NonterminalTypeExpression *type);ClassHierarchy::Class *process_external_type_declaration(NonterminalExternalTypeExpression *external_type, NonterminalData *nonterminal);bool process_alternative_type_declaration(AlternativeData &alternative, NonterminalData &nonterminal, int alternative_number, NonterminalTypeExpression *type);ClassHierarchy::Class *process_standalone_type_declaration(NonterminalTypeExpression *type);string default_naming_proc(const char *s);string default_terminal_class_name(const char *s);string default_nonterminal_class_name(const char *s);string default_alternative_class_name(const string &s, int alternative_number);void report_undefined_base_class(ostream &os, Terminal *t);bool identifier_contains_no_hyphens(Terminal *t);ClassHierarchy::Class *process_scope_in_member_name_specification(Terminal *scope, Terminal *id, const pair<int, int> &location);ClassHierarchy::DataMember *process_single_data_member_declaration(Terminal *scope, Terminal *name, int nn, int an, int number_of_iterations);string generate_default_data_member_name(int n);string serialize_external_type_expression(NonterminalExternalTypeExpression &expr);bool apply_common_ancestor_determination_procedure(ClassHierarchy::Class *&dest, ClassHierarchy::Class *src, SymbolNumber sn, ClassHierarchy::DataMember *data_member, Terminal *t);bool process_option_statement(NonterminalOptionStatement &option_statement);pair<char *, AssignmentData::ValueType> process_single_value_in_option_statement(Terminal *t, bool process_escape_sequences_in_string);bool high_level_decode_escape_sequences(Terminal *t, string &s);void make_up_data_member_in_class_symbol();bool process_grammar(){	make_built_in_symbols();	if(!process_class_declarations()) return false;	if(!assign_values_to_variables_stage_zero()) return false;	if(data.variables.make_up_connection)		make_up_data_member_in_class_symbol();	if(!process_expressions()) return false;	if(data.terminals.size()<=2)	{		cout << "The grammar should contain at least one terminal symbol.\n";		return false;	}	if(data.nonterminals.size()<=1)	{		cout << "The grammar should contain at least one nonterminal symbol.\n";		return false;	}	assert(classes.in_global_scope.size());	return true;}void make_built_in_symbols(){	// S'	NonterminalData start_symbol_of_augmented_grammar;	start_symbol_of_augmented_grammar.name="S'";	start_symbol_of_augmented_grammar.declaration=NULL;	start_symbol_of_augmented_grammar.type=0;	start_symbol_of_augmented_grammar.is_ancillary=true;	start_symbol_of_augmented_grammar.category=NonterminalData::START;	data.nonterminals.push_back(start_symbol_of_augmented_grammar);	// eof	TerminalData eof_terminal;	eof_terminal.name="eof";	eof_terminal.type=new ClassHierarchy::Class("TerminalEOF", classes.terminal, NULL);	eof_terminal.type->is_abstract=false;	data.eof_terminal_number=data.terminals.size();	eof_terminal.type->assigned_to=SymbolNumber::for_terminal(data.eof_terminal_number);	data.terminals.push_back(eof_terminal);	// error	TerminalData error_terminal;	error_terminal.name="error";	error_terminal.type=new ClassHierarchy::Class("TerminalError", classes.terminal, NULL);	error_terminal.type->is_abstract=false;	data.error_terminal_number=data.terminals.size();	error_terminal.type->assigned_to=SymbolNumber::for_terminal(data.error_terminal_number);	data.terminals.push_back(error_terminal);}bool process_class_declarations(){	bool flag=true;	// Pass 1. Determining how many rules are there for each nonterminal.	// It is really vital to do it before all other processing.	map<const char *, int, NullTerminatedStringCompare> how_many_rules_for_nonterminal;	for(int i=0; i<data.S->statements.size(); i++)		if(typeid(*data.S->statements[i])==typeid(NonterminalRuleStatement))		{			NonterminalRuleStatement &rule_statement=*dynamic_cast<NonterminalRuleStatement *>(data.S->statements[i]);			how_many_rules_for_nonterminal[rule_statement.left->text]++;		}#ifdef DEBUG	cout << how_many_rules_for_nonterminal << "\n";#endif	string start_nonterminal_name;	// Pass 2: Making the class hierarchy. It is done without looking	// inside the expressions.	for(int i=0; i<data.S->statements.size(); i++)	{		if(typeid(*data.S->statements[i])==typeid(NonterminalTerminalStatement))		{			NonterminalTerminalStatement &terminal_statement=*dynamic_cast<NonterminalTerminalStatement *>(data.S->statements[i]);			for(int j=0; j<terminal_statement.names.size(); j++)			{				Terminal *t=terminal_statement.names[j];				int tn=data.find_terminal(t->text);				int nn=data.find_nonterminal(t->text);				assert(!(tn!=-1 && nn!=-1));				if(tn!=-1)				{					cout << "Terminal " << t->text << ", ";					data.terminals[tn].print_where_it_was_declared(cout);					cout << ", cannot be redeclared at ";					t->print_location(cout);					cout << ".\n";					flag=false;				}				else if(nn!=-1)				{					cout << "Attempt to redeclare nonterminal " << t->text << " (";					data.nonterminals[nn].print_where_it_was_declared(cout);					cout << ") as terminal at ";					t->print_location(cout);					cout << ".\n";					flag=false;				}				else				{					TerminalData terminal;					terminal.name=t->text;					terminal.declaration=t;					if(process_terminal_type_declaration(terminal, terminal_statement.types[j]))						data.terminals.push_back(terminal);					else						flag=false;				}			}		}		else if(typeid(*data.S->statements[i])==typeid(NonterminalNonterminalStatement))		{			NonterminalNonterminalStatement &nonterminal_statement=*dynamic_cast<NonterminalNonterminalStatement *>(data.S->statements[i]);			bool has_external_tag;			if(!strcmp(nonterminal_statement.kw->text, "nonterminal"))				has_external_tag=false;			else if(!strcmp(nonterminal_statement.kw->text, "external"))				has_external_tag=true;			else				assert(false);			for(int j=0; j<nonterminal_statement.names.size(); j++)			{				Terminal *t=nonterminal_statement.names[j];				NonterminalExternalTypeExpression *external_type=nonterminal_statement.external_types[j];				int tn=data.find_terminal(t->text);				int nn=data.find_nonterminal(t->text);				assert(!(tn!=-1 && nn!=-1));				if(tn!=-1)				{					cout << "Attempt to redeclare terminal " << t->text << " (";					data.terminals[tn].print_where_it_was_declared(cout);					cout << ") as nonterminal at ";					t->print_location(cout);					cout << ".\n";					flag=false;				}				else if(nn!=-1)				{					cout << "Nonterminal " << t->text << ", ";					data.nonterminals[nn].print_where_it_was_declared(cout);					cout << ", cannot be redeclared at ";					t->print_location(cout);					cout << ".\n";					flag=false;				}				else				{					int new_nn=data.nonterminals.size();					data.nonterminals.push_back(NonterminalData());					NonterminalData &nonterminal=data.nonterminals[new_nn];					nonterminal.name=t->text;					nonterminal.declaration=t;					if(!has_external_tag)					{						nonterminal.category=NonterminalData::NORMAL;						if(!process_nonterminal_type_declaration(new_nn, nonterminal_statement.internal_types[j]))							flag=false;						if(external_type && !process_external_type_declaration(external_type, &nonterminal))							flag=false;					}					else					{						nonterminal.category=NonterminalData::EXTERNAL;						if(!process_nonterminal_type_declaration(new_nn, NULL))							flag=false;						if(!process_external_type_declaration(external_type, &nonterminal))							flag=false;						nonterminal.type->template_parameters.push_back(nonterminal.external_type);					}					// if there were any errors (which have					// already been reported by now),					// nonterminal.type may be NULL.					if(nonterminal.type!=NULL)					{						int nr=how_many_rules_for_nonterminal[t->text];						if(has_external_tag)							nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::WRAPPER;						else if(nr<=1)							nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::UNKNOWN;						else							nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::BASE;					}				}			}		}		else if(typeid(*data.S->statements[i])==typeid(NonterminalClassStatement))		{			NonterminalClassStatement &class_statement=*dynamic_cast<NonterminalClassStatement *>(data.S->statements[i]);			ClassHierarchy::Class *m=process_standalone_type_declaration(class_statement.expr);			if(!m) flag=false;		}		else if(typeid(*data.S->statements[i])==typeid(NonterminalRuleStatement))		{			NonterminalRuleStatement &rule_statement=*dynamic_cast<NonterminalRuleStatement *>(data.S->statements[i]);			Terminal *t=rule_statement.left;			int tn=data.find_terminal(t->text);			int nn=data.find_nonterminal(t->text);			assert(!(tn!=-1 && nn!=-1));			int nr=how_many_rules_for_nonterminal[t->text];			assert(nr>0);			if(tn!=-1)			{				cout << "Terminal " << t->text << ", ";				data.terminals[tn].print_where_it_was_declared(cout);				cout << ", cannot be used in left part of rule at ";				t->print_location(cout);				cout << ".\n";				flag=false;				continue;			}			else if(nn==-1 && nr==1)			{				int new_nn=data.nonterminals.size();				data.nonterminals.push_back(NonterminalData());				NonterminalData &nonterminal=data.nonterminals[new_nn];				nonterminal.name=t->text;				nonterminal.declaration=t;				nonterminal.category=NonterminalData::NORMAL;				// creating a single class				bool result=process_nonterminal_type_declaration(new_nn, rule_statement.type);				if(!result)				{					flag=false;					continue;				}				nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::SINGLE;				AlternativeData alternative;				alternative.declaration=rule_statement.left;				alternative.type=NULL;				alternative.expr=rule_statement.right;			//	cout << "pushing alternative: " << (void *)rule_statement.right << "\n";				nonterminal.alternatives.push_back(alternative);				nonterminal.multiple_alternatives_mode=false;			}			else if(nn==-1 && nr>1)			{				int new_nn=data.nonterminals.size();				data.nonterminals.push_back(NonterminalData());				NonterminalData &nonterminal=data.nonterminals[new_nn];				nonterminal.name=t->text;				nonterminal.declaration=t;				nonterminal.category=NonterminalData::NORMAL;				// Creating a base class using a generated name.				bool result=process_nonterminal_type_declaration(new_nn, NULL);				if(!result)				{					flag=false;					continue;				}				nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::BASE;				AlternativeData alternative;				alternative.declaration=rule_statement.left;				alternative.expr=rule_statement.right;				bool result2=process_alternative_type_declaration(alternative, nonterminal, nonterminal.alternatives.size(), rule_statement.type);				if(!result2)				{				//	cout << "pushing alternative: " << (void *)rule_statement.right << "\n";					nonterminal.alternatives.push_back(alternative);					flag=false;					continue;				}				assert(!alternative.type->is_abstract);			//	cout << "pushing alternative: " << (void *)rule_statement.right << "\n";				nonterminal.alternatives.push_back(alternative);				nonterminal.multiple_alternatives_mode=true;			}			else if(nn!=-1)			{				NonterminalData &nonterminal=data.nonterminals[nn];				assert(nonterminal.category==NonterminalData::NORMAL					|| nonterminal.category==NonterminalData::EXTERNAL);				if(!nonterminal.type)				{					assert(!flag);				}				else if(nonterminal.category==NonterminalData::EXTERNAL)				{					assert(nonterminal.type->nonterminal_class_category==ClassHierarchy::Class::WRAPPER);					nonterminal.multiple_alternatives_mode=false;				}				else if(nr>1)				{					assert(nonterminal.type->nonterminal_class_category==ClassHierarchy::Class::BASE);					nonterminal.multiple_alternatives_mode=true;				}				else if(rule_statement.type || nonterminal.type->nonterminal_class_category==ClassHierarchy::Class::BASE)				{					nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::BASE;					nonterminal.multiple_alternatives_mode=true;				}				else if(nonterminal.type->nonterminal_class_category==ClassHierarchy::Class::UNKNOWN)				{					nonterminal.type->nonterminal_class_category=ClassHierarchy::Class::SINGLE;					nonterminal.multiple_alternatives_mode=false;				}				else					assert(false);				AlternativeData alternative;				alternative.declaration=rule_statement.left;				alternative.expr=rule_statement.right;				if(nonterminal.multiple_alternatives_mode)				{					bool result=process_alternative_type_declaration(alternative, nonterminal, nonterminal.alternatives.size(), rule_statement.type);					if(!result)					{						nonterminal.alternatives.push_back(alternative);						flag=false;						continue;					}

⌨️ 快捷键说明

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