编译原理实验2-递归下降分析–表达式求值

http://blog.csdn.net/xuzengqiang/article/details/7596357

这是源地址,个人并没有做太大改动,于是就不写原创。

写编译原理实验的时候,当写到

  1. Expression->Term|Expression+Term|Expression-Term  
  2.   
  3. Term->Factor|Term*Factor|Term/Factor  
  4.   
  5. Factor->(Expression)| number 
这里的时候,由于不能正确解析expression、term 与factor苦恼了半天。(老师就讲了个大概,根本不能直接使用啊!!!!!虽然老师很漂亮)

这里原作者进行了语法改动。

  1. E->TE2  
  2. E2->+TE2 | -TE2 | ε  
  3. T->*FT2  
  4. T2->*FT2 | /FT2 |ε  
  5. F->(E) | i  
将后面的视为同级,极大地方便了编码。这里在编译原理中使用的方法叫做利用右递归消除左递归的方法。极大地方便了编码。

版本1:

原作者的编码我只是进行了小的改动能识别多位数

#include<iostream> 
#include<cstdio> 
#include<string> 
using namespace std; 
char expr[1010];
int start=0;
string T();
string T2();
string F();
string E2(); 
string F2();
string E() 
{   string a=T(),b=E2();     
    return a+b; 
} 
string E2() 
{   string a,b;     
    switch(expr[start])     
    {   case '+':start++;a=T();b=E2();return a+"+"+b;     
        case '-':start++;a=T();b=E2();return a+"-"+b;     
        default:return "";     
    } 
} 
string T() 
{   string a=F(),b=T2();     
    return a+b; 
} 
string T2() 
{   string a,b;     
    switch(expr[start])     
    {   case '*':start++;a=F();b=T2();return a+"*"+b;     
        case '/':start++;a=F();b=T2();return a+"/"+b;     
        default:return "";     
    } 
} 
string F() 
{   if(expr[start]=='(')     
    {   string a;         
        start++;a=E();start++;         
        return a;     
    }     
    return F2(); 
} 
int min(int a,int b)
{
	if(a<b)
		return a;
	return b;
}
string F2()
{
	string ans;
	for(int i=start;i<strlen(expr);i++)
	{
		if(expr[i]=='*'||expr[i]=='-'||expr[i]=='+'||expr[i]=='/'||expr[i]==')')
		{
			start=i;
			return ans;
		}
		else
		{
			char *p=&expr[i];
			ans.append(p,1);
		}
	}
	return ans;
}
int main() 
{   scanf("%s",expr);     
    start=0;     
    cout<<E()<<endl; 
} 


然后是版本2:

  1. Expression->Term|Expression+Term|Expression-Term  
  2.   
  3. Term->Factor|Term*Factor|Term/Factor  
  4.   
  5. Factor->(Expression)| number |id
  6.  
  7. Define->(int|float|num) id=num 

最终实验我们要计算出值,于是我进行了一次比较大的改动,先识别是否有Define,将定义名称保存在string name[]中,定义的实际值保存在double num[]中。如果没有实际值,bool flag[]则为0。然后对后缀表达式中所有数字和id用加#来分隔。然后根据后缀表达式计算出结果。(马上考四级了,还没过啊)!!!!!

#include<iostream> 
#include<cstdio> 
#include<string> 
#include<stack>
using namespace std; 

string name[100];
bool flag[100];
double num[100];
char expr[1010];
int id=0;
int start=0;

string T();
string T2();
string F();
string E2(); 
string F2();

