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

📄 process.cpp

📁 Full support for extended regular expressions (those with intersection and complement); Support for
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			cout << "Reference to undefined nonterminal '" << expr_in.symbol->text << "' at ";
			print_terminal_location(cout, expr_in.symbol);
			cout << ".\n";
			return false;
		}
		NonterminalData &nonterminal=data.nonterminals[expr_in.nn];
		
		nonterminal.is_used_in_IN_expressions=true;
		nonterminal.where_it_is_used_in_IN_expressions.push_back(expr_in.symbol);
		
		if(nn>=0)
		{
			PathData &path=data.derivation_paths[nn][expr_in.nn];
			if(!path.v.size() || path.worst!=PathData::IN_EXPRESSION)
			{
				path.v.clear();
				path.v.push_back(make_pair(expr_in.symbol, PathData::IN_EXPRESSION));
				path.worst=PathData::IN_EXPRESSION;
			}
		}
		
		return true;
	}
	else if(typeid(*expr)==typeid(NonterminalExpressionC_Constant))
	{
		NonterminalExpressionC_Constant &expr_const=*dynamic_cast<NonterminalExpressionC_Constant *>(expr);
		if(!strcmp(expr_const.true_or_false->text, "true"))
			expr_const.value=true;
		else if(!strcmp(expr_const.true_or_false->text, "false"))
			expr_const.value=false;
		else
			assert(false);
		return true;
	}
	else
	{
		assert(false);
		return false; // to please the compiler
	}
}

bool check_whether_terminal_symbol_is_in_range(int tn, Terminal *location)
{
	if(tn>=0 && tn<data.variables.alphabet_cardinality)
		return true;
	else
	{
		cout << "Out-of-range symbol " << tn << " at ";
		print_terminal_location(cout, location);
		cout << ".\n";
		return false;
	}
}

bool check_whether_terminal_symbol_is_in_range(vector<int> &v, Terminal *location)
{
	vector<int> v2;
	for(int i=0; i<v.size(); i++)
		if(!(v[i]>=0 && v[i]<data.variables.alphabet_cardinality))
			v2.push_back(v[i]);
	if(v2.size())
	{
		cout << "Out-of-range symbol" << (v2.size()==1 ? " " : "s ");
		for(int i=0; i<v2.size(); i++)
		{
			if(i)
			{
				if(i<v2.size()-1)
					cout << ", ";
				else
					cout << " and ";
			}
			cout << v2[i];
		}
		cout << " in string at ";
		print_terminal_location(cout, location);
		cout << ".\n";
		return false;
	}
	return true;
}

inline bool is_octal_digit(char c) { return c>='0' && c<='7'; }

bool decode_escape_sequences(char *s, vector<int> &v)
{
	static char *escape_sequences="n\nt\tv\vb\br\rf\fa\a\\\\??\'\'\"\"";
	
	int length=strlen(s);
	assert(length>=2 && (s[0]=='\x27' || s[0]=='\x22') && s[0]==s[length-1]);
	s[length-1]=0;
	
	for(int i=1; s[i]; i++)
		if(s[i]!='\\')
			v.push_back(s[i]);
		else
		{
			i++;
			if(!s[i])
				return false;
			
			bool flag=false;
			for(int j=0; escape_sequences[j]; j+=2)
				if(s[i]==escape_sequences[j])
				{
					v.push_back(escape_sequences[j+1]);
					flag=true;
					break;
				}
			if(!flag)
			{
				if(s[i]=='x' || s[i]=='u' || s[i]=='U')
				{
					i++;
					int j;
					for(j=0; isxdigit(s[i+j]); j++);
					if(s[i-1]=='x')
					{
						if(!j || j>8)
							return false;
					}
					else if(s[i-1]=='u')
					{
						if(j>=4)
							j=4;
						else
							return false;
					}
					else if(s[i-1]=='U')
					{
						if(j>=8)
							j=8;
						else
							return false;
					}
					else
						assert(false);
					
					char backup=s[i+j];
					s[i+j]=0;
					int sn;
					sscanf(s+i, "%x", &sn);
					v.push_back(sn);
					s[i+j]=backup;
					i+=j-1;
				}
				else if(is_octal_digit(s[i]))
				{
					i++;
					int j;
					for(j=0; is_octal_digit(s[i+j]); j++);
					if(!j || j>11 || (j==11 && s[i]>='3'))
						return false;
					
					int sn=0;
					int factor=1;
					for(int k=j+i-1; k>=i; k--)
					{
						sn+=(s[k]-'8')*factor;
						factor*=8;
					}
					v.push_back(sn);
					i+=j-1;
				}
				else
					return false;
			}
		}
	
	return true;
}

