编译原理 算符优先
思路:
首先需要定义数据结构如下:
static struct Node2//用于构造算符优先算法
{
char Left;
char Right;
bool isfirstvt;
bool islastvt;
};
一个节点代表一个A->a这样的一个式子,left是非终结符,right为终结符。Isfirstvt为真是代表a是A的firstvt中的一员。Islastvt同理。
之后进行文法的扩展,与算符优先处理的初始化。如下:
GrammerSet[grammersetcount].Left = 'S';
GrammerSet[grammersetcount].RightCount = 1;
strcpy_s(GrammerSet[grammersetcount].Right[0], "#S#");
GrammerSet[grammersetcount].Right[0][1] = GrammerSet[0].Left;
grammersetcount++;
Non_Ter[nontercount++] = 'S';
TerSymbol[tersymbolcount++] = '#';
for (int i = 0; i < nontercount; i++)
{
for (int j = 0; j < tersymbolcount; j++)
{
Algorithm[algorithmcount].Left = Non_Ter[i];
Algorithm[algorithmcount].Right = TerSymbol[j];
//Algorithm[algorithmcount].isfirstvt = infirst(Algorithm[algorithmcount].Left, Algorithm[algorithmcount].Right);
//Algorithm[algorithmcount].islastvt = infollow(Algorithm[algorithmcount].Left, Algorithm[algorithmcount].Right);
Algorithm[algorithmcount].islastvt = false;
Algorithm[algorithmcount].isfirstvt = false;
algorithmcount++;
}
}
求firstvt
遍历所有产生式,如果P->Qa或者P->a则将a是P的firstvt中的一员,将代表其的节点中的isfirstvt设为true即可。现在我们已经将所有明显可见的数据求出来了,下面进行隐式推导中的firstvt计算。先将上面的道德isfirstvt为真的数据入栈,循环以下计算直到栈为空。
首先将栈顶弹出栈,记为Q->a,遍历所有产生式,找到P->Q这样的产生式,如果P->a的isfirstvt为flase,则将其置为true再入栈。
求lastvt
这个与firstvt一样的道理。我就不赘述了。
构造分析表
for 每个形如 P->X1X2…Xn的产生式 do
for i =1 to n-1 do
begin
if Xi和Xi+1都是终结符 then
Xi = Xi+1
if i<= n-2, Xi和Xi+2 是终结符, 但Xi+1 为非终结符 then
Xi = Xi+2
if Xi为终结符, Xi+1为非终结符 then
for FirstVT 中的每个元素 a do
Xi < a ;
if Xi为非终结符, Xi+1为终结符 then
for LastVT 中的每个元素 a do
a > Xi+1 ;
end
遍历所有产生式根据上面的四种情况进行填入即可。
构造总控程序
这个是这次实验的最重要的一部分。从输入串中读入一个字符到a中,然后找到栈中第一个非终结符的位置,之后我们要判断栈中是否含有可以进行规约的句柄,存在的标志就是当前栈顶的算符优先左大于a的算符优先,只要满足这个条件我们就可以进行规约,以下为规约步骤。寻找最左素短语,最左素短语的头在栈里面,它的算符优先是右大于(右优先)在栈里面比他更深的哪一个终结符,由此我们可以找到最左素短语的头。而最左素短语的尾巴在栈顶,定位了最左素短语就进行规约。遍历所有产生式,如果一个产生式与当前最左素短语终结符一一对应相等,非终结符一一对应但不一定需要相等,那么就将这个最左素短语规约为这条产生式的LEFT非终结符。规约完成后,我们又要进行判断栈中是否含有可以进行规约的句柄,这就保证了算法的正确性,不会导致规约过多或者过少。其实这就是算符优先的特点。当栈里面没有句柄之后,跳出这层循环,进行移进操作,将a移入栈中,不过这之前还要判断栈顶与a的优先关系,查表若没有定义则报错。否则正常移进栈中。a指向输入串的下一个字符。当a为“#”的时候就结束。结束之后,我们的栈中应该是“#A#”的样子。判断一下,如果不是就报错,否则输出正确。
完整代码:
//代码是前几天改的,现在我也忘了改了什么,就这样吧。
有没有精通计算机网络与3D场景渲染方面的大佬?有些问题想请教一下。
#pragma once
#ifndef ALGORITHM_PRIORITY_H
#define ALGORITHM_PRIORITY_H
#include <iostream>
#include <fstream>
#include <stack>
#include <map>
#include <iostream>
using namespace std;
static struct Node
{
char Left;
int RightCount;
char Right[100][100];
int FirstCount;
int FollowCount;
char First[100];
char Follow[100];
};
static struct Node2//用于构造算符优先算法
{
char Left;
char Right;
bool isfirstvt;
bool islastvt;
};
static Node2 Algorithm[100];
static Node GrammerSet[100];
int grammersetcount = 0;
int tersymbolcount = 0;//终结符数量
int nontercount = 0;//非终结符数量 默认第一个非终结符为开始符号
char TerSymbol[200];//终结符 非大写字母
char Non_Ter[200];//非终结符 大写字母
char AllSymbol[400];//所有符号
char AlgorithmTable[100][100];//算符优先表
char text[1000];//输入要处理的字符串
int algorithmcount = 0;
class Algorithm_Priority
{
public:
void Algorithm_Priority_main()
{
ReadGrammerSet();
initvt();
FirstVT();
LastVT();
CreateAlgorithmTable();
ShowAlgorithmTable();
AlgorithmMainControlProcess();
}
private:
void ShowGrammerSet(Node GrammerSet[])
{
for (int i = 0; i < grammersetcount; i++)
{
cout << i << " " << GrammerSet[i].Left << endl;
for (int j = 0; j < GrammerSet[i].RightCount; j++)
cout << j << " " << GrammerSet[i].Right[j] << endl;
}
cout << "非终结符的数量" << nontercount << endl;
cout << "非终结符" << endl;
for (int i = 0; i < nontercount; i++)
cout << Non_Ter[i] << " ";
cout << endl;
cout << "终结符的数量" << tersymbolcount << endl;
cout << "终结符" << endl;
for (int i = 0; i < tersymbolcount; i++)
cout << TerSymbol[i] << " ";
cout << endl;
for (int i = 0; i < grammersetcount; i++)
{
for (int j = 0; j < GrammerSet[i].RightCount; j++)
{
cout << GrammerSet[i].Left << "->" << GrammerSet[i].Right[j] << endl;
}
}
}
void ReadGrammerSet()
{
char str[100];
while (1)
{
cin >> str;
if (str[0] == '#')
break;
GrammerSet[grammersetcount].Left = str[0];
SymbolProcess(str[0]);//处理左边的
for (int i = 3; i < strlen(str); i++)
{
int j = 0;
char str2[100];
while ((str[i] != '|') && (str[i] != '\0'))
{
SymbolProcess(str[i]);//处理右边的
str2[j++] = str[i++];
}
str2[j] = '\0';
strcpy_s(GrammerSet[grammersetcount].Right[GrammerSet[grammersetcount].RightCount], str2);
GrammerSet[grammersetcount].RightCount++;
}
grammersetcount++;
}
}
bool isTerSymbol(char ch)
{
// cout << "正在判断"<<ch<<"是否为终结符" << endl;
if (ch >= 'A' && ch <= 'Z')
return false;
return true;
}
void SymbolProcess(char ch)
{
//非终结符
if (ch <= 'Z' && ch >= 'A')
{
int flag = 0;
for (int i = 0; i < nontercount; i++)
{
if (ch == Non_Ter[i])
{
flag = 1;
break;//已收录
}
}
if (flag == 0)
{
Non_Ter[nontercount++] = ch;
}
}
else//终结符
{
int flag = 0;
for (int i = 0; i < tersymbolcount; i++)
{
if (ch == TerSymbol[i])
{
flag = 1;
break;//已收录
}
}
if (flag == 0)
{
TerSymbol[tersymbolcount++] = ch;
}
}
}
//Algorithm Priority 算符优先
void initvt()
{
//扩展
GrammerSet[grammersetcount].Left = 'S';
GrammerSet[grammersetcount].RightCount = 1;
strcpy_s(GrammerSet[grammersetcount].Right[0], "#S#");
GrammerSet[grammersetcount].Right[0][1] = GrammerSet[0].Left;
grammersetcount++;
Non_Ter[nontercount++] = 'S';
TerSymbol[tersymbolcount++] = '#';
for (int i = 0; i < nontercount; i++)
{
for (int j = 0; j < tersymbolcount; j++)
{
Algorithm[algorithmcount].Left = Non_Ter[i];
Algorithm[algorithmcount].Right = TerSymbol[j];
//Algorithm[algorithmcount].isfirstvt = infirst(Algorithm[algorithmcount].Left, Algorithm[algorithmcount].Right);
//Algorithm[algorithmcount].islastvt = infollow(Algorithm[algorithmcount].Left, Algorithm[algorithmcount].Right);
Algorithm[algorithmcount].islastvt = false;
Algorithm[algorithmcount].isfirstvt = false;
algorithmcount++;
}
}
//cout << GrammerSet[grammersetcount - 1].Right[0] << endl;
cout << "vt初始化完成" << endl;
}
void FirstVT()
{
cout << "进行FirstVT" << endl;
//P->Qa P->a
for (int i = 0; i < grammersetcount; i++)
{
for (int j = 0; j < GrammerSet[i].RightCount; j++)
{
char P = GrammerSet[i].Left;
char x1 = GrammerSet[i].Right[j][0];
char x2 = GrammerSet[i].Right[j][1];
if (isTerSymbol(x1))//a
{
for (int k = 0; k < algorithmcount; k++)
{
if (Algorithm[k].Left == P && Algorithm[k].Right == x1)
{
Algorithm[k].isfirstvt = true;
}
}
}
if (!isTerSymbol(x1) && isTerSymbol(x2))//Qa
{
for (int k = 0; k < algorithmcount; k++)
{
if (Algorithm[k].Left == P && Algorithm[k].Right == x2)
{
Algorithm[k].isfirstvt = true;
}
}
}
}
}
cout << "开始进行栈操作" << endl;
stack<Node2>Stack;
for (int i = 0; i < algorithmcount; i++)
{
if (Algorithm[i].isfirstvt == true)
{
Stack.push(Algorithm[i]);
}
}
while (!Stack.empty())//循环至栈空
{
Node2 node1 = Stack.top();
Stack.pop();//Q->a
char Q = node1.Left;
char a = node1.Right;
for (int i = 0; i < grammersetcount; i++)
{
for (int j = 0; j < GrammerSet[i].RightCount; j++)
{
char P = GrammerSet[i].Left;
if (GrammerSet[i].Right[j][0] == node1.Left)//P->Q
{
int pos = 0;
for (pos = 0; pos < algorithmcount; pos++)
{
if (Algorithm[pos].Left == P && Algorithm[pos].Right == a)
{
break;
}
}
if (Algorithm[pos].isfirstvt == false)
{
Algorithm[pos].isfirstvt = true;
Stack.push(Algorithm[pos]);
}
}
}
}
}
//打印firstvt;
for (int i = 0; i < algorithmcount; i++)
{
if (Algorithm[i].isfirstvt == true)
{
cout << Algorithm[i].Left << ":" << Algorithm[i].Right << endl;;
}
}
}
void LastVT()
{
cout << "进行LastVT" << endl;
//P->......aQ P->.....a
for (int i = 0; i < grammersetcount; i++)
{
for (int j = 0; j < GrammerSet[i].RightCount; j++)
{
int length = strlen(GrammerSet[i].Right[j]);
char P = GrammerSet[i].Left;
char x1 = GrammerSet[i].Right[j][length - 1];
char x2 = GrammerSet[i].Right[j][length - 2];
if (isTerSymbol(x1))//......a
{
for (int k = 0; k < algorithmcount; k++)
{
if (Algorithm[k].Left == P && Algorithm[k].Right == x1)
{
Algorithm[k].islastvt = true;
}
}
}
if (!isTerSymbol(x1) && isTerSymbol(x2))//.....aQ
{
for (int k = 0; k < algorithmcount; k++)
{
if (Algorithm[k].Left == P && Algorithm[k].Right == x2)
{
Algorithm[k].islastvt = true;
}
}
}
}
}
cout << "开始进行栈操作" << endl;
stack<Node2>Stack;
for (int i = 0; i < algorithmcount; i++)
{
if (Algorithm[i].islastvt)
{
Stack.push(Algorithm[i]);
}
}
while (!Stack.empty())//循环至栈空
{
Node2 node1 = Stack.top();
Stack.pop();//Q->a
char Q = node1.Left;
char a = node1.Right;
for (int i = 0; i < grammersetcount; i++)
{
for (int j = 0; j < GrammerSet[i].RightCount; j++)
{
char P = GrammerSet[i].Left;
if (GrammerSet[i].Right[j][0] == node1.Left)//P->Q
{
int pos = 0;
for (pos = 0; pos < algorithmcount; pos++)
{
if (Algorithm[pos].Left == P && Algorithm[pos].Right == a)
{
break;
}
}
if (Algorithm[pos].islastvt == false)
{
Algorithm[pos].islastvt = true;
Stack.push(Algorithm[pos]);
}
}
}
}
}
//打印lastvt;
for (int i = 0; i < algorithmcount; i++)
{
if (Algorithm[i].islastvt == true)
{
cout << Algorithm[i].Left << ":" << Algorithm[i].Right << endl;;
}
}
}
bool infirstvt(char P, char a)
{
for (int i = 0; i < algorithmcount; i++)
{
if ((Algorithm[i].Left == P) && (Algorithm[i].Right == a))
return Algorithm[i].isfirstvt;
}
return false;
}
bool inlastvt(char P, char a)
{
for (int i = 0; i < algorithmcount; i++)
{
if ((Algorithm[i].Left == P) && (Algorithm[i].Right == a))
return Algorithm[i].islastvt;
}
return false;
}
void CreateAlgorithmTable()
{
for (int i = 1; i <= tersymbolcount; i++)
{
AlgorithmTable[i][0] = TerSymbol[i - 1];
AlgorithmTable[0][i] = TerSymbol[i - 1];
}
for (int i = 0; i < grammersetcount; i++)
{
for (int j = 0; j < GrammerSet[i].RightCount; j++)
{
for (int k = 0; k < strlen(GrammerSet[i].Right[j]) - 1; k++)
{
char x1 = GrammerSet[i].Right[j][k];
char x2 = GrammerSet[i].Right[j][k + 1];
//1
if (isTerSymbol(x1) && isTerSymbol(x2))
{
int pos1 = 0;
int pos2 = 0;
for (pos1 = 1; pos1 <= tersymbolcount; pos1++)
{
if (AlgorithmTable[pos1][0] == x1)
break;
}
for (pos2 = 1; pos2 <= tersymbolcount; pos2++)
{
if (AlgorithmTable[0][pos2] == x2)
break;
}
AlgorithmTable[pos1][pos2] = '=';
}
//2
if (isTerSymbol(x1) && !isTerSymbol(x2))
{
for (int r = 0; r < algorithmcount; r++)
{
if ((Algorithm[r].Left == x2) && (Algorithm[r].isfirstvt == true))
{
char ch = Algorithm[r].Right;
int pos1 = 0;
int pos2 = 0;
for (pos1 = 1; pos1 <= tersymbolcount; pos1++)
{
if (AlgorithmTable[pos1][0] == x1)
break;
}
for (pos2 = 1; pos2 <= tersymbolcount; pos2++)
{
if (AlgorithmTable[0][pos2] == ch)
break;
}
AlgorithmTable[pos1][pos2] = '<';
}
}
}
//3
if (!isTerSymbol(x1) && isTerSymbol(x2))
{
for (int r = 0; r < algorithmcount; r++)
{
if ((Algorithm[r].Left == x1) && (Algorithm[r].islastvt == true))
{
char ch = Algorithm[r].Right;
int pos1 = 0;
int pos2 = 0;
for (pos1 = 1; pos1 <= tersymbolcount; pos1++)
{
if (AlgorithmTable[pos1][0] == ch)
break;
}
for (pos2 = 1; pos2 <= tersymbolcount; pos2++)
{
if (AlgorithmTable[0][pos2] == x2)
break;
}
AlgorithmTable[pos1][pos2] = '>';
}
}
}
//4
if (k < strlen(GrammerSet[i].Right[j]) - 2)
{
char x1 = GrammerSet[i].Right[j][k];
char x3 = GrammerSet[i].Right[j][k + 1];
char x2 = GrammerSet[i].Right[j][k + 2];
if (isTerSymbol(x1) && isTerSymbol(x2) && !isTerSymbol(x3))
{
int pos1 = 0;
int pos2 = 0;
for (pos1 = 1; pos1 <= tersymbolcount; pos1++)
{
if (AlgorithmTable[pos1][0] == x1)
break;
}
for (pos2 = 1; pos2 <= tersymbolcount; pos2++)
{
if (AlgorithmTable[0][pos2] == x2)
break;
}
AlgorithmTable[pos1][pos2] = '=';
}
}
}
}
}
}
void ShowAlgorithmTable()
{
for (int i = 0; i <= tersymbolcount; i++)
{
cout << endl << endl;
for (int j = 0; j <= tersymbolcount; j++)
{
cout << AlgorithmTable[i][j] << " ";
}
}
}
void AlgorithmMainControlProcess()
{
cout << endl;
int pos = 0;
ifstream fin;
fin.open("test.txt");
while (!fin.eof())
{
text[pos++] = fin.get();
}
fin.close();
// cout << text << endl;;
pos = 0;
char s[100] = { '\0' };//分析栈
for (int i = 0; i < 100; i++)
s[i] = '\0';
int k = 1;
s[0] = '#';
s[1] = '#';
int j = 1;
char Q;
char a;
do {
a = text[pos++];//把下一个符号读进a
//找到栈中第一个非终结符的位置 用j指向这个非终结符
if (isTerSymbol(s[k]))
{
j = k;
}
else
{
j = k - 1;//算符优先文法中不可能存在两个相邻的非终结符
}
//寻找最左素短语
while (serchAlgorithmTable(s[j], a) == 1)//s[j]>a
{
//寻找最左素短语
while (1)
{
Q = s[j];
if (isTerSymbol(s[j - 1]))
{
j = j - 1;
}
else
{
j = j - 2;
}
if (serchAlgorithmTable(s[j], Q) == -1)
break;
}
for (int m = 0; m < grammersetcount; m++)
{
for (int n = 0; n < GrammerSet[m].RightCount; n++)
{
//遍历所有产生式
int pos1 = 0;
int pos2 = j + 1;
int flag = 1;
for (pos1 = 0; pos1 < strlen(GrammerSet[m].Right[n]); pos1++)
{
if (pos2 > k)
{
flag = 0;
break;
}
//终结符对应相等 非终结符只要都是非终结符就好
if ((GrammerSet[m].Right[n][pos1] == s[pos2]) || ((!isTerSymbol(s[pos2])) && (!isTerSymbol(GrammerSet[m].Right[n][pos1]))))
{
pos2++;
if ((pos2 > k) && (pos1 == strlen(GrammerSet[m].Right[n]) - 1))//匹配完成且成功
{
flag = 1;
pos2 = k;
break;
}
flag = 1;
}
else
{
pos2++;
flag = 0;
break;
}
}
if (pos2 != k)
flag = 0;
if (flag == 1)//匹配成功。可以规约
{
k = j + 1;
for (int i = j + 1; i < 100; i++)
s[i] = '\0';
s[k] = GrammerSet[m].Left;
cout << "规约成功-----" << GrammerSet[m].Left << endl;
break;
}
}
}
}
//移进
if ((serchAlgorithmTable(s[j], a) == -1) || (serchAlgorithmTable(s[j], a) == 0))
{
k++;
s[k] = a;
cout << "移进" << a << endl;
}
else
{
cout << "error" << endl;
return;
}
} while (a != '#');
if (s[3] == '#' && (!isTerSymbol(s[2])))
cout << "正确" << endl;
else cout << "error" << endl;
cout << s << endl;
}
int serchAlgorithmTable(char ch1, char ch2)
{
int flag = 9;//-1 0 1 分别代表 < = >
int pos1 = 0;
int pos2 = 0;
for (pos1 = 1; pos1 <= tersymbolcount; pos1++)
{
if (AlgorithmTable[pos1][0] == ch1)
break;
}
for (pos2 = 1; pos2 <= tersymbolcount; pos2++)
{
if (AlgorithmTable[0][pos2] == ch2)
break;
}
if (AlgorithmTable[pos1][pos2] == '=')
flag = 0;
if (AlgorithmTable[pos1][pos2] == '<')
flag = -1;
if (AlgorithmTable[pos1][pos2] == '>')
flag = 1;
return flag;
}
};
#endif