一、程序功能描述
本程序由C/C++编写,实现了:算符优先文法、最左素短语、算符优先矩阵、优先函程序等概念的定义及实例。
以专题 1 词法分析程序的输出为语法分析的输入,实现算符优先分析算法,完成以下描述算术表达式的算符优先文法的算符优先分析过程:
G[E]: E→E+T∣E-T∣T
T→T*F∣T/F∣F
F→(E)∣i
二、主要数据结构描述
关于具体的数据结构,主要使用了C语言的数组,其中字符数组运用最多,主要用于表示和存储Vn、Vt及FirstVt和LastVt的集合:
关于抽象的数据结构,则通过了一维数组实现了分析栈’stack’的数据结构,以用于算符优先的语法分析。此外,还用到了文件读写的相关数据结构及接口。
三、程序结构描述
除main函数外,本程序共定义了11个函数:
其中包含6个’find’函数,它们的功能相似,都是返回要查找字符在相应集合中的下标,否则返回-1;或者只是判断字符是否在First集或Last集中,无返回值,通过在数组中标记来维护算法。
‘add_to_VnVt’函数负责读取提供的文法规则,将其遍历,添加非终结符号和终结符号:
‘make_relation_table’函数负责构建算符优先关系矩阵。根据文法规则,判断终结符之间的关系,进而填充关系矩阵’Prior_rela’。下图的全局变量中,ll_cnt表示文法G[E]的条数,Prior_rela表示优先关系表,equation和alike用于装载从txt文件中读取到的字符串。
LAUNCH函数意味着数据装载和预处理已经完成,程序正式启动。它会输出一些提示信息,而后输出算符优先语法分析的结果,包括非终结符号集、终结符号集、文法的FirstVt集和LastVt集、优先关系矩阵。
analysis函数用于进行算符优先语法分析,通过算符优先关系表对输入的表达式进行分析,判断其是否符合文法规则。
四、程序测试
测试案例展示如下:
测试用例1:a*b*(c+d)-e+f/g
#include
#include
#include
#include
using namespace std;
const int N = 500;
char Vn[N];
char Vt[N];
char First_Vt[N][N];
char Last_Vt[N][N];
char G_E[N][N] = {
"E->E+T|E-T|T",
"T->T*F|T/F|F",
"F->(E)|i"
};
int ll_cnt = 3;
char Prior_rela[N][N];
char equation[N], alike[N];
int find_in_Vn(char c);
int find_in_Vt(char c);
int find_in_FirstVt(char c,int i);
int find_in_LastVt(char c,int i);
void find_in_FirstVt(char ll[N][N]);
void find_in_LastVt(char ll[N][N]);
void openFIle();
void make_relation_table(char LLL[N][N]);
void add_to_VnVt(char ll[N][N]);
void LAUNCH();
void analysis();
void openFIle() {
cout << "-------------------------------------------------------" << endl;
cout << "文件内容为:" << endl;
FILE* fp;
char buf[1000];
if ((fp = fopen("test1.txt", "r")) != NULL) {
while (fgets(buf, 1000, fp) != NULL)
{
int len = strlen(buf);
printf("%s \n", buf);
int flag = 0;
for (int i = 0; i < len; i++) {
if (buf[i] == '(' && flag == 0) {
flag = 1;
for (int j = i + 1; j < len; j++) {
if (buf[j] == ',') {
equation[strlen(equation)] = buf[j + 1];
if ((buf[j + 1] >= 'a' && buf[j + 1] <= 'z') ||
(buf[j + 1] >= 'A' && buf[j + 1] <= 'Z')) {
alike[strlen(alike)] += 'i';
}
else alike[strlen(alike)] = buf[j + 1];
i = j + 1;
break;
}
}
}
else if (flag == 1 && buf[i] == ')') {
flag = 0;
}
}
}
}
equation[strlen(equation)] = '#';
alike[strlen(alike)] = '#';
fclose(fp);
cout << "-------------------------------------------------------" << endl;
cout << "输入的语句为:" << equation << endl;
cout << "将其转化为:" << alike << endl;
cout << "-------------------------------------------------------" << endl;
}
void add_to_VnVt(char ll[N][N]) {
int Vn_index = 0;
int Vt_index = 0;
int temp = 0;
int temp1 = 0;
for (int i = 0; i < ll_cnt; i++) {
Vn[Vn_index] = ll[i][0];
Vn_index++;
}
for (int i = 0; i < ll_cnt; i++) {
for (int j = 3; j < strlen(ll[i]); j++) {
temp = 0;
for (int k = 0; k < strlen(Vn); k++) {
if (ll[i][j] == Vn[k] || ll[i][j] == '|' || ll[i][j] == 'N') {
temp = 1;
break;
}
}
if (temp == 0) {
temp1 = 0;
for (int k = 0; k < strlen(Vt); k++) {
if (ll[i][j] == Vt[k]) {
temp1 = 1;
break;
}
}
if (temp1 == 0) {
Vt[Vt_index] = ll[i][j];
Vt_index++;
}
}
}
}
Vt[strlen(Vt)] = '#';
}
int find_in_Vn(char c) {
int location = -1;
for (int i = 0; i < ll_cnt; i++) {
if (c == Vn[i]) {
location = i;
break;
}
}
return location;
}
int find_in_Vt(char c) {
int location = -1;
for (int i = 0; i < strlen(Vt); i++) {
if (c == Vt[i]) {
location = i;
break;
}
}
return location;
}
int find_in_FirstVt(char c, int i) {
int temp = -1;
for (int j = 0; j < strlen(First_Vt[i]); j++) {
if (First_Vt[i][j] == c) {
temp = j;
break;
}
}
return temp;
}
int find_in_LastVt(char c, int i) {
int temp = -1;
for (int j = 0; j < strlen(Last_Vt[i]); j++) {
if (Last_Vt[i][j] == c) {
temp = j;
break;
}
}
return temp;
}
void LAUNCH() {
cout << "*******************************************************" << endl;
cout << "算符优先语法分析设计" << endl;
cout << "非终结符号集(Vn)为:" << Vn << endl;
cout << "终结符号集(Vt)为:" << Vt << endl;
cout << "*******************************************************" << endl;
cout << "文法当前的FristVt集为:" << endl;
for (int i = 0; i < ll_cnt; i++) {
cout <= 0; i--) {
temp = 1;
for (int j = 3; j < strlen(ll[i]); j++) {
if (temp == 1) {
if (find_in_Vn(ll[i][j]) != -1) {
for (int k = 0; k < strlen(First_Vt[find_in_Vn(ll[i][j])]); k++) {
if (find_in_FirstVt(First_Vt[find_in_Vn(ll[i][j])][k], i) == -1) {
First_Vt[i][strlen(First_Vt[i])] = First_Vt[find_in_Vn(ll[i][j])][k];
}
}
}
}
temp = 0;
if (ll[i][j] == '|') {
temp = 1;
}
}
}
}
}
void find_in_LastVt(char ll[N][N]) {
for (int i = 0; i < ll_cnt; i++) {
for (int j = 3; j < strlen(ll[i]); j++) {
if (j==strlen(ll[i])-1 || ll[i][j+1]=='|') {
if (find_in_Vt(ll[i][j]) != -1) {
if (find_in_LastVt(ll[i][j], i) == -1) {
Last_Vt[i][strlen(Last_Vt[i])] = ll[i][j];
}
}
else {
if (find_in_Vt(ll[i][j-1])!=-1) {
if (find_in_LastVt(ll[i][j-1], i) == -1) {
Last_Vt[i][strlen(Last_Vt[i])] = ll[i][j - 1];
}
}
}
}
}
}
for (int w = 0; w < 2; w++) {
for (int i = ll_cnt - 1; i >= 0; i--) {
for (int j = 3; j < strlen(ll[i]); j++) {
if (j == strlen(ll[i])-1 || ll[i][j + 1] == '|') {
if (find_in_Vn(ll[i][j]) != -1) {
for (int k = 0; k < strlen(Last_Vt[find_in_Vn(ll[i][j])]); k++) {
if (find_in_LastVt(Last_Vt[find_in_Vn(ll[i][j])][k], i) == -1) {
Last_Vt[i][strlen(Last_Vt[i])] = Last_Vt[find_in_Vn(ll[i][j])][k];
}
}
}
}
}
}
}
}
void make_relation_table(char LLL[N][N]) {
char ll[N][N];
for (int i = 1; i < ll_cnt + 1; i++) {
strcpy(ll[i], LLL[i - 1]);
}
strcpy(ll[0],"S->#E#");
for (int i = 0; i < strlen(Vt); i++) {
for (int j = 0; j < strlen(Vt); j++) {
Prior_rela[i][j] = 'N';
}
}
for (int i = 0; i < ll_cnt+1; i++) {
for (int j = 3; j < strlen(ll[i]); j++) {
if (find_in_Vn(ll[i][j]) == -1 && ll[i][j] != '|') {
if (j < strlen(ll[i]) - 1) {
if (find_in_Vn(ll[i][j + 1]) == -1 && ll[i][j] != '|') {
Prior_rela[find_in_Vt(ll[i][j])][find_in_Vt(ll[i][j + 1])] = '=';
}
}
if (j < strlen(ll[i]) - 2) {
if (find_in_Vn(ll[i][j + 1]) != -1 && ll[i][j + 2] != '|' && find_in_Vn(ll[i][j + 2]) == -1) {
Prior_rela[find_in_Vt(ll[i][j])][find_in_Vt(ll[i][j + 2])] = '=';
}
}
}
if (j < strlen(ll[i]) - 1) {
if (find_in_Vn(ll[i][j]) == -1 && find_in_Vn(ll[i][j+1])!=-1 && ll[i][j]!='|') {
for (int k = 0; k < strlen(First_Vt[find_in_Vn(ll[i][j + 1])]); k++) {
Prior_rela[find_in_Vt(ll[i][j])][find_in_Vt(First_Vt[find_in_Vn(ll[i][j + 1])][k])] = '<';
}
}
else if (find_in_Vn(ll[i][j]) != -1 && find_in_Vn(ll[i][j + 1]) == -1 && ll[i][j+1] != '|') {
for (int k = 0; k < strlen(Last_Vt[find_in_Vn(ll[i][j])]); k++) {
Prior_rela[find_in_Vt(Last_Vt[find_in_Vn(ll[i][j])][k])][find_in_Vt(ll[i][j+1])] = '>';
}
}
}
}
}
}
void analysis() {
cout << " 分析栈" << " " << "语句" << endl;
char a1, a2;
int like_index = 0;
char stack[N];
char s[N];
int j;
char q;
int lengh;
int temp=1;
stack[like_index] = '#';
stack[1] = '\0';
for (int i = 0; i < strlen(alike); i++) {
temp = 1;
if (find_in_Vn(stack[strlen(stack)-1]) == -1) {
j = strlen(stack) - 1;
}
else j = strlen(stack) - 2;
if (Prior_rela[find_in_Vt(stack[j])][find_in_Vt(alike[i])] == '=') {
like_index = strlen(stack);
stack[like_index]=alike[i];
stack[like_index + 1] = '\0';
}
else if (Prior_rela[find_in_Vt(stack[j])][find_in_Vt(alike[i])] == '<') {
like_index = strlen(stack);
stack[like_index] = alike[i];
stack[like_index + 1] = '\0';
}
else if (Prior_rela[find_in_Vt(stack[j])][find_in_Vt(alike[i])] == '>') {
for (int y=0;;y++) {
for (;;) {
q = stack[j];
lengh = j;
if (j >= 1 && find_in_Vn(stack[j - 1]) == -1) {
j--;
}
else if (j >= 2) {
j = j - 2;
}
if (Prior_rela[find_in_Vt(stack[j])][find_in_Vt(q)] == '<') {
break;
}
}
stack[j + 1] = '\0';
like_index = strlen(stack);
stack[like_index] = 'E';
stack[like_index + 1] = '\0';
if (y == 0) {
for (int u = i; u < strlen(alike); u++) {
s[u - i] = alike[u];
lengh = u - i+1;
}
s[lengh] = '\0';
cout.width(10);
cout.unsetf(ios::left);
cout.fill(' ');
cout << stack;
cout << " " << s << endl;
}
like_index = strlen(stack);
stack[like_index] = alike[i];
stack[like_index + 1] = '\0';
for (int u = i; u < strlen(alike); u++) {
s[u - i] = alike[u];
lengh = u - i + 1;
}
cout.width(10);
cout.unsetf(ios::left);
cout.fill(' ');
s[lengh] = '\0';
cout << stack;
cout << " " << s << endl;
temp = 0;
if (strlen(stack) <= 2) { break; }
a1 = stack[strlen(stack) - 1];
if (find_in_Vn(stack[strlen(stack) - 2]) == -1) {
a2 = stack[strlen(stack) - 2];
}
else a2 = stack[strlen(stack) - 3];
if (Prior_rela[find_in_Vt(a2)][find_in_Vt(a1)] == '<' || Prior_rela[find_in_Vt(a2)][find_in_Vt(a1)] == '=') {
break;
}
}
}
else {
cout << "分析出错!" << endl;
break;
}
if (temp != 0) {
for (int u = i; u < strlen(alike); u++) {
s[u - i] = alike[u];
lengh = u - i + 1;
}
s[lengh] = '\0';
cout.width(10);
cout.unsetf(ios::left);
cout.fill(' ');
cout << stack;
cout<< " " << s << endl;
}
}
if (strcmp(stack, "#E#") == 0) {
cout << "分析成功!" << endl;
}
}
int main(void) {
add_to_VnVt(G_E);
find_in_FirstVt(G_E);
find_in_LastVt(G_E);
make_relation_table(G_E);
LAUNCH();
openFIle();
analysis();
return 0;
}