bool high_level_decode_escape_sequences(Terminal *t, string &s)
{
	vector<int> v;
	bool result=decode_escape_sequences(t->text, v);
	if(!result)
	{
		cout << "Ill-formed escape sequences in string at ";
		print_terminal_location(cout, t);
		cout << ".\n";
		return false;
	}
	bool flag=true;
	for(int k=0; k<v.size(); k++)
		if(!(v[k]>=0 && v[k]<data.variables.alphabet_cardinality))
		{
			cout << data.variables.alphabet_cardinality << "\n";
			cout << "Out-of-range characters in string at ";
			print_terminal_location(cout, t);
			cout << ".\n";
			flag=false;
			break;
		}
	if(!flag)
		return false;
	
	s=""; // s.clear(); /* some old g++ does not have clear() :-( */
	for(int k=0; k<v.size(); k++)
		s+=char(v[k]);
	return true;
}

bool get_character_from_the_string_that_is_expected_to_be_exactly_one_character_long(NonterminalExpressionS *expr_s, int nn, int &result)
{
	if(!process_expression_proc(expr_s, nn, false))
		return false;
	
	if(expr_s->is_nts)
	{
		cout << "Expecting a string at ";
		print_terminal_location(cout, expr_s->symbol);
		cout << ".\n";
		return false;
	}
	
	if(expr_s->s.size()!=1)
	{
		cout << "The string should be exactly one character long at ";
		print_terminal_location(cout, expr_s->symbol);
		cout << ".\n";
		return false;
	}
	
	result=expr_s->s[0];
	
	return true;
}

bool process_option_statement(NonterminalOptionStatement &option_statement)
{
	char *s=option_statement.left->text; // make me const
	
#if 0
	map<const char *, variable_base *, NullTerminatedStringCompare>::iterator p=data.variables.database.find(s);
	if(p==data.variables.database.end())
	{
		cout << "Assignment to unknown variable '" << s << "' at ";
		print_terminal_location(cout, option_statement.left);
		cout << ".\n";
		return false;
	}
	return true;
#endif
	
	map<char *, AssignmentData, NullTerminatedStringCompare>::iterator p=data.assignments.find(s);
	if(p!=data.assignments.end())
	{
		cout << "Duplicate assignment to variable '" << s << "' at ";
		print_terminal_location(cout, option_statement.left);
		cout << " (earlier assignment at ";
		print_terminal_location(cout, (*p).second.declaration->left);
		cout << ").\n";
		return false;
	}
	
	if(!variable_exists(s))
	{
		cout << "Warning: assignment to unknown variable '" << s << "' at ";
		print_terminal_location(cout, option_statement.left);
		cout << " will probably have no effect.\n";
	}
	
	AssignmentData ad;
	ad.declaration=&option_statement;
	
	bool flag=true;
	for(int j=0; j<option_statement.right.size(); j++)
	{
		char *s1=option_statement.right[j]->text;
		char *final_s;
		AssignmentData::ValueType vt;
		if(!strcmp(s1, "true") || !strcmp(s1, "yes") || !strcmp(s1, "on"))
		{
			vt=AssignmentData::VALUE_TRUE;
			final_s=s1;
		}
		else if(!strcmp(s1, "false") || !strcmp(s1, "no") || !strcmp(s1, "off"))
		{
			vt=AssignmentData::VALUE_FALSE;
			final_s=s1;
		}
		else if(typeid(*option_statement.right[j])==typeid(Whale::TerminalId))
		{
			vt=AssignmentData::VALUE_ID;
			final_s=s1;
		}
		else if(typeid(*option_statement.right[j])==typeid(Whale::TerminalString))
		{
			vt=AssignmentData::VALUE_STRING;
			string str;
			if(!high_level_decode_escape_sequences(option_statement.right[j], str))
			{
				flag=false;
				continue;
			}
			final_s=strdup(str.c_str());
		}
		else if(typeid(*option_statement.right[j])==typeid(Whale::TerminalNumber))
		{
			vt=AssignmentData::VALUE_NUMBER;
			final_s=s1;
		}
		else if(typeid(*option_statement.right[j])==typeid(Whale::TerminalHexNumber))
		{
			vt=AssignmentData::VALUE_HEX_NUMBER;
			assert(s1[0]=='0' && tolower(s1[1])=='x' && s1[2]);
			final_s=s1+2;
		}
		else if(typeid(*option_statement.right[j])==typeid(Whale::TerminalCode))
		{
			vt=AssignmentData::VALUE_CODE;
			const char *s=option_statement.right[j]->text;
			int k=(s[0]=='{' ? 1 : 2);
			string str(s+k, s+strlen(s)-k);
			final_s=strdup(str.c_str());
		}
		else
			assert(false);
		
		ad.values.push_back(std::make_pair(final_s, vt));
	}
	
	data.assignments[s]=ad;
	
	return flag;
}

