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

📄 ll1.cpp

📁 LL1文法的实现
💻 CPP
字号:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
//===========================================================================================
typedef struct{
	char formule[6][15];			//用于存放产生式,从0到6对应+,*,(,),i,#;
	char word;						//用于存放非终结符
}Table;

typedef struct{						//定义栈(符号栈)
	char elem[20];					
	int top;
}SeqStack;

//==========================================================================================
char Letter[10];					 //定义全局变量,用来存放产生式里面出现的大写字母
char LessLetter[10];                 //存放产生式里面出现的终结符                  
int LetterNumber;	//存放非终结符的数目
int LessNumber;     //存放终结符的数目
int location;                        //存放express数组里的位置
int mark=0;							//作为标志位,mark=0 表示没有左递归 mark=1 表示存在左递归
char FIRST[10][15];					//存放非终结符的FIRST集合
char FOLLOW[10][15];				//存放非终结符的FOLLOW集合
int k1=0;
int step=0;                         //记录预测分析的步骤
SeqStack signStack;					//符号栈
//===========================================================================================
//函数声明
void Search(char express[][15],char a);
void First(char a[],char express[][15],int i,int s);
void Follow(char express[][15],char a);
//===========================================================================================
void init(char a[][15]){              //对数组进行初始化
	for(int i=0;i<10;i++)
		for(int j=0;j<15;j++)
			a[i][j]='\0';
}

void InitTable(Table analyse[]){//对预测分析表进行初始化
	int i,j,k;
	for(i=0;i<5;i++)
		for(j=0;j<6;j++)
			for(k=0;k<15;k++){
				analyse[i].word=' ';
				analyse[i].formule[j][k]='\0';
			}
}

void InitSeqStack(){				//对符号栈进行初始化
	int i;
	for(i=0;i<20;i++)
		signStack.elem[i]='\0';
	signStack.top=-1;
}
				
void input(char temp[][15],int number){
	for(int i=0;i<number;i++){
		printf("\n请输入第%d个产生式:",i+1);
		scanf("%s",temp[i]);
	}
}

void output(char temp[][15],int number){
	for(int i=0;i<number;i++)
		printf("%s\n",temp[i]);
}

bool IsLetter(char a){
	if((a<='Z')&&(a>='A'))
		return true;
	else
		return false;
}

bool judge(char a){					//判断字母a是否出现在终结字母表中
	int i;
	for(i=0;i<10;i++)
		if(a==Letter[i])
			return false;
	return true;
}

bool judgement(char a){				//判断字母a是否出现在终结字母表中
	int i; 
	for(i=0;i<10;i++)
		if(a==LessLetter[i])
			return false;
	return true;
}

void MakeLetter(char temp[][15],int number){  //生成非终结符字母表
	int i,j;
	for(i=0;i<number;i++)
		for(j=0;j<15;j++){
			if(IsLetter(temp[i][j])){//判断是否为非终结字符
				if(judge(temp[i][j]))
					Letter[LetterNumber++]=temp[i][j];
			}
		}
		Letter[LetterNumber]='\0';
}

void MakeLessLetter(char temp[][15],int number){			//生成终结符字母表
	int i,j;
	for(i=0;i<number;i++)
		for(j=3;j<15;j++){
			if(!IsLetter(temp[i][j])&&temp[i][j]!='|'){
				if(judgement(temp[i][j]))
					LessLetter[LessNumber++]=temp[i][j];
			}
		}
		LessLetter[LessNumber++]='#';
		LessLetter[LessNumber]='\0';
}

char DefineLetter(){						//查看还有那个大写字母没有在字母表中出现
	for(char ch='A';ch<='Z';ch++)
			if(judge(ch)){
				Letter[LetterNumber++]=ch;
				return ch;
			}
	return 'Z';
}

