自上而下的语法分析:LL(1)文法分析

自上而下的语法分析:LL(1)文法分析

1.实验内容及要求

(1)根据给定文法,先求出First和Follow集合,构造预测分析表
(2)根据预测分析表分析给定表达式是否是该文法识别的正确的算术表达式(要求输出归约过程)
(3)假如给定表达式文法为:
E->TE’;
E’->+TE’|e;
T->FT’;
T’->*FT’|e;
F->(E)|i;
(4) 分析的句子可为:
(i+i)*i和i+i)*i

2.运行结果
在这里插入图片描述
在这里插入图片描述
3.实验代码

// QX.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <fstream>
#include <string>
using namespace std;


static int Len = 0;//记录文件中产生式的个数
static string Gen[50][50];//记录消除左递归后的产生式
static int Gen_num[50];//消除左递归后每个产生式中句子的个数

static char Vt[50];//记录终结符
static int len_vt = 0;//终结符的个数
static string Vn[50];//非终结符数组,因为存在E‘  所以需要设置为string类型
static int len_vn = 0;//非终结符的个数

static string First[50][50];//记录first集
static int len_first = 0;
static int num_Fi[50];

static string Follow[50][50];//记录follow集
static int len_follow = 0;
static int num_Fo[50];

static string Ana_Table[50][50] = { "" };
static char V[50];

static int arrx[50];//follow集中包含的元素

static int Mer[50][50];//记录first和follow的表格

bool IsVt(char c) {//判断是否为终结符/e(空集)
	for (int i = 0; i < len_vt; i++) {
		if (c == Vt[i] || c == 'e') {
			return true;
		}
	}
	return false;
}
bool IsVn(string s) {//判断是否为非终结符
	for (int i = 0; i < len_vn; i++) {
		if (s == Vn[i]) {
			return true;
		}
	}
	return false;
}
void Pretreatment(string arr[]) {//预处理程序
	for (int i = 0; i < Len; i++) {//遍历每行产生式
		int npc = 0;
		for (int j = 0; j < arr[i].length(); j++) {//遍历一行产生式的每个字符
			if (arr[i][j] == '-') {
				Gen[i][Gen_num[i]++] = arr[i].substr(npc, j - npc);
				Vn[len_vn++] = arr[i].substr(npc, j - npc);//取出非终结符
				npc = j + 2;
			}
			else if (arr[i][j] == '|' || arr[i][j] == ';') {
				Gen[i][Gen_num[i]++] = arr[i].substr(npc, j-npc);
				npc = j + 1;
			}
		}
	}

//取出终结符
	for (int i = 0; i < Len; i++) {
		for (int j = 1; j < Gen_num[i]; j++) {
			for (int k = 0; k < Gen[i][j].length(); k++) {
				if (Gen[i][j][k] != '\'' && !IsVt(Gen[i][j][k]) && !IsVn(Gen[i][j].substr(k, 1))) {
					Vt[len_vt++] = Gen[i][j][k];
				}
			}
			
		}
	}
}


bool Is(char c, int n) {
	for (int i = 0; i < num_Fi[n]; i++) {
		if (First[n][i][0] == c) {
			return true;
		}
	}
	return false;
}
void Cre_First() {//构建first集
	for (int i = 0; i < Len; i++) {
		First[len_first][num_Fi[len_first]++] = Gen[i][0];
		for (int j = 1; j < Gen_num[i]; j++) {
			if (Gen[i][j][0] != Gen[i][0][0] && !Is(Gen[i][j][0], i)) {//P->Q.. && Q不在P的first集中
				First[len_first][num_Fi[len_first]++] += Gen[i][j][0];
			}
		}
		len_first++;
	}
	int flag = 1;
	while (flag) {
		flag = 0;
		for (int i = 0; i < len_first; i++) {
			string arr[50];
			int len = 0;
			for (int j = 1; j < num_Fi[i]; j++) {
				if (IsVt(First[i][j][0])) {
					arr[len++] = First[i][j];
				}
				else {
					string str = First[i][j];
					for (int k = 0; k < len_first; k++) {
						if (str._Equal(First[k][0])) {
							for (int p = 1; p < num_Fi[k]; p++) {
								arr[len++] = First[k][p];
							}
							break;
						}
					}
				}
			}
			num_Fi[i] = 1;
			for (int j = 0; j < len; j++) {
				First[i][num_Fi[i]++] = arr[j];
			}
		}
		for (int i = 0; i < len_first; i++) {
			int npc = 0;
			for (int j = 1; j < num_Fi[i]; j++) {
				if (!IsVt(First[i][j][0])) {
					flag = 1;
					npc = 1;
					break;
				}
			}
			if (npc == 1) {
				break;
			}
		}
	}
	cout << "\n==========first集合:============\n" << endl;
	for (int i = 0; i < len_first; i++) {
		cout << "FIRST(" << First[i][0] << "):";
		for (int j = 1; j < num_Fi[i]; j++) {
			cout << First[i][j] << " ";
		}
		cout << endl;
	}
}

