编译原理中LL(1)分析程序的设计---用c++程序语言实现

一.前言

作为当代大学生的我,我喜极而泣,最后一个编译原理实验报告了,这次是一个提高性实验报告。肝完这个,编译原理,这门课,再也没有实验报告了,我再也不要担心我没有头发了。行了,废话不多说,我直接呈现内容吧。实验心得这类的什么东西,还是留一点小小的隐私吧。直接肝!!

二.内容

1.问题描述
预测分析属于自上而下不带回溯的语法分析方法,这种分析方法要求文法是LL(1)的,语法分析程序的输入是终结符号串(即单词符号串,一一个“#”结尾),如果输入串是句子,则输出YES,否则输出NO和错误信息。
以算术表达式的文法为例来进行LL(1)分析程序的设计。
(1)文法: 设LL(1)文法G为:
E→TE’
E’→+TE’|ε
T→FT’
T’→*FT’|ε
F→(E)|i
注:i为整型常数或者为标示符表示的整型变量。
(2)分析表 设LL(1)分析表M如下表所示。
在这里插入图片描述

2.问题实现的算法
预测分析算法 实现预测分析算法需要使用一个分析栈stack存放文法符号。变量top为stack的栈顶指针,变量a存放当前输入符号。LL(1)分析表为整型二维数组M[m][n].
x为栈顶符号
分析算法思想:
①若x=a=’#’,则分析成功,分析器停止工作。
②若x=a≠’#’,即栈顶符号x与当前扫描的输入符号a匹配;则将x从栈顶弹出,输入指针指向下一个输入符号,继续对下一个字符进行分析。
③若x为一非终结符号A,则查M[A,a]:
1.若M[A,a]中为一个A的产生式,则将A自栈顶弹出,并将M[A,a]中的产生式右部符号串按逆序逐一入栈;如果M[A,a]中的产生式为A->ε,则只将A自栈顶弹出。
2.若M[A,a]中为空,则发现语法错误,调用出错处理程序进行处理。
控制程序描述如下:
将“#“和文法开始符号依次压入栈中;
把第一个输入符号读入a;
do{
把栈顶符号弹出并放入x中;
if(x∈VT)
{
if(x==a)
{
if(a!=’#’) 将下一个输入符号读入a;
}
else error();
}
else
if(M[x,a]=”x→Y1Y2…Yk”)
{
按逆序依次把Yk,Yk-1…Y1压入栈中,
输出”x→Y1Y2…Yk”;
}
else error();
}while (x!=”#”)

3.问题选用的数据结构

实现预测分析算法需要使用一个分析栈stack存放文法符号。变量top为stack的栈顶指针,变量a存放当前输入符号。LL(1)分析表为整型二维数组M[m][n].x为栈顶符号,ex存放输入串,j为输入串的指针。non_sign数组存放非终结符号,ter_sign数组存放终结符号,字符串数组form存放产生式。本程序采用c++语言来实现。
non_sign:char[]//存放非终结符号
ter_sign:char[]//存放终结符号
form:string[]//存放产生式
M:int[][]//分析表
stack:char[]//符号栈(分析栈)
a:char //当前输入符号
ex:string//输入串
j:int //输入串的指针

4.整个程序的流程图
在这里插入图片描述

5.详细设计(设计各个函数)
本程序将如下设置为全局变量,故下函数均没有形参(print_tip函数例外)
non_sign:char[]//存放非终结符号
ter_sign:char[]//存放终结符号
form:string[]//存放产生式
M:int[][]//分析表
stack:char[]//符号栈(分析栈)
a:char //当前输入符号
ex:string//输入串
j:int //输入串的指针

各个函数:
void init_form()//算术表达式的产生式的初始化 //@代替ε A代替E’ B代替T’

void init_table()//LL(1)分析表的初始化

void suanshu_table()//赋值成算术表达式的LL(1)分析表

void display()//显示主界面

void print_match()//匹配情况

void error()//错误情况

int seek_non()//找到当前非终结符号对应的下标 返回值非终结符号对应的下标

int seek_ter()//找到当前终结符号对应的下标 返回值当前终结符号对应的下标

void print_tip(char t)//输出信息,弹出栈顶元素,,
//输入当前栈顶元素

6.程序功能效果图:
在这里插入图片描述

在这里插入图片描述

3.代码

#include<iostream>
#include<string>
#include<string.h> 
#define max 100 
#include<stdlib.h>
using namespace std;
int i;//循环变量 

char non_sign[10]={'E','A','T','B','F'};//存放非终结符号 从0开始 
char ter_sign[10]={'i','+','*','(',')','#'};//存放终结符号 从0开始 
string form[10];//存放产生式 从0开始
int M[5][6];//LL(1)分析表 从0开始 
char stack[max];//分析栈(符号栈)  从1开始  
char x;//栈顶符号   
int top=0;//栈顶指针
char a;//当前输入的符号
string ex;//输入串  从0开始 
int j=0;//输入串指针 
int main(){
	void init_form();
	void init_table();
	void suanshu_table();
	void display(); 
	void print_match();
	int seek_non();
	int seek_ter();
	void error();
	void print_tip(char t);//输出信息,弹出栈顶元素,,
	int flag;//分析表中的数  
	init_form();//算术表达式的产生式的初始化
	init_table();//LL(1)分析表的初始化
	suanshu_table();//赋值成算术表达式的LL(1)分析表
	display();//显示主界面 
	
	//将#和文法开始符依次压入栈中
	top++;
	stack[top]='#';
	top++;
	stack[top]='E';
	
	a=ex[j];//把第一个输入符号读入a
	
	cout<<endl;
	cout<<"符号栈";
	cout<<'\t';
	cout<<"当前输入符号";
	cout<<'\t';
	cout<<"输入串"; 
	cout<<'\t';
	cout<<"说明"<<endl; 
	
	do{
		
		x=stack[top];//把栈顶符号弹出并放入x中 
		print_tip(x);//输出信息,弹出栈顶元素,,
		top--;
		if(x<'A'||x>'Z'){//栈顶符号是终结符号 
			if(x==a){//匹配  
				if(a!='#'){
					j++;
					a=ex[j];//将下一个输入符号读入a 
					print_match();//匹配情况
					cout<<a<<endl;
				}
				else{//x=a='#'的情况 
					cout<<",匹配";
				} 
//					cout<<",匹配";
			}
			else{
					error();//错误情况 
					exit(0);
				} 
		}
		else{//栈顶符号是非终结符号
			flag=M[seek_non()] [seek_ter()];
			if(flag!=-1){
				if(form[flag][3]=='@'){
//					top--;
					cout<<",因M["<<x<<","<<a<<"]中为"<<form[flag]<<",故不压栈"<<endl;
				}
				else{
					for(i=form[flag].size()-1;i>=3;i--){//按逆序依次将产生式的候选式压入栈 
						top++;
						stack[top]=form[flag][i];
					}
					cout<<",将M["<<x<<","<<a<<"]中为"<<form[flag]<<"的";
					for(i=3;i<form[flag].size();i++){
						cout<<form[flag][i];
					} 
					cout<<"逆序压栈"<<endl; 
				}
			}
			else{
				error();
				exit(0);
			}
		} 
		
	}while(x!='#');
	if(x==a){
//		for(i=1;i<=top;i++){//符号栈 
//			cout<<stack[i];
//		} 
//		cout<<'\t';
//		cout<<'\t';
//		cout<<a;//当前输入符号 
//		cout<<'\t';
//		for(i=j+1;i<=ex.size();i++){//输入串 
//			cout<<ex[i];
//		}
//		cout<<'\t';
		cout<<",分析成功,YES,accept!";
	} 
	return 0;
}

void init_form(){//算术表达式的产生式的初始化    //@代替ε A代替E'  B代替T' 
	form[0]="E->TA";
	form[1]="A->+TA";
	form[2]="A->@"; 
	form[3]="T->FB";
	form[4]="B->*FB";
	form[5]="B->@";
	form[6]="F->(E)";
	form[7]="F->i";
}

void init_table(){//LL(1)分析表的初始化 
	int i;//循环变量 
	int j; //循环变量
	for(i=0;i<5;i++){
		for(j=0;j<6;j++){
			M[i][j]=-1;
		}
	} 
}

void suanshu_table(){//赋值成算术表达式的LL(1)分析表
	M[0][0]=0;M[0][3]=0;//E->TA
	M[1][1]=1;         //A->+TA
	M[1][4]=2;M[1][5]=2;//A->@
	M[2][0]=3;M[2][3]=3;//T->FB
	M[3][1]=5;M[3][4]=5;M[3][5]=5;//B->@
	M[3][2]=4;//B->*FB
	M[4][0]=7;//F->i
	M[4][3]=6;//F->(E)
}

void display(){//显示主界面 
	cout<<"***************@代替ε A代替E'  B代替T'*****************"<<endl;
	cout<<"算术表达式的文法为:"<<endl;
	for(i=0;i<8;i++){
		cout<<'\t'<<form[i]<<endl;
	}
	cout<<"****************************************************"<<endl;
	cout<<"请输入一个算术表达式串(以#结束):(串只能以i,+,*,(,)构成)"<<endl;
	cin>>ex;
	ex[ex.size()]='#';//用户忘记输入#,系统自动加上 
}

void print_match(){//匹配情况 
//	cout<<'\t';
//	for(i=1;i<=top;i++){//符号栈 
//		cout<<stack[i];
//	} 
//	cout<<'\t';
//	cout<<'\t';
//	cout<<a;//当前输入符号 
//	cout<<'\t';
//	for(i=j+1;i<=ex.size();i++){//输入串 
//		cout<<ex[i];
//	}
//	cout<<'\t';  //说明 
	cout<<",匹配";
	cout<<",读出输入串的下一个输入符号"; 
}

void error(){//错误情况 
	for(i=1;i<=top;i++){
		cout<<stack[i];
	} 
	cout<<'\t';
	cout<<a;
	cout<<'\t';
	for(i=j+1;i<ex.size();i++){
		cout<<ex[i];
	}
	cout<<'\t';
	cout<<"NO,输入的符号不正确!!"<<endl;
} 

int seek_non(){//找到当前非终结符号对应的下标 
	for(i=0;i<strlen(non_sign);i++){
		if(x==non_sign[i]){
			break;
		}
	}
	return i;
} 

int seek_ter(){//找到当前终结符号对应的下标 
	for(i=0;i<strlen(ter_sign);i++){
		if(a==ter_sign[i]){
			break;
		}
	}
	return i;
} 

void print_tip(char t){//输出信息,弹出栈顶元素,, 
	for(i=1;i<=top;i++){//符号栈 
		cout<<stack[i];
	} 
	cout<<'\t';
	cout<<'\t';
	cout<<a;//当前输入符号 
	cout<<'\t';
	for(i=j+1;i<=ex.size();i++){//输入串 
		cout<<ex[i];
	}
	cout<<'\t';
	cout<<"弹出栈顶符号"<<t; 
}
  • 16
    点赞
  • 161
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无言月梧桐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值