void remove(char temp[],int number,char express[][15]){   //消除左递归
	int i,j,r,k,t;
	char ch;
	for(i=0;i<15;i++)
		if(temp[i]=='|'){
			r=i;
			for(j=r+1;j<15;j++)
				if(temp[j]=='|'||temp[j]=='\0'){
					k=j;
					break;
				}
		}
	ch=DefineLetter();
	for(i=0;i<3;i++)
		express[location][i]=temp[i];
	for(t=r+1;t<k;t++)
		express[location][i++]=temp[t];
	express[location][i]=ch;
	location++;
	express[location][0]=ch;
	express[location][1]='-';
	express[location][2]='>';
	i=3;
	for(j=4;j<r;j++)
		express[location][i++]=temp[j];
	express[location][i++]=ch;
	express[location][i++]='|';
	express[location][i++]='@';
	location++;
	
}
		
void manage(char temp[][15],int number,char express[][15]){
	int i,j,t;
	int flag[10];      //作为标志位,flag=0 表示没有左递归 flag=1 表示存在左递归
	for(i=0;i<number;i++)
		flag[i]=0;//付初值,没有左递归
	for(i=0;i<number;i++)
		for(j=3;j<15;j++){
			if(temp[i][0]==temp[i][j]){//如果有左递归
				flag[i]=1;
				mark=1;
				t=j;
				remove(temp[i],number,express);
			}
		}//////////////////////////////////////////////////////////////////////////
		for(i=0;i<number;i++){
			if(flag[i]==0){
				for(j=0;j<15;j++)
					express[location][j]=temp[i][j];
				location++;
			}
		}
}

void Search(char express[][15],char a,int j){
	int i;
	for(i=0;i<location;i++)
		if(express[i][0]==a)
			First(express[i],express,i,j);
}

void First(char a[],char express[][15],int i,int s){						//求FIRST集合
	int j,k=0,t;
	if(IsLetter(a[3]))
		Search(express,a[3],s);
	else{
		FIRST[s][k++]=a[3];
		for(j=3;j<15;j++)
			if(a[j]=='|')
				FIRST[s][k++]=a[j+1];
		FIRST[s][k]='\0';
	}
	if(i!=s){	//表示求左递归时候进行了递归运算,即产生式右边第一个是非终结符
		for(t=0;t<15;t++)
			if(FIRST[s][t]=='@')
				First(a,express,i,s);
	}
}

void outFIRST(char express[][15]){						//将FIRST集合输出到屏幕上
	int i,j,k=0;
	printf("\nFIRST集合如下:\n");
	for(i=0;i<location;i++){
		printf("FIRST(%c)={",express[i][0]);
		for(j=0;j<15;j++)
			if(FIRST[i][j+1]=='\0'){
			printf("%c}\n",FIRST[i][j]);
			break;
			}
			else
				printf("%c,",FIRST[i][j]);
	
	}
}

bool estimate(char a[],char b){					//判断字母b是否在数组a中
	for(int i=0;i<15;i++)
		if(b==a[i])
			return true;
	return false;
}

void addFollow(int i,int j){						//将FOLLOW[i]加到FOLLOW[j]中
	int a;
	for(a=0;a<15;a++)
		if(!estimate(FOLLOW[j],FOLLOW[i][a]))
			FOLLOW[j][k1++]=FOLLOW[i][a];
}

void Solve(char express[][15],char a[],int p,int j){	
	int i,t,r,temp;
	k1=0;
	if(a[j+1]=='\0'){			//若FOLLOW[p]已经求出,则直接加入到FOLLOW[a[j]]中
		if(FOLLOW[p][0]!='\0'){
			for(int r=0;r<location;r++)
				if(express[r][0]==a[j]){
					temp=r;
					break;
				}
				addFollow(p,temp);
		}
		else
			Follow(express,express[p][0]);			//若FOLLOW[p]还没有求出,则先求出FOLLOW[p];
	}
	else if(!IsLetter(a[j+1])&&a[j+1]!='|'){
		if(a[j]==express[0][0]){
			k1++;
			FOLLOW[0][k1++]=a[j+1];
		}
		else{
			for(r=0;r<location;r++)
				if(express[r][0]==a[j]){
					FOLLOW[r][k1++]=a[j+1];
					break;
				}
		}
	}
	else if(IsLetter(a[j+1])){
		for(i=0;i<location;i++)
			if(express[i][0]==a[j+1]){
				for(int s=0;s<15;s++){
					if(express[i][s]=='@'&&express[i][s-1]=='|')	//若非终结符能直接推出@
						if(	FOLLOW[i][0]!='\0'){
							for(int r=0;r<location;r++)
								if(express[r][0]==a[j]){
									temp=r;
									break;
								}
							addFollow(i,temp);
						}
						else
							Follow(express,express[i][0]);
				}									          
				for(t=0;t<15;t++)				//将FIRST[a[j+1]]加入到FOLLOW[i]中    
					if(!estimate(FOLLOW[temp],FIRST[i][t]))
						if(FIRST[i][t]!='@')
							FOLLOW[temp][k1++]=FIRST[i][t];
			}
	}

}