//=============求解follow用到
int FindSub(string c) {//follow中对应的下标
	for (int i = 0; i < Len; i++) {
		if (c._Equal(Gen[i][0])) {
			return i;
		}
	}
	return -1;
}
int FindSub_Vt(char c) {//找到终结符在终结符数组中的下标
	if (c == '#') {
		return len_vt;
	}
	for (int i = 0; i < len_vt; i++) {
		if (c == Vt[i])
			return i;
	}
	return -1;
}
void PrintFollow(bool arry[][50]) {//输出follow集
	cout << "\n==========follow集合:============\n" << endl;
	for (int i = 0; i < Len; i++) {
		cout << "follow(" << Gen[i][0] << "): ";
		Follow[len_follow][num_Fo[len_follow]++] = Gen[i][0];
		for (int j = 0; j < len_vt + 1; j++) {
			if (j == len_vt) {
				cout << "#" << " ";
				Follow[len_follow][num_Fo[len_follow]++] = "#";
			}
			else if (arry[i][j] == true) {
				cout << Vt[j] << " ";
				Follow[len_follow][num_Fo[len_follow]++] = Vt[j];
			}
		}
		len_follow++;
		cout << endl;
	}
	for (int i = 0; i < Len; i++) {
		for (int j = 0; j < len_vt + 1; j++) {
			if (arry[i][j] == true) {
				arrx[j] = 1;
			}
		}
	}
}
bool Exit_Fi(int n, char c) {
	string str(1, c);
	for (int i = 1; i < num_Fi[n]; i++) {
		if (str == First[n][i]) {
			return true;
		}
	}
	return false;
}
bool Exit_F0(int n, char c) {
	string str(1, c);
	for (int i = 1; i < num_Fo[n]; i++) {
		if (str == Follow[n][i]) {
			return true;
		}
	}
	return false;
}

void Print(bool arry[][50]) {
	cout << "\n\n=================First集 & Follow集=================\n";
	cout << "\t\t";
	char arr[50];

	for (int i = 0; i < len_vt; i++) {
		arr[i] = Vt[i];
	}
	arr[len_vt] = '#';
	arr[len_vt + 1] = 'e';//上表头有len+2元素
	for (int i = 0; i < len_vt + 2; i++) {
		cout << arr[i] << "\t";
	}
	cout << endl;
	for (int i = 0; i < len_first; i++) {
		cout << "First(" << First[i][0] << ")" << "\t";
		for (int j = 0; j < len_vt + 2; j++) {
			if (Exit_Fi(i, arr[j])) {
				cout << 1 << "\t";
			}
			else {
				cout << "-" << "\t";
			}
		}
		cout << endl;
	}
	for (int i = 0; i < len_first; i++) {
		cout << "Follow(" << First[i][0] << ")" << "\t";
		for (int j = 0; j < len_vt + 2; j++) {
			if (Exit_F0(i, arr[j])) {
				cout << 1 << "\t";
			}
			else {
				cout << "-" << "\t";
			}
		}
		cout << endl;
	}
}

