自上而下的语法分析: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);
}