void Follow(char express[][15],char a){					//求FOLLOW集合
	int i,j;
	if(a==express[0][0])				//若为开始符号则把#号加入到FOLLOW集合中
		FOLLOW[0][0]='#';
	for(i=0;i<location;i++)
		for(j=3;j<15;j++)
			if(express[i][j]==a&&express[i][0]!=a){
				Solve(express,express[i],i,j);
			}
}

void outFOLLOW(char express[][15]){						//将FIRST集合输出到屏幕上
	int i,j,k=0;
	printf("\nFOLLOW集合如下:\n");
	for(i=0;i<location;i++){
		printf("FOLLOW(%c)={",express[i][0]);
		for(j=0;j<15;j++)
			if(FOLLOW[i][j+1]=='\0'){
			printf("%c}\n",FOLLOW[i][j]);
			break;
			}
			else
				printf("%c,",FOLLOW[i][j]);
	
	}
}

bool opinion(char a,int i){							//判断字母a是否出现在FIRST集合中
	int j;
	for(j=0;j<15;j++)
		if(a==FIRST[i][j])
				return true;
	return false;
}

bool judgeFollow(char a,int i){					//判断字母a是否出现在FOLLOW集合中
	int j,k;
	for(j=0;j<15;j++)
		if(FIRST[i][j]=='@'){
			for(k=0;k<15;k++)
				if(a==FOLLOW[i][k])
					return true;
		}
	return false;
}
	
int Creat(Table &tab,char express[],int j){					//将产生式放入分析表中
	int i;
	tab.word=express[0];
	for(i=0;i<15;i++)
		if(express[i]=='|')
			if(express[i+1]==LessLetter[j]){
					tab.formule[j][0]=express[0];
					tab.formule[j][1]='-';
					tab.formule[j][2]='>';
					tab.formule[j][3]=LessLetter[j];
					return 1;
				}
	for(i=0;i<15;i++){
		if(express[i]!='|')
			tab.formule[j][i]=express[i];
		else
			break;
	}
	return 0;
}

void CreatTable(Table analyse[],char express[][15]){				//构造预测分析表
	int i,j;
	for(i=0;i<location;i++)
		for(j=0;j<LessNumber;j++)
			if(opinion(LessLetter[j],i))
				Creat(analyse[i],express[i],j);
			else{
				if(judgeFollow(LessLetter[j],i)){
					analyse[i].formule[j][0]=express[i][0];
					analyse[i].formule[j][1]='-';
					analyse[i].formule[j][2]='>';
					analyse[i].formule[j][3]='@';
				}
			}			
}

void outTable(Table analyse[]){				//输出预测分析表
	int i,j;
	printf("\n预测分析表如下:\n");
	for(j=0;j<LessNumber;j++)
		printf("\t%c",LessLetter[j]);
	printf("\n");
	for(i=0;i<5;i++){
		printf("%c\t",analyse[i].word);
		for(j=0;j<6;j++)
			printf("%s\t",analyse[i].formule[j]);
		printf("\n");
	}
}

bool judgeStack(char a){				//判断字母a与符号栈顶元素是否相同
	if(signStack.elem[signStack.top]==a)
		return true;
	return false;
}