bool process_grammar(NonterminalS *S)
{
	bool flag=true;
	
	data.variables.alphabet_cardinality=256; // this assignment of a *temporary* value is a horrible hack. Ought to do it better.
	
	for(int i=0; i<S->statements.size(); i++)
	{
		if(typeid(*S->statements[i])==typeid(NonterminalRuleStatement))
		{
			NonterminalRuleStatement &rule_statement=*dynamic_cast<NonterminalRuleStatement *>(S->statements[i]);
			
			char *s=rule_statement.left->text;
			int nn=data.find_nonterminal(s);
			if(nn==-1)
			{
				NonterminalData new_nonterminal;
				new_nonterminal.name=s; // it's not an error.
				nn=data.nonterminals.size();
				data.nonterminals.push_back(new_nonterminal);
			}
			
			NonterminalData &nonterminal=data.nonterminals[nn];
			nonterminal.rules.push_back(&rule_statement);
		}
		else if(typeid(*S->statements[i])==typeid(NonterminalActionStatement))
		{
			// doing nothing by now
		}
		else if(typeid(*S->statements[i])==typeid(NonterminalStartConditionsStatement))
		{
			NonterminalStartConditionsStatement &start_conditions_statement=*dynamic_cast<NonterminalStartConditionsStatement *>(S->statements[i]);
			
			for(int j=0; j<start_conditions_statement.names.size(); j++)
			{
				char *s=start_conditions_statement.names[j]->text;
				int ssn=data.find_start_condition(s);
				
				if(ssn==-1)
				{
					StartConditionData new_start_condition;
					new_start_condition.name=s;
					new_start_condition.declaration=start_conditions_statement.names[j];
					ssn=data.start_conditions.size();
					data.start_conditions.push_back(new_start_condition);
				}
				else
				{
					StartConditionData &start_condition=data.start_conditions[ssn];
					cout << "Start condition ";
					cout << "'" << start_condition.name << "'";
					cout << ", declared at ";
					print_terminal_location(cout, start_condition.declaration);
					cout << ", is redeclared at ";
					print_terminal_location(cout, start_conditions_statement.names[j]);
					cout << "; redeclaration ignored.\n";
				}
			}
		}
		else if(typeid(*S->statements[i])==typeid(NonterminalOptionStatement))
		{
			bool result=process_option_statement(*dynamic_cast<NonterminalOptionStatement *>(S->statements[i]));
			if(!result)
				flag=false;
		}
		else if(typeid(*S->statements[i])==typeid(NonterminalInvalidStatement))
			flag=false; // there was a parse error.
		else
			assert(false);
	}
	
	if(!data.start_conditions.size())
	{
		// if no start conditions were defined, a single start
		// condition named 'INITIAL' should be created.
		
		StartConditionData initial;
		initial.name="INITIAL";
		initial.declaration=NULL;
		data.start_conditions.push_back(initial);
		
		data.variables.start_conditions_enabled=false;
	}
	else
		data.variables.start_conditions_enabled=true;
	
	if(!assign_values_to_variables_stage_zero()) return false;
	cout << "Alphabet cardinality is " << data.variables.alphabet_cardinality << ".\n";
	
	int n=data.nonterminals.size();
	
	data.derivation_paths.destructive_resize(n, n);
	for(int i=0; i<n; i++)
	{
		NonterminalData &nonterminal=data.nonterminals[i];
		
		for(int j=0; j<nonterminal.rules.size(); j++)
		{
			// Prof. Zhogolev would have killed me for this trick:
			bool old_value=nonterminal.can_be_used_in_IN_expressions;
			nonterminal.can_be_used_in_IN_expressions=true;
			
			if(!process_expression_proc(nonterminal.rules[j]->right, i, true))
			{
				cout << nonterminal.name << " " << j << "\n";
				flag=false;
			}
			
			if(!nonterminal.can_be_used_in_IN_expressions)
				nonterminal.locations_of_offending_rules.push_back(nonterminal.rules[j]->arrow);
			else
				nonterminal.can_be_used_in_IN_expressions=old_value;
			
			// I do feel ashamed, honestly!
		}
	}
	
	for(int i=0; i<S->statements.size(); i++)
	{
		if(typeid(*S->statements[i])==typeid(NonterminalActionStatement))
		{
			NonterminalActionStatement &action_statement=*dynamic_cast<NonterminalActionStatement *>(S->statements[i]);
			
			char *s;
			bool is_special;

⌨️ 快捷键说明

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