根据文法进行表达式推导(编译原理)
1、实验要求
已知文法:
E-> T | E +T
T-> F | T * F
F->(E) | i
请给出下述表达的推导公式:
- i+i
- (i)
- (i+i)*i
2、实验原理
通过文法进行推导分为左推导和右推导
例如: i+i
左推导:
E | ||||
---|---|---|---|---|
E | + | T | ||
T | + | T | ||
F | + | T | ||
i | + | T | ||
i | + | F | ||
i | + | i |
右推导:
E | ||||
---|---|---|---|---|
E | + | T | ||
E | + | F | ||
E | + | i | ||
T | + | i | ||
F | + | i | ||
i | + | i |
3、算法设计(左推导)
通过文法我们可以发现,文法总共分为3行,每一行的左边均为一个非终结符,第一行是E,第二行是T,第三行是F。每一行的右边都包括两部分,第一行是一个单字符E以及E和T的相加;第二行是一个单字符T以及T和F的乘积;第三行是(E)以及终结符i。由此规律,我们可以做出以下算法设计思想:
- 输入需进行推导的表达式
- 对表达式每个字符逆序进行文法第一行的判断,即:
(1)判断表达式是否有‘+’运算符(括号内有‘+’除外)。是,输出“E->E+T”,‘+’运算符之前的所有字符返回进行操作2,‘+’之后的字符进行操作3;否,进行下一步。
(2)输出“E->T”,所有字符进行操作3 - 对表达式每个字符逆序进行文法第二行的判断,即:
(1)判断表达式是否有‘ ∗ * ∗’运算符(括号内有‘ ∗ * ∗’除外)。是,输出“T>T ∗ * ∗F”,‘ ∗ * ∗’运算符之前的所有字符返回进行操作3,‘ ∗ * ∗’之后的字符进行操作4;否,进行下一步。
(2)输出“T->F”,所有字符进行操作4 - 对表达式每个字符逆序进行文法第三行的判断,即:
(1)若第一个字符是否为。是,’ ( ( (‘,输出”F->(E)”,然后将该字符串的’(‘、’)'两个字符删去,返回操作2;否,输出“F->i”,操作结束。
4、实验过程
- 首先进行函数的声明和主函数建立,并定义全局变量
//全局变量
char str[10];//存储
int step;//记录推导步长
void DeduceE(int l,int r);//文法第一行
void DeduceT(int l,int r);//文法第二行
void DeduceF(int l,int r);//文法第三行
void Init();
//主函数
int main(){
Init();//初始化,输入文法和推导式
DeduceE(0,strlen(str));//进行文法的推导
}
- 初始化,输入文法内容和推导式
//初始化
void Init(){
cout<<"文法为:"<<endl<<"E->T|E+T"<<endl<<"T->F|T*F"<<endl<<"F->(E)|i"<<endl;
cout<<"输入推导式:"<<endl;
cin>>str;
cout<<"推导表达式为:"<<endl;
}
- 开始对推导式进行文法的分析
第一行文法分析:
//首字符E,第一行文法
void DeduceE(int l,int r){
int bracket=0;//记录括号
int symbol=0;//记录符号
for(int i=r-1;i>=l;i--){//判断字符串是否含括号和运算符
if(str[i]==')')
bracket++;
if(str[i]=='(')
bracket--;
if(!bracket){//没有括号或不再括号内部,则进行运算符操作(不对括号内的内容进行运算符处理)
if(str[i]=='+'){
symbol=1;
cout<<"step "<<step<<":"<<"E->E+T"<<endl;
step++;
DeduceT(l,i);//转去进行文法第二行判断
DeduceE(i+1,r);//继续进行文法第一行判断
break;
}
}
}
if(!symbol){//字符串既没括号,也没字符
cout<<"step "<<step<<":"<<"E->T"<<endl;
step++;
DeduceT(l,r);//转去进行文法第二行判断
}
}
因文法第二行分析和第一行大致相同,就不列举代码,直接展示文法第三行的分析
//首字符F,第三行文法
void DeduceF(int l,int r){
char a[10];
int i,j=0;
if(str[l]=='('){//判断是否含括号
cout<<"step "<<step<<":"<<"F->(E)"<<endl;
step++;
for(i=0;i<strlen(str);i++)//删除字符串的’(‘’)‘两个字符
if(str[i]!=')')
a[j++]=str[i];
memset(str,0,sizeof(str));
for(i=0;i<strlen(a);i++)
str[i]=a[i];
DeduceE(l+1,strlen(str));//返回文法第一行
}
else{//无括号,直接输出值i
cout<<"step "<<step<<":"<<"F->i"<<endl;
step++;
}
}
4、源代码和截图
程序已经过调试,无编译错误
#include<iostream>
#include<string.h>
using namespace std;
//全局变量
char str[10];//存储
int step;//记录推导步长
void DeduceE(int l,int r);//文法第一行
void DeduceT(int l,int r);//文法第二行
void DeduceF(int l,int r);//文法第三行
void Init();
//主函数
int main(){
Init();//初始化,输入文法和推导式
DeduceE(0,strlen(str));//进行文法的推导
}
//初始化
void Init(){
cout<<"文法为:"<<endl<<"E->T|E+T"<<endl<<"T->F|T*F"<<endl<<"F->(E)|i"<<endl;
cout<<"输入推导式:"<<endl;
cin>>str;
cout<<"推导表达式为:"<<endl;
}
//首字符F,第三行文法
void DeduceF(int l,int r){
char a[10];
int i,j=0;
if(str[l]=='('){//判断是否含括号
cout<<"step "<<step<<":"<<"F->(E)"<<endl;
step++;
for(i=0;i<strlen(str);i++)
if(str[i]!=')')
a[j++]=str[i];
memset(str,0,sizeof(str));
for(i=0;i<strlen(a);i++)
str[i]=a[i];
DeduceE(l+1,strlen(str));//返回文法第一行
}
else{//无括号,直接输出值i
cout<<"step "<<step<<":"<<"F->i"<<endl;
step++;
}
}
//首字符T,第二行文法
void DeduceT(int l,int r){
int bracket=0;//记录括号
int symbol=0;//记录符号
for(int i=r-1;i>=l;i--){//判断字符串是否含括号和运算符
if(str[i]==')')
bracket++;
if(str[i]=='(')
bracket--;
if(!bracket){//没有括号或不在括号内部,则进行运算符操作(不对括号内的内容进行运算符处理)
if(str[i]=='*'){
symbol=1;
cout<<"step "<<step<<":"<<"T->T*F"<<endl;
step++;
DeduceF(l,i);//转去进行文法第三行判断
DeduceT(i+1,r);//继续进行文法第一行判断
break;
}
}
}
if(!symbol){//字符串既没括号,也没字符
cout<<"step "<<step<<":"<<"T->F"<<endl;
step++;
DeduceF(l,r);//转去进行文法第三行判断
}
}
//首字符E,第一行文法
void DeduceE(int l,int r){
int bracket=0;//记录括号
int symbol=0;//记录符号
for(int i=r-1;i>=l;i--){//判断字符串是否含括号和运算符
if(str[i]==')')
bracket++;
if(str[i]=='(')
bracket--;
if(!bracket){//没有括号或不再括号内部,则进行运算符操作(不对括号内的内容进行运算符处理)
if(str[i]=='+'){
symbol=1;
cout<<"step "<<step<<":"<<"E->E+T"<<endl;
step++;
DeduceT(l,i);//转去进行文法第二行判断
DeduceE(i+1,r);//继续进行文法第一行判断
break;
}
}
}
if(!symbol){//字符串既没括号,也没字符
cout<<"step "<<step<<":"<<"E->T"<<endl;
step++;
DeduceT(l,r);//转去进行文法第二行判断
}
}