int settle(char bunch[],Table analyse[],char express[][15]){
	int i,j,t,s,r;
	int flag=0;
	for(i=0;i<location;i++)
		if(express[i][0]==signStack.elem[signStack.top]){
			j=i;
			break;
		}
	if(judgeStack(bunch[0])&&bunch[0]=='#')			//如果符号栈顶为'#'且输入串也为'#'号时候结束,分析成功了。
		return 1;
	else if(judgeStack(bunch[0])){					//如果符号栈顶和输入串第一位相同,则把符号栈的栈顶元素弹出,且输入串第一位也删除
		for(i=0;i<10;i++)
			bunch[i-1]=bunch[i];
		signStack.elem[signStack.top]='\0';
		signStack.top--;
		printf("%d\t%s\t%s\t\n",step++,signStack.elem,bunch);
	}
	
	else{
			
			for(t=0;t<LessNumber;t++){
				if(bunch[0]==LessLetter[t]){
					s=t;
					if(analyse[j].formule[s][3]=='@'){					//如果对应的产生式为X->@,则直接把栈顶元素弹出,输入串不变
							signStack.elem[signStack.top]='\0';
							signStack.top--;
							flag=1;
							break;
						}
					else{
						for(r=15;r>=3;r--){						//找到符号栈顶和输入串第一位对应的产生式,将产生式右部反序压入到符号栈中
							if(analyse[j].formule[s][r]!='\0'){
								signStack.elem[signStack.top]=analyse[j].formule[s][r];
								signStack.top++;
							}
						}
					}
					if(flag==0)
						signStack.top--;
					break;
				}
			}
		printf("%d\t%s\t%s\t%s\n",step++,signStack.elem,bunch,analyse[j].formule[s]);
	}
	return 0;
	
}
	
void inputString(char bunch[],Table analyse[],char express[][15]){
	int i,j,k;
	printf("\n请输入要分析的句子:\n");
	scanf("%s",bunch);
	printf("\n利用预测分析表进行预测分析的步骤如下:\n");
	signStack.top++;   
	signStack.elem[signStack.top]='#';			//首先将'#'号压入符号栈
	signStack.top++;
	signStack.elem[signStack.top]=express[0][0];	//将开始符号压入栈顶
	printf("步骤\t符号栈\t输入串\t所用产生式\n");
	printf("%d\t%s\t%s\t\n",step++,signStack.elem,bunch);	//找到开始符号和输入串第一位对应的产生式,将产生式右部反序压入到符号栈中
	for(i=0;i<LessNumber;i++){
		if(LessLetter[i]==bunch[0]){
			j=i;
			for(k=15;k>=3;k--)
				if(analyse[0].formule[j][k]!='\0'){
					signStack.elem[signStack.top]=analyse[0].formule[j][k];
					signStack.top++;
				}
		}
	}
	printf("%d\t%s\t%s\t%s\n",step++,signStack.elem,bunch,analyse[0].formule[j]);
	signStack.top--;
	while(signStack.elem[signStack.top]!='#')
		settle(bunch,analyse,express);
	printf("分析成功!\n");
	
}
	
	
int main(){
	char temp[10][15];
	char express[10][15];
	int number; //记录文法里面产生式的个数
	int i;
	char bunch[10];	//存放输入串
	for(i=0;i<10;i++)
		bunch[i]='\0';
	Table analyse[5];		//存放预测分析表
	init(temp);
	init(express);
	init(FIRST);
	init(FOLLOW);
	InitTable(analyse);
	InitSeqStack();
	printf("\n**********************LL(1)文法的实现**************************\n");
	for(i=0;i<10;i++)
		Letter[i]='\0';//用来存放产生式里面出现的大写字母
	printf("\n请输入文法里面的产生式个数:");
	scanf("%d",&number);
	input(temp,number);//输入文法规则
	MakeLetter(temp,number);//存储非终结字符
	MakeLessLetter(temp,number);//存储终结字符
	manage(temp,number,express);//消除左递归
	if(mark==1){
		printf("\n文法存在左递归!\n");
		printf("消除左递归后的文法如下:\n");
		output(express,location);
	}
	for(i=0;i<location;i++)
		First(express[i],express,i,i);
	for(i=0;i<location;i++)
		Follow(express,express[i][0]);
	outFIRST(express);
	outFOLLOW(express);
	CreatTable(analyse,express);
	outTable(analyse);
	inputString(bunch,analyse,express);
	return 1;
}

⌨️ 快捷键说明

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