string E() 
{   string a=T(),b=E2();     
    return a+b; 
} 
string E2() 
{   string a,b;     
    switch(expr[start])     
    {   case '+':start++;a=T();b=E2();return a+"+"+b;     
        case '-':start++;a=T();b=E2();return a+"-"+b;     
        default:return "";     
    } 
} 
string T() 
{   string a=F(),b=T2();     
    return a+b; 
} 
string T2() 
{   string a,b;     
    switch(expr[start])     
    {   case '*':start++;a=F();b=T2();return a+"*"+b;     
        case '/':start++;a=F();b=T2();return a+"/"+b;     
        default:return "";     
    } 
} 
string F() 
{   if(expr[start]=='(')     
    {   string a;         
        start++;a=E();start++;         
        return a;     
    }     
    return F2(); 
} 
int min(int a,int b)
{
	if(a<b)
		return a;
	return b;
}
string F2()
{
	string ans="#";
	for(int i=start;i<strlen(expr);i++)
	{
		if(expr[i]=='*'||expr[i]=='-'||expr[i]=='+'||expr[i]=='/'||expr[i]==')')
		{
			start=i;
			return ans;
		}
		else
		{
			char *p=&expr[i];
			ans.append(p,1);
		}
	}
	return ans;
}
double stringtodouble(string tmp)
{
	double d=0;
	double k=10;
	bool fa=0;
	for(int i=0;i<tmp.length();i++)
	{
		if(!fa)
		{
			if(tmp[i]!='.')
			d=d*10+(int)(tmp[i]-'0');
			else fa=1;
		}
		else 
		{
			d+=((int)(tmp[i]-'0'))/k;
			k*=10;
		}
	}
	return d;
}
void gtmdbyyl2(string tmp)
{
	if(tmp.find("=")!=string::npos)
	{
		string na=tmp.substr(0,tmp.find("="));
		string va=tmp.substr(tmp.find("=")+1);
		name[id]=na;
		num[id]=stringtodouble(va);
		flag[id]=1;
	}
	else
	{
		name[id]=tmp;
		flag[id]=0;
	}
	id++;
}
void gtmdbyyl(string tmp)
{
	while(tmp.find(",")!=string::npos)
	{
		gtmdbyyl2(tmp.substr(0,tmp.find(",")));
		tmp=tmp.substr(tmp.find(",")+1);
	}
	if(tmp.find(";")!=string::npos)
	{
		gtmdbyyl2(tmp.substr(0,tmp.length()-1));
	}
	else 
		gtmdbyyl2(tmp);
}
int findname(string tmp)//-1代表没有 -2代表没有值
{
	for(int i=0;i<id;i++)
	{
		if(tmp==name[i])//别问我为什么不用运算符重载,我用了不对,我也不知道为什么。
		{
			if(flag[i]==1)
				return i;
			else
				return -2;
		}
	}
	return -1;
}
bool isnum(string tmp)
{
	bool fa=0;
	for(int i=0;i<tmp.length();i++)
	{
		if(tmp[i]=='.'&&!fa)
			fa=1;
		else if(tmp[i]>='0'&&tmp[i]<'9')
			continue;
		else return false;
	}
	return true;
}
void ans()
{
	string key=E();
	//cout<<key<<endl;
	stack<double> va;
	string c="";
	for(int i=1;i<key.length();i++)
	{
		
		if(key[i]!='*'&&key[i]!='/'&&key[i]!='+'&&key[i]!='-'&&key[i]!='#')
		{
			char *p=&key[i];
			c.append(p,1);
			if(i==key.length()-1)
			{
				if(isnum(c))
				{
					va.push(stringtodouble(c));
					c.clear();
				}
				else
				{
					int ans=findname(c);
					if(ans==-1)
					{
						cout<<"error"<<endl;
						exit(0);
					}
					else if (ans==-2)
					{
						cout<<"error"<<endl;
						exit(0);
					}
					else
						va.push(num[ans]);
				}
			}
		}
		else
		{
			if(c!="")
			{
				if(isnum(c))
				{
					va.push(stringtodouble(c));
					c.clear();
				}
				else
				{
					int ans=findname(c);
					if(ans==-1)
					{
						cout<<"error"<<endl;
						return;
					}
					else if (ans==-2)
					{
						cout<<"error"<<endl;
						return;
					}
					else
						va.push(num[ans]);
					c.clear();
				}
			}
			if(key[i]=='*')
			{
				if(va.size()>=2){
					double x=va.top();va.pop();double y=va.top();va.pop();va.push(x*y);}
				else{
					cout<<"error"<<endl;return;}
			}
			else if(key[i]=='/')
			{
				if(va.size()>=2){
					double x=va.top();va.pop();double y=va.top();va.pop();va.push(x/y);}
				else{
					cout<<"error"<<endl;return;}
			}
			else if(key[i]=='+')
			{
				if(va.size()>=2){double x=va.top();va.pop();double y=va.top();va.pop();va.push(x+y);}
				else if(va.size()==0){cout<<"error"<<endl;return;}

			}
			else if(key[i]=='-')
			{
				if(va.size()>=2)
				{double x=va.top();va.pop();double y=va.top();va.pop();va.push(x-y);}
				else if(va.size()==0)
				{cout<<"error"<<endl;return;}
				else{ 
					double x=va.top();x=-x;va.pop();va.push(x);
				}
			}
		}
	}
	cout<<"输出:\n"<<va.top()<<endl;
}
bool input(string tmp)
{
	if((tmp.substr(0,3)=="int")&&(tmp[3]==' '))
	{
		gtmdbyyl(tmp.substr(4));
	}
	else if((tmp.substr(0,6)=="double")&&(tmp[6]==' '))
	{
		gtmdbyyl(tmp.substr(7));
	}
	else if((tmp.substr(0,5)=="float")&&(tmp[5]==' '))
	{
		gtmdbyyl(tmp.substr(6));
	}
	else
	{
		strcpy(expr,tmp.c_str());
		ans();
		return false;
	}
	return true;
}
int main() 
{   
	string c;
	freopen("in.txt","r",stdin);
	cout<<"输入:"<<endl;
	while(getline(cin,c))
	{
		//cout<<c<<endl;
		//getchar();
		if(!input(c))
		{
			cout<<"输入continue回车继续测试,输入end结束测试"<<endl;
			//getchar();
		}
		else
			continue;
		string key;
		cin>>key;
		//cout<<key<<endl;
		if(key=="continue")
		{			
			id=0;
			start=0;
			memset(expr,'\0',sizeof(expr));
			for(int i=0;i<100;i++)
			{
				name[i].clear();
				flag[i]=0;
				num[i]=0;
			}
			cout<<"输入:"<<endl;
			getchar();
		}
		else if(key=="end")
		{
			break;
		}
	}
} 



猜你喜欢

转载自blog.csdn.net/yizhangbiao/article/details/73236908