根据文法进行表达式推导

根据文法进行表达式推导(编译原理)

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. 输入需进行推导的表达式
  2. 对表达式每个字符逆序进行文法第一行的判断,即:
    (1)判断表达式是否有‘+’运算符(括号内有‘+’除外)。是,输出“E->E+T”,‘+’运算符之前的所有字符返回进行操作2,‘+’之后的字符进行操作3;否,进行下一步。
    (2)输出“E->T”,所有字符进行操作3
  3. 对表达式每个字符逆序进行文法第二行的判断,即:
    (1)判断表达式是否有‘ ∗ * ’运算符(括号内有‘ ∗ * ’除外)。是,输出“T>T ∗ * F”,‘ ∗ * ’运算符之前的所有字符返回进行操作3,‘ ∗ * ’之后的字符进行操作4;否,进行下一步。
    (2)输出“T->F”,所有字符进行操作4
  4. 对表达式每个字符逆序进行文法第三行的判断,即:
    (1)若第一个字符是否为。是,’ ( ( (‘,输出”F->(E)”,然后将该字符串的’(‘、’)'两个字符删去,返回操作2;否,输出“F->i”,操作结束。

4、实验过程

  1. 首先进行函数的声明和主函数建立,并定义全局变量
//全局变量 
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));//进行文法的推导 
}
  1. 初始化,输入文法内容和推导式
//初始化 
void Init(){
	cout<<"文法为:"<<endl<<"E->T|E+T"<<endl<<"T->F|T*F"<<endl<<"F->(E)|i"<<endl;
	cout<<"输入推导式:"<<endl;
	cin>>str;
	cout<<"推导表达式为:"<<endl; 
}
  1. 开始对推导式进行文法的分析
    第一行文法分析:
//首字符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);//转去进行文法第二行判断 
	} 	
} 




 

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 14
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值