void Cre_Follow() {//2020-5-27 终于写出来了,
	bool arry[50][50];
	for (int i = 0; i < Len; i++) {
		for (int j = 0; j < len_vt + 1; j++) {
			arry[i][j] = false;
		}
	}
	arry[0][len_vt] = true;
	for (int i = 0; i < Len; i++) {
		for (int j = 1; j < Gen_num[i]; j++) {
			int len = Gen[i][j].length();
			for (int k = 1; k < len; k++) {
				if (IsVt(Gen[i][j][k]) && !IsVt(Gen[i][j][k - 1])) {   //p->Qa   a加入follow(Q)
					string str = "";
					if (len > 2 && Gen[i][j][k - 1] == '\'') {
						str = Gen[i][j].substr(k - 2, 2);
					}
					else {
						str += Gen[i][j][k - 1];
					}
					int x = FindSub(str);
					int y = FindSub_Vt(Gen[i][j][k]);
					arry[x][y] = true;
				}
			}
		}
	}
	for (int i = 0; i < Len; i++) {
		for (int j = 1; j < Gen_num[i]; j++) {
			int len = Gen[i][j].length();
			for (int k = 0; k < len - 1; k++) {
				if (!IsVt(Gen[i][j][k]) && !IsVt(Gen[i][j][k + 1]) && Gen[i][j][k + 1] != '\'') {//P->..QW   first(W)-"e"  --->follow(Q)
					string str = "";
					if (k < len - 2 && Gen[i][j][k + 2] == '\'') {
						str = Gen[i][j].substr(k + 1, 2);
					}
					else {
						str += Gen[i][j][k + 1];
					}
					int y = FindSub(str);//  W  在消除左递归后的数组中所在的行下标
					str = "";
					if (k > 0 && Gen[i][j][k] == '\'') {
						str = Gen[i][j].substr(k - 1, 2);
					}
					else {
						str += Gen[i][j][k];
					}
					int x = FindSub(str);//  Q  在消除左递归后的数组中所在的行下标 
					for (int w = 1; w < num_Fi[y]; w++) {
						if (!First[y][w]._Equal("e")) {
							int m = FindSub_Vt(First[y][w][0]);
							arry[x][m] = true;
						}
					}
				}
			}
		}
	}
	for (int i = 0; i < Len; i++) {
		for (int j = 1; j < Gen_num[i]; j++) {
			int len = Gen[i][j].length();
			for (int k = 0; k < len; k++) {
				if (k == len - 1 && !IsVt(Gen[i][j][k])) {//最后一个元素   P->....Q||P->....Q'   follow(P)入follow(Q)
					string str = "";
					if (Gen[i][j][k] == '\'') {
						str = Gen[i][j].substr(k - 1, 2);
					}
					else {
						str += Gen[i][j][k];
					}
					int x = FindSub(str);//Q所在行
					int y = FindSub(Gen[i][0]);//P所在行
					for (int p = 0; p < len_vt + 1; p++) {
						if (arry[y][p]) {
							arry[x][p] = true;
						}
					}
				}
				else if (k < len - 1) {
					if (!IsVt(Gen[i][j][k]) && !IsVt(Gen[i][j][k + 1])) {
						string str = "";
						if (k < len - 2 && Gen[i][j][k + 2] == '\'') {
							str = Gen[i][j].substr(k + 1, 2);
						}
						else {
							str += Gen[i][j][k];
						}
						int t = FindSub(str);
						int flag = 0;
						for (int w = 1; w < num_Fi[t]; w++) {//判断是否包含空集
							if (First[t][w]._Equal("e")) {
								flag = 1;
								break;
							}
						}
						if (flag) {//包含空集
							str = "";
							if (Gen[i][j][k] == '\'') {
								str = Gen[i][j].substr(k - 1, 2);
							}
							else {
								str += Gen[i][j][k];
							}
							int x = FindSub(str);//Q所在行
							int y = FindSub(Gen[i][0]);//P所在行
							for (int p = 0; p < len_vt + 1; p++) {
								if (arry[y][p]) {
									arry[x][p] = true;
								}
							}
						}

					}
				}
			}
		}
	}
	PrintFollow(arry);
	Print(arry);
}


void Print_Table() {
	cout << "\n\n" << "\t";
	for (int i = 0; i < len_vt + 1; i++) {
		cout << V[i]<<"\t\t";
	}
	cout << endl;
	for (int i = 0; i < len_first; i++){
		cout << First[i][0] << "\t";
		for (int j = 0; j < len_vt + 1; j++) {
			if (Ana_Table[i][j] != "") {
				cout << Ana_Table[i][j] << "\t\t";
			}
			else {
				cout << ""<<"\t\t";
			}
		}
		cout << endl;
	}
}

int FindSub_V(char c) {
	for (int i = 0; i < len_vt + 1; i++) {
		if (c == V[i]) {
			return i;
		}
	}
	return -1;
}

void Cre_AnaTable() {
	for (int i = 0; i < len_vt; i++) {
		V[i] = Vt[i];
	}
	V[len_vt] = '#';
	for (int i = 0; i < len_first; i++) {
		for (int j = 1; j < num_Fi[i]; j++) {
			if (First[i][j][0] != 'e') {//该终结符  不为空
				int y = FindSub_V(First[i][j][0]);//该终结符所在的下标
				if (Gen_num[i] == 2) {//只有一个产生式后件
					Ana_Table[i][y] = Gen[i][0] + "->" + Gen[i][1];
				}
				else {//有多个产生式后件
					for (int k = 1; k < Gen_num[i]; k++) {
						if (Gen[i][k][0] == First[i][j][0]) {
							Ana_Table[i][y] = Gen[i][0] + "->" + Gen[i][k];
							break;
						}
					}
				}
			}
			else {//该终结符  为空
				for (int k = 1; k < num_Fo[i]; k++) {
					int y = FindSub_V(Follow[i][k][0]);
					Ana_Table[i][y] = Gen[i][0] + "->" + "e";
				}
			}
		}
	}
	Print_Table();
}


void Analysis(string str) {
	cout << "\n\n==========预测分析过程==========\n";
	string stack = "";
	stack += str[0]; 
	stack += Gen[0][0];
	str=str.substr(1, str.length() - 1);
	char a = str[0];
	bool flag = true;
	int npc = 0;
	cout << "步骤\t\t" << "符号栈\t\t" << "输入串\t\t" << "所用产生式" << endl;
	cout << npc << "\t\t" << stack << "\t\t" << str << "\t\t" << "" << "\n";
	while (flag) {
		npc++;
		char x = stack[stack.length() - 1];
		stack.erase(stack.length() - 1);
		if (IsVt(x)) {//栈顶元素为终结符
			if (x == a) {
				str=str.substr(1, str.length() - 1);
				a = str[0];
				cout << npc << "\t\t" << stack << "\t\t" << str << "\t\t" << "" << "\n";
			}
			else {
				cout << "error" << endl;
				break;
			}
		}
		else if (x == '#') {//栈顶元素位#
			if (x == a) {
				flag = false;
			}
			else {
				cout << "error" << endl;
				break;
			}
		}
		else{
			string s="";
			if (x == '\'') {
				s += stack[stack.length() - 1];
				s += x;
				stack.erase(stack.length() - 1);
			}
			else {
				s += x;
			}
			int m;
			for (int i = 0; i < Len; i++) {
				if (s == Gen[i][0]) {
					m = i;
					break;
				}
			}
			int n = FindSub_V(a);
			int len = Ana_Table[m][n].length();
			if (len == 0) {
				cout << "error" << endl;
			}
			else if (Ana_Table[m][n][len-1] != 'e') {
				for (int k = len - 1; k >= 0; k--) {
					if (Ana_Table[m][n][k] == '>') {
						break;
					}
					else if (Ana_Table[m][n][k] == '\'') {
						stack += Ana_Table[m][n].substr(k - 1, 2);
						k--;
					}
					else {
						stack += Ana_Table[m][n][k];
					}
				}
				cout << npc << "\t\t" << stack << "\t\t" << str << "\t\t" << Ana_Table[m][n] << "\n";
			}
			else {
				cout << npc << "\t\t" << stack << "\t\t" << str << "\t\t" << Ana_Table[m][n] << "\n";
			}
		}
		//cout << npc << "\t\t" << stack << "\t\t" << str << "\t\t" << "" << "\n";
	}
}




int main()
{
    string Pri[100];
	ifstream infile("Source.txt");
	if (!infile)
		cout << "error" << endl;
	int len = 0;//文件中产生式的个数
	while (infile.good()) {
		getline(infile, Pri[len++]);
	}//len=5
	cout << "==========从文件中读取到的产生式==========\n" << endl;
	for (int i = 0; i < len; i++) {
		cout << Pri[i] << endl;
	}
	Len = len;
	Pretreatment(Pri);
	Cre_First();
	Cre_Follow();
	Cre_AnaTable();
	string str;
	cout << "==========请输入产生式==========" << endl;
	cin >> str;//       #i*i+i#
	Analysis(str);
}

  • 4
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_码